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