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