package org.finra.datagenerator.scaffolding.transformer.service; import org.finra.datagenerator.scaffolding.transformer.TransformDirection; import org.finra.datagenerator.scaffolding.transformer.function.FunctionTransformation; import org.finra.datagenerator.scaffolding.transformer.service.TransformationsProvider$; import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.atomic.AtomicLong; import java.util.function.Predicate; import java.util.stream.Collectors; /** * Created by dkopel on 11/17/16. */ public class TransformationContext { public final Long iteration; public final Map<Long, java.util.Collection<TransformationContainer>> containers; public final Set<FunctionTransformationContainer> functionTransformations; public final Map<Predicate<TransformationContext>, Set<OutputOverride<?>>> overrides = new HashMap(); public final TransformationSessionType sessionType; Class<?> currentClass; Object currentInstance; Field field; public TransformationContext(Long iteration, Map<Long, java.util.Collection<TransformationContainer>> containers, Set<FunctionTransformationContainer> functionTransformations, TransformationSessionType sessionType, Map<Predicate<TransformationContext>, Set<OutputOverride<?>>> overrides) { this.iteration = iteration; this.containers = containers; this.functionTransformations = functionTransformations; this.overrides.putAll(overrides); this.sessionType = sessionType; } public TransformationContext(Long iteration, Map<Long, java.util.Collection<TransformationContainer>> containers, Set<FunctionTransformationContainer> functionTransformations) { this(iteration, containers, functionTransformations, TransformationsProvider$.MODULE$.defaultSessionType(), new HashMap<>()); } public <S> void setCurrentInstance(S inst) { this.currentInstance = inst; } public <S> void setCurrentClass(Class<S> clazz) { this.currentClass = clazz; } public Long getIteration() { return iteration; } public Boolean hasFunctionTransformation(String key, Class<? extends FunctionTransformation> clazz) { return functionTransformations .stream() .filter(ft -> ft.key.equals(key) && ft.clazz.equals(clazz)) .count() > 0; } public Boolean hasFunctionTransformation(Class<? extends FunctionTransformation> clazz) { return functionTransformations .stream() .filter(ft -> ft.clazz.equals(clazz)) .count() > 0; } public Set<OutputOverride<?>> getOutputOverrides(Class clazz) { return overrides.entrySet() .stream() .filter(e -> e.getKey().test(this)) .flatMap(e -> e.getValue().stream() .filter(o -> o.clazz.equals(clazz))) .collect(Collectors.toSet()); } public Optional<OutputOverride<?>> getCurrentOutputOverride() { return getOutputOverrides(currentClass).stream() .filter(oo -> field.getName().equals(oo.field) && oo.condition.test(this)) .findFirst(); } public boolean hasOverrides() { return getCurrentOutputOverride().isPresent(); } public OutputOverride<?> getOutputOverride(Class clazz, Field field) { if(overrides.containsKey(iteration)) { Set<OutputOverride> os = overrides.get(iteration).stream() .filter(o -> o.clazz.equals(clazz) && o.field.equals(field)) .collect(Collectors.toSet()); if(os.size() > 0) { return os.iterator().next(); } } return null; } public TransformationContext addTransformationContainer(final TransformationContainer container) { List<TransformationContainer> cs = getCurrentIteration().stream() .filter(c -> !container.alias.equals(c.alias) && !container.clazz.equals(c.clazz)) .collect(Collectors.toList()); cs.add(container); this.containers.put(iteration, cs); return this; } public Map<String, Class> getAliases() { return containers.entrySet() .stream() .flatMap(e -> e.getValue().stream()) .filter(c -> c instanceof InputTransformationContainer) .collect(Collectors.toMap( c -> c.alias, c -> c.clazz )); } public Object getIteration(Long iteration, String alias) { TransformationContainer tc = containers.getOrDefault(iteration, new ArrayList<>()) .stream() .filter(i -> i.alias.equals(alias)) .findFirst() .orElse(null); return (tc != null && tc.value != null) ? tc.value : null; } public List<TransformationContainer> getCurrentIteration() { return containers.getOrDefault(iteration, new ArrayList<>()) .stream() .sorted() .collect(Collectors.toList()); } public <T> T getPreviousByClass(Class<T> clazz) { return (T) containers.getOrDefault(iteration-1L, new HashSet<TransformationContainer>()) .stream() .filter(i -> i.clazz.equals(clazz)) .findFirst() .orElse(null); } public List<TransformationContainer> getIterationOutputs() { return getCurrentIteration() .stream() .filter(i -> i.direction.equals(TransformDirection.OUTPUT)) .collect(Collectors.toList()); } public Set<TransformationContainer> getIterationInputs() { return getCurrentIteration() .stream() .filter(i -> i.direction.equals(TransformDirection.INPUT)) .collect(Collectors.toSet()); } public Set<FunctionTransformationContainer> getFunctionTransformations() { return functionTransformations; } public Map<Predicate<TransformationContext>, Set<OutputOverride<?>>> getOverrides() { return overrides; } public <T> Class<T> getCurrentClass() { return (Class<T>) currentClass; } public <T> T getCurrentInstance() { return (T) currentInstance; } public static Map<Long, Collection<TransformationContainer>> convert(Map<Long, List<TransformationContainer>> inputs) { final AtomicLong l = new AtomicLong(); return inputs .entrySet() .stream() .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue().stream() .map(c -> { if(c.direction == TransformDirection.INPUT) { return new InputTransformationContainer(c.alias, c.clazz, c.value, l.getAndIncrement()); } else { return new OutputTransformationContainer(c.alias, c.clazz, c.value, l.getAndIncrement()); } }) .collect(Collectors.toList()) ) ); } }