EphemeralConst.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-6.1.0).
003  * Copyright (c) 2007-2020 Franz Wilhelmstötter
004  *
005  * Licensed under the Apache License, Version 2.0 (the "License");
006  * you may not use this file except in compliance with the License.
007  * You may obtain a copy of the License at
008  *
009  *      http://www.apache.org/licenses/LICENSE-2.0
010  *
011  * Unless required by applicable law or agreed to in writing, software
012  * distributed under the License is distributed on an "AS IS" BASIS,
013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014  * See the License for the specific language governing permissions and
015  * limitations under the License.
016  *
017  * Author:
018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019  */
020 package io.jenetics.prog.op;
021 
022 import static java.lang.String.format;
023 import static java.util.Objects.requireNonNull;
024 import static io.jenetics.internal.util.SerialIO.readNullableString;
025 import static io.jenetics.internal.util.SerialIO.writeNullableString;
026 
027 import java.io.IOException;
028 import java.io.InvalidObjectException;
029 import java.io.ObjectInput;
030 import java.io.ObjectInputStream;
031 import java.io.ObjectOutput;
032 import java.io.Serializable;
033 import java.util.Objects;
034 import java.util.function.Supplier;
035 
036 import io.jenetics.internal.util.Lazy;
037 
038 /**
039  * Implementation of an <em>ephemeral</em> constant. It causes the insertion of
040  * a <em>mutable</em> constant into the operation tree. Every time this terminal
041  * is chosen a, different value is generated which is then used for that
042  * particular terminal, and which will remain fixed for the given tree. The main
043  * usage would be to introduce random terminal values.
044  *
045  <pre>{@code
046  * final Random random = ...;
047  * final Op<Double> val = EphemeralConst.of(random::nextDouble);
048  * }</pre>
049  *
050  <b>Serialization</b>
051  * Although the {@code EphemeralConst} class implements the {@link Serializable}
052  * interface, the serialization will fail if the <em>const</em> supplier is not
053  <em>serializable</em> as well. This can be achieved by <em>casting</em> the
054  * supplier to a {@link Serializable}.
055  <pre>{@code
056  * final Random random = new Random();
057  * final EphemeralConst<Integer> object = EphemeralConst.of(
058  *     "R",
059  *     (Supplier<Integer> & Serializable)random::nextInt
060  * );
061  * }</pre>
062  * The serialization of the <em>constant</em> will fail, if the lambda has to
063  * capture variables form a <em>non</em>-serializable context (class). In such a
064  * case it is advisable to create a dedicated supplier class.
065  <pre>{@code
066  * final class RandomInt implements Supplier<Integer>, Serializable {
067  *     private final Random rnd = new Random();
068  *     private final int min;
069  *     private final int max;
070  *
071  *     private RandomInt(final int min, final int max) {
072  *         this.min = min;
073  *         this.max = max;
074  *     }
075  *
076  *     \@Override
077  *     public Integer get() {
078  *         return rnd.nextInt(max - min) + min;
079  *     }
080  * }
081  * }</pre>
082  *
083  *
084  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
085  @version 5.0
086  @since 3.9
087  */
088 public final class EphemeralConst<T>
089     extends Val<T>
090     implements Op<T>, Serializable
091 {
092 
093     private static final long serialVersionUID = 1L;
094 
095     private final Lazy<T> _value;
096     private final Supplier<T> _supplier;
097 
098     private EphemeralConst(
099         final String name,
100         final Lazy<T> value,
101         final Supplier<T> supplier
102     ) {
103         super(name);
104         _value = requireNonNull(value);
105         _supplier = requireNonNull(supplier);
106     }
107 
108     private EphemeralConst(final String name, final Supplier<T> supplier) {
109         this(name, Lazy.of(supplier), supplier);
110     }
111 
112     /**
113      * Return a newly created, uninitialized constant of type {@code T}.
114      *
115      @return a newly created, uninitialized constant of type {@code T}
116      */
117     @Override
118     public Op<T> get() {
119         return new EphemeralConst<>(name(), _supplier);
120     }
121 
122     /**
123      * Fixes and returns the constant value.
124      *
125      @since 5.0
126      *
127      @return the constant value
128      */
129     @Override
130     public T value() {
131         return _value.get();
132     }
133 
134     @Override
135     public String toString() {
136         return name() != null
137             ? format("%s(%s)", name(), value())
138             : Objects.toString(value());
139     }
140 
141     /**
142      * Create a new ephemeral constant with the given {@code name} and value
143      * {@code supplier}. For every newly created operation tree, a new constant
144      * value is chosen for this terminal operation. The value is than kept
145      * constant for this tree.
146      *
147      @param name the name of the ephemeral constant
148      @param supplier the value supplier
149      @param <T> the constant type
150      @return a new ephemeral constant
151      @throws NullPointerException if one of the arguments is {@code null}
152      */
153     public static <T> EphemeralConst<T> of(
154         final String name,
155         final Supplier<T> supplier
156     ) {
157         return new EphemeralConst<>(requireNonNull(name), supplier);
158     }
159 
160     /**
161      * Create a new ephemeral constant with the given value {@code supplier}.
162      * For every newly created operation tree, a new constant value is chosen
163      * for this terminal operation. The value is than kept constant for this tree.
164      *
165      @param supplier the value supplier
166      @param <T> the constant type
167      @return a new ephemeral constant
168      @throws NullPointerException if the {@code supplier} is {@code null}
169      */
170     public static <T> EphemeralConst<T> of(final Supplier<T> supplier) {
171         return new EphemeralConst<>(null, supplier);
172     }
173 
174 
175     /* *************************************************************************
176      *  Java object serialization
177      * ************************************************************************/
178 
179     private Object writeReplace() {
180         return new Serial(Serial.EPHEMERAL_CONST, this);
181     }
182 
183     private void readObject(final ObjectInputStream stream)
184         throws InvalidObjectException
185     {
186         throw new InvalidObjectException("Serialization proxy required.");
187     }
188 
189     void write(final ObjectOutput outthrows IOException {
190         writeNullableString(name(), out);
191         out.writeObject(value());
192         out.writeObject(_supplier);
193     }
194 
195     @SuppressWarnings({"unchecked""rawtypes"})
196     static EphemeralConst read(final ObjectInput in)
197         throws IOException, ClassNotFoundException
198     {
199         final String name = readNullableString(in);
200         final Object value = in.readObject();
201         final Supplier supplier = (Supplier)in.readObject();
202 
203         return new EphemeralConst(name, Lazy.ofValue(value), supplier);
204     }
205 
206 }