AnyGene.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-5.2.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;
021 
022 import static java.util.Objects.requireNonNull;
023 import static io.jenetics.internal.util.Hashes.hash;
024 import static io.jenetics.util.RandomRegistry.random;
025 
026 import java.util.Objects;
027 import java.util.function.Predicate;
028 import java.util.function.Supplier;
029 
030 import io.jenetics.internal.math.Randoms;
031 import io.jenetics.util.ISeq;
032 import io.jenetics.util.IntRange;
033 import io.jenetics.util.MSeq;
034 
035 /**
036  * {@code Gene} implementation, which allows to create genes without explicit
037  * implementing the {@code Gene} interface.
038  *
039  <pre>{@code
040  * class Main {
041  *     // First monday of 2015.
042  *     private static final LocalDate MIN_MONDAY = LocalDate.of(2015, 1, 5);
043  *
044  *     // Supplier of random 'LocalDate' objects. The implementation is responsible
045  *     // for guaranteeing the desired allele restriction. In this case we will
046  *     // generate only mondays.
047  *     static LocalDate nextRandomMonday() {
048  *         return MIN_MONDAY.plusWeeks(RandomRegistry.getRandom().nextInt(1000));
049  *     }
050  *
051  *     // Create a new 'LocalDate' gene. All other genes, created with
052  *     // gene.newInstance(), are calling the 'newRandomMonday' method.
053  *     final AnyGene<LocalDate> gene = AnyGene.of(Main::nextRandomMonday);
054  * }
055  * }</pre>
056  * The example above shows how to create {@code LocalDate} genes from a random
057  * {@code LocalDate} supplier. It also shows how to implement a restriction on
058  * the created dates. The usage of the {@code AnyGene} class is useful for
059  * supporting custom allele types without explicit implementation of the
060  * {@code Gene} interface. But the {@code AnyGene} can only be used for a subset
061  * of the existing alterers.
062  *
063  @see AnyChromosome
064  *
065  * @implNote
066  * This class is immutable and thread-safe.
067  *
068  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
069  @version 3.3
070  @since 3.3
071  */
072 public final class AnyGene<A> implements Gene<A, AnyGene<A>> {
073 
074     private final A _allele;
075     private final Supplier<? extends A> _supplier;
076     private final Predicate<? super A> _validator;
077 
078     private AnyGene(
079         final A allele,
080         final Supplier<? extends A> supplier,
081         final Predicate<? super A> validator
082     ) {
083         _allele = allele;
084         _supplier = requireNonNull(supplier);
085         _validator = requireNonNull(validator);
086     }
087 
088     @Deprecated
089     @Override
090     public A getAllele() {
091         return _allele;
092     }
093 
094     @Override
095     public AnyGene<A> newInstance() {
096         return new AnyGene<>(_supplier.get(), _supplier, _validator);
097     }
098 
099     @Override
100     public AnyGene<A> newInstance(final A value) {
101         return new AnyGene<>(value, _supplier, _validator);
102     }
103 
104     @Override
105     public boolean isValid() {
106         return _validator.test(_allele);
107     }
108 
109     @Override
110     public int hashCode() {
111         return hash(_allele, hash(AnyGene.class));
112     }
113 
114     @Override
115     public boolean equals(final Object obj) {
116         return obj == this ||
117             obj instanceof AnyGene &&
118             Objects.equals(((AnyGene)obj)._allele, _allele);
119     }
120 
121     @Override
122     public String toString() {
123         return Objects.toString(_allele);
124     }
125 
126 
127     /* *************************************************************************
128      *  Static factory methods.
129      * ************************************************************************/
130 
131     /**
132      * Create a new {@code AnyGene} instance with the given parameters. New
133      * (random) genes are created with the given allele {@code supplier}.
134      *
135      @param <A> the allele type
136      @param allele the actual allele instance the created gene represents.
137      *        {@code null} values are allowed.
138      @param supplier the allele-supplier which is used for creating new,
139      *        random alleles
140      @param validator the validator used for validating the created gene. This
141      *        predicate is used in the {@link #isValid()} method.
142      @return a new {@code AnyGene} with the given parameters
143      @throws NullPointerException if the {@code supplier} or {@code validator}
144      *         is {@code null}
145      */
146     public static <A> AnyGene<A> of(
147         final A allele,
148         final Supplier<? extends A> supplier,
149         final Predicate<? super A> validator
150     ) {
151         return new AnyGene<>(allele, supplier, validator);
152     }
153 
154     /**
155      * Create a new {@code AnyGene} instance with the given parameters. New
156      * (random) genes are created with the given allele {@code supplier}. The
157      * {@code validator} predicate of the generated gene will always return
158      * {@code true}.
159      *
160      @param <A> the allele type
161      @param allele the actual allele instance the created gene represents.
162      *        {@code null} values are allowed.
163      @param supplier the allele-supplier which is used for creating new,
164      *        random alleles
165      @return a new {@code AnyGene} with the given parameters
166      @throws NullPointerException if the {@code suppler} is {@code null}
167      */
168     public static <A> AnyGene<A> of(
169         final A allele,
170         final Supplier<? extends A> supplier
171     ) {
172         return new AnyGene<>(allele, supplier, a -> true);
173     }
174 
175     /**
176      * Create a new {@code AnyGene} instance with the given allele
177      * {@code supplier}. The {@code validator} predicate of the generated gene
178      * will always return {@code true}.
179      *
180      @param <A> the allele type
181      @param supplier the allele-supplier which is used for creating new,
182      *        random alleles
183      @return a new {@code AnyGene} with the given parameters
184      @throws NullPointerException if one of the parameters is {@code null}
185      */
186     public static <A> AnyGene<A> of(final Supplier<? extends A> supplier) {
187         return new AnyGene<>(supplier.get(), supplier, a -> true);
188     }
189 
190     /**
191      * Create a new {@code AnyGene} instance with the given parameters. New
192      * (random) genes are created with the given allele {@code supplier}.
193      *
194      @param <A> the allele type
195      @param supplier the allele-supplier which is used for creating new,
196      *        random alleles
197      @param validator the validator used for validating the created gene. This
198      *        predicate is used in the {@link #isValid()} method.
199      @return a new {@code AnyGene} with the given parameters
200      @throws NullPointerException if one of the parameters is {@code null}
201      */
202     public static <A> AnyGene<A> of(
203         final Supplier<? extends A> supplier,
204         final Predicate<? super A> validator
205     ) {
206         return new AnyGene<>(supplier.get(), supplier, validator);
207     }
208 
209     // Create gene sequence.
210     static <A> ISeq<AnyGene<A>> seq(
211         final IntRange lengthRange,
212         final Supplier<? extends A> supplier,
213         final Predicate<? super A> validator
214     ) {
215         return MSeq.<AnyGene<A>>ofLength(Randoms.nextInt(lengthRange, random()))
216             .fill(() -> of(supplier.get(), supplier, validator))
217             .toISeq();
218     }
219 
220 }