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 }