1 package net.bmahe.genetics4j.gp;
2
3 import java.util.Arrays;
4 import java.util.Objects;
5 import java.util.function.BiFunction;
6 import java.util.function.Function;
7 import java.util.function.Supplier;
8
9 import org.apache.commons.lang3.Validate;
10
11 import net.bmahe.genetics4j.gp.math.ImmutableCoefficientOperation;
12 import net.bmahe.genetics4j.gp.math.ImmutableCoefficientOperation.Builder;
13
14 public final class OperationFactories {
15
16 private OperationFactories() {
17 }
18
19 @SuppressWarnings("rawtypes")
20 public static OperationFactory ofOperationSupplier(final Class[] acceptedTypes, final Class returnedType,
21 final Supplier<Operation> buildSupplier) {
22 Objects.requireNonNull(acceptedTypes);
23 Objects.requireNonNull(returnedType);
24 Objects.requireNonNull(buildSupplier);
25
26 return new OperationFactory() {
27
28 @Override
29 public Class returnedType() {
30 return returnedType;
31 }
32
33 @Override
34 public Class[] acceptedTypes() {
35 return acceptedTypes;
36 }
37
38 @Override
39 public Operation build(final InputSpec inputSpec) {
40 return buildSupplier.get();
41 }
42 };
43 }
44
45 @SuppressWarnings("rawtypes")
46 public static OperationFactory of(final Class[] acceptedTypes, final Class returnedType,
47 final Function<InputSpec, Operation> operationBuilder) {
48 Objects.requireNonNull(acceptedTypes);
49 Objects.requireNonNull(returnedType);
50 Objects.requireNonNull(operationBuilder);
51
52 return new OperationFactory() {
53 @Override
54 public Class[] acceptedTypes() {
55 return acceptedTypes;
56 }
57
58 @Override
59 public Class returnedType() {
60 return returnedType;
61 }
62
63 @Override
64 public Operation build(final InputSpec inputSpec) {
65 return operationBuilder.apply(inputSpec);
66 }
67 };
68 }
69
70 @SuppressWarnings("rawtypes")
71 public static OperationFactory of(final String name, final Class[] acceptedTypes, final Class returnedType,
72 final BiFunction<Object[], Object[], Object> compute) {
73 Validate.notBlank(name);
74 Objects.requireNonNull(acceptedTypes);
75 Objects.requireNonNull(returnedType);
76 Objects.requireNonNull(compute);
77
78 return new OperationFactory() {
79
80 @Override
81 public Class[] acceptedTypes() {
82 return acceptedTypes;
83 }
84
85 @Override
86 public Class returnedType() {
87 return returnedType;
88 }
89
90 @Override
91 public Operation build(final InputSpec inputSpec) {
92 return ImmutableOperation.of(name, Arrays.asList(acceptedTypes), returnedType, compute);
93 }
94 };
95 }
96
97 @SuppressWarnings("rawtypes")
98 public static OperationFactory ofCoefficient(final String name, final Class returnedType, final Object value) {
99 Validate.notBlank(name);
100 Objects.requireNonNull(returnedType);
101 Objects.requireNonNull(value);
102
103 return new OperationFactory() {
104
105 @Override
106 public Class[] acceptedTypes() {
107 return new Class[] {};
108 }
109
110 @Override
111 public Class returnedType() {
112 return returnedType;
113 }
114
115 @Override
116 public Operation build(final InputSpec inputSpec) {
117 final Builder<Object> operationBuilder = ImmutableCoefficientOperation.builder();
118
119 operationBuilder.name(name)
120 .value(value)
121 .returnedType(returnedType)
122 .prettyName(name + "[" + value + "]");
123
124 return operationBuilder.build();
125 }
126 };
127 }
128
129 public static <T> OperationFactory ofTerminal(final String name, final Class<T> returnedType,
130 final Supplier<T> compute) {
131 Validate.notBlank(name);
132 Objects.requireNonNull(returnedType);
133 Objects.requireNonNull(compute);
134
135 return of(name, new Class[] {}, returnedType, (input, parameter) -> {
136 return compute.get();
137 });
138 }
139
140 public static <T, U> OperationFactory ofUnary(final String name, final Class<T> acceptedType,
141 final Class<U> returnedType, final Function<T, U> compute) {
142 Validate.notBlank(name);
143 Objects.requireNonNull(acceptedType);
144 Objects.requireNonNull(returnedType);
145 Objects.requireNonNull(compute);
146
147 return of(name, new Class[] { acceptedType }, returnedType, (input, parameters) -> {
148 Objects.requireNonNull(parameters);
149
150 final Object parameter1 = parameters[0];
151 Objects.requireNonNull(parameter1);
152 Validate.isInstanceOf(acceptedType, parameter1);
153
154 @SuppressWarnings("unchecked")
155 final T operand = (T) parameter1;
156
157 return compute.apply(operand);
158 });
159 }
160
161 @SuppressWarnings("unchecked")
162 public static <T, U, V> OperationFactory ofBinary(final String name, final Class<T> acceptedType1,
163 final Class<U> acceptedType2, final Class<V> returnedType, final BiFunction<T, U, V> compute) {
164 Validate.notBlank(name);
165 Objects.requireNonNull(acceptedType1);
166 Objects.requireNonNull(acceptedType2);
167 Objects.requireNonNull(returnedType);
168 Objects.requireNonNull(compute);
169
170 return of(name, new Class[] { acceptedType1, acceptedType2 }, returnedType, (input, parameters) -> {
171 Objects.requireNonNull(parameters);
172
173 final Object parameter1 = parameters[0];
174 Objects.requireNonNull(parameter1);
175 Validate.isInstanceOf(acceptedType1, parameter1);
176 final T operand1 = (T) parameter1;
177
178 final Object parameter2 = parameters[1];
179 Objects.requireNonNull(parameter2);
180 Validate.isInstanceOf(acceptedType2, parameter2);
181 final U operand2 = (U) parameter2;
182
183 return compute.apply(operand1, operand2);
184 });
185 }
186 }