View Javadoc
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).value(value).returnedType(returnedType).prettyName(name + "[" + value + "]");
120 
121 				return operationBuilder.build();
122 			}
123 		};
124 	}
125 
126 	public static <T> OperationFactory ofTerminal(final String name, final Class<T> returnedType,
127 			final Supplier<T> compute) {
128 		Validate.notBlank(name);
129 		Objects.requireNonNull(returnedType);
130 		Objects.requireNonNull(compute);
131 
132 		return of(name, new Class[] {}, returnedType, (input, parameter) -> {
133 			return compute.get();
134 		});
135 	}
136 
137 	public static <T, U> OperationFactory ofUnary(final String name, final Class<T> acceptedType,
138 			final Class<U> returnedType, final Function<T, U> compute) {
139 		Validate.notBlank(name);
140 		Objects.requireNonNull(acceptedType);
141 		Objects.requireNonNull(returnedType);
142 		Objects.requireNonNull(compute);
143 
144 		return of(name, new Class[] { acceptedType }, returnedType, (input, parameters) -> {
145 			Objects.requireNonNull(parameters);
146 
147 			final Object parameter1 = parameters[0];
148 			Objects.requireNonNull(parameter1);
149 			Validate.isInstanceOf(acceptedType, parameter1);
150 
151 			@SuppressWarnings("unchecked")
152 			final T operand = (T) parameter1;
153 
154 			return compute.apply(operand);
155 		});
156 	}
157 
158 	@SuppressWarnings("unchecked")
159 	public static <T, U, V> OperationFactory ofBinary(final String name, final Class<T> acceptedType1,
160 			final Class<U> acceptedType2, final Class<V> returnedType, final BiFunction<T, U, V> compute) {
161 		Validate.notBlank(name);
162 		Objects.requireNonNull(acceptedType1);
163 		Objects.requireNonNull(acceptedType2);
164 		Objects.requireNonNull(returnedType);
165 		Objects.requireNonNull(compute);
166 
167 		return of(name, new Class[] { acceptedType1, acceptedType2 }, returnedType, (input, parameters) -> {
168 			Objects.requireNonNull(parameters);
169 
170 			final Object parameter1 = parameters[0];
171 			Objects.requireNonNull(parameter1);
172 			Validate.isInstanceOf(acceptedType1, parameter1);
173 			final T operand1 = (T) parameter1;
174 
175 			final Object parameter2 = parameters[1];
176 			Objects.requireNonNull(parameter2);
177 			Validate.isInstanceOf(acceptedType2, parameter2);
178 			final U operand2 = (U) parameter2;
179 
180 			return compute.apply(operand1, operand2);
181 		});
182 	}
183 }