All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.regnosys.rosetta.translate.BackwardCompatibilityGenerator.xtend Maven / Gradle / Ivy

There is a newer version: 11.25.1
Show newest version
package com.regnosys.rosetta.translate

import java.util.Map

/**
 * Generator provides backward compatibility for models stuck on earlier model versions.
 */
class BackwardCompatibilityGenerator {
	
	def Map generate() {
		val map = newHashMap
		
		// remove once bundle version 10.6.0 is no longer used
		map.put('com/regnosys/rosetta/translate/ROMParseHandler',
			'''
			package com.regnosys.rosetta.translate;
			
			import static com.regnosys.rosetta.translate.GeneratorPathUtil.anyMatch;
			import static com.regnosys.rosetta.translate.GeneratorPathUtil.matches;
			
			import java.util.Arrays;
			import java.util.Collection;
			import java.util.HashMap;
			import java.util.Iterator;
			import java.util.List;
			import java.util.Map;
			import java.util.Optional;
			import java.util.Set;
			import java.util.function.Consumer;
			import java.util.function.Predicate;
			import java.util.function.Supplier;
			import java.util.stream.Collectors;
			
			import org.slf4j.Logger;
			import org.slf4j.LoggerFactory;
			
			import com.google.common.collect.Multimap;
			import com.google.inject.Injector;
			import com.regnosys.rosetta.common.translation.MappingContext;
			import com.regnosys.rosetta.common.translation.MappingProcessor;
			import com.regnosys.rosetta.common.translation.Path;
			import com.regnosys.rosetta.translate.basic.BasicParseHandler;
			import com.rosetta.model.lib.RosettaModelObjectBuilder;
			import com.rosetta.model.lib.path.RosettaPath;
			
			/**
			 * Generated by the ROMParseHandler
			 * 
			 * RosettaModelObject parse handler.
			 * 
			 * Note: ROM is a misspelt acronym for Rosetta Model Object.
			 */
			public abstract class ROMParseHandler extends ParseHandler {
			
				private static final Logger LOGGER = LoggerFactory.getLogger(ROMParseHandler.class);
				
				private final Map> conditionPathCache = new HashMap<>();
				
			    public static  
			    		void evaluateConditionalPaths(ROMParseHandler rmoXmlParseHandler,
			                                          HandlerCache underlyers,
			                                          Consumer> setter,
			                                          Collection path) {
			    	rmoXmlParseHandler.evaluateConditionalPaths(underlyers, setter, path);
			    }
			
			    protected final Injector injector;
			    protected final MappingContext mappingContext;
			    protected Multimap, HandlerSupplier> handlers;
			    protected Multimap, MappingProcessorSupplier> mappingProcessors;
			
			    private T underlying;
			
			    public ROMParseHandler(Injector injector, MappingContext mappingContext) {
			        this.rosettaPath = new Path();
			        this.injector = injector;
			        this.mappingContext = mappingContext;
			    }
			
			    public T getUnderlying() {
			        return underlying;
			    }
			
			    public void setUnderlying(T underlying) {
			        this.underlying = underlying;
			    }
			
			    @SuppressWarnings("unchecked")
			    protected > H findOrNew(HandlerCache underlyers,
																										  String attribute,
																										  Path fullPath,
																										  Supplier supplier) {
			        return (H) underlyers.getOrCreateHandler(attribute, fullPath, supplier);
			    }
			
			    protected List toStrings(Path path) {
			        return path.getElements().stream()
			                .map(p -> p.getPathName())
			                .collect(Collectors.toList());
			    }
			
			    public Collection> getMappingProcessorForPath(Path localPath,
																												 Path parentPath,
																												 MappingContext mappingContext) {
			        return mappingProcessors.get(toStrings(localPath)).stream()
							.map(mp -> mp.apply(parentPath, mappingContext))
							.collect(Collectors.toList());
			    }
			
			    public Collection> getMappingProcessorMatchPaths() {
			        return mappingProcessors.keySet();
			    }
			
			    public Collection> getHandlerMatchPaths() {
			        return handlers.keySet();
			    }
			
			    public Collection getHandlersForPath(Path localPath, Path parentPath) {
			        return handlers.get(toStrings(localPath)).stream()
			                .map(h -> h.apply(localPath, parentPath))
			                .collect(Collectors.toList());
			    }
			
			    protected  H useOrNew(H handlerField, Supplier supplier) {
			        if (handlerField == null) {
			            H handler = supplier.get();
			            return handler;
			        }
			        return handlerField;
			    }
			
			    protected  void evaluateConditionalPaths(HandlerCache underlyers,
			                                                                                  Consumer> setter,
			                                                                                  Collection conditionalPaths) {
			        evaluateConditionalPaths(underlyers, setter, conditionalPaths, a -> true);
			    }
			
			    protected  void evaluateConditionalPaths(ROMParseHandler underlyer,
			                                                                                  Set xmlPathsToHere,
			                                                                                  Consumer> setter,
			                                                                                  List conditionalPaths) {
			        evaluateConditionalPaths(underlyer, xmlPathsToHere, setter, conditionalPaths.stream()
			        		.map(p -> Path.parse(p))
			        		.collect(Collectors.toList()), a -> true);
			    }
			
			    protected  void evaluateConditionalPaths(HandlerCache underlyers,
			                                                                                  Consumer> setter,
			                                                                                  Collection conditionalPaths,
			                                                                                  Predicate> additionalTest) {
			        for (ROMParseHandler handler : underlyers.getAllHandlers()) {
			            if (matches(handler.getXmlPathsToHere(), conditionalPaths) && additionalTest.test(handler.getXmlPathsToHere())) {
			                setter.accept(handler);
			            }
			        }
			    }
			
			    protected  void evaluateConditionalPaths(ROMParseHandler handler,
			                                                                                  Set xmlPathsToHere,
			                                                                                  Consumer> setter,
			                                                                                  List conditionalPaths,
			                                                                                  Predicate> additionalTest) {
			
			        if (handler != null && xmlPathsToHere.stream().anyMatch(p -> anyMatch(p, conditionalPaths)) && additionalTest.test(handler.getXmlPathsToHere())) {
			            setter.accept(handler);
			        }
			    }
			
			    protected  void useConditionalCache(BasicParseHandler handler, Path path, Map values) {
			        handler.setParentSetter(v -> values.put(path, v));
			        handler.setParentSupplier(() -> Optional.ofNullable(values.get(path)));
			    }
			
			    protected boolean areEqual(String a, String b) {
			        if (a == null) return b == null;
			        return a.equals(b);
			    }
			
			    protected boolean areEqual(String a, Boolean b) {
			        if (a == null) return b == null;
			        return Boolean.valueOf(a).equals(b);
			    }
			
			    protected boolean areEqual(Boolean b, String a) {
			        return areEqual(a, b);
			    }
			
			    protected boolean areEqual(String a, Integer b) {
			        if (a == null) return b == null;
			        return Integer.valueOf(a).equals(b);
			    }
			
			    protected boolean areEqual(Integer b, String a) {
			        return areEqual(a, b);
			    }
			
			    protected static class AnonHandler extends ROMParseHandler {
			        public AnonHandler(Injector injector, MappingContext mappingContext, Path rosettaPath, T underlying) {
			            super(injector, mappingContext);
			            this.rosettaPath = rosettaPath;
			            setUnderlying(underlying);
			        }
			    }
			
			    protected int getMappingListIndex(Collection listAttribute, List mergeSynonyms) {
			        if (!mergeSynonyms.isEmpty()) {
			            // Merge (e.g. map onto same list item, rather than create new list item), unless excluded path
			            List excludedPathElements = mergeSynonyms.stream()
			                    .map(MergeSynonymValue::getExcludePath)
			                    .collect(Collectors.toList());
			            boolean excludedPath = getXmlPathsToHere().stream()
			                    .flatMap(synPath -> synPath.getElements().stream())
			                    .map(Path.PathElement::getPathName)
			                    .anyMatch(pathElementName -> excludedPathElements.contains(pathElementName));
			            // If excluded, use index of the list size (e.g. map on to a new list item at the end of the list)
			            // If included, use index of the list size minus one (e.g. map on to the last existing item of the list)
			            return Math.max(0, sizeOf(listAttribute) - (excludedPath ? 0 : 1));
			        }
			        // if not merge synonym is specified then always create a new list item
			        return sizeOf(listAttribute);
			    }
			
			    /**
			     * I'm not sure if getting the last path is the correct thing to do, but there should be only one path for this.
			     *
			     * @param synonymPaths - the synonym paths to this attribute (not including what is inside [synonym value="..."]
			     * @param synonymValue - the synonym path specified inside the attribute synonym [synonym value="..."] - dot separated string representing path
			     * @return the last synonym path and the synonym value combined
			     */
			    protected String getSynonymPathForConditionFunc(Set synonymPaths, String synonymValue) {
			        Iterator iterator = synonymPaths.iterator();
			        Path lastPath = null;
			        while (iterator.hasNext()) {
			            lastPath = iterator.next();
			        }
			        if (lastPath != null) {
			            Path fullPath = lastPath.append(Path.parse(synonymValue));
			            return formatPathWithNoIndexesAndSeparators(fullPath);
			        }
			        return ""; // top level
			    }
			
			    protected String formatPathWithNoIndexesAndSeparators(Path path) {
			        return path.getElements().stream()
			                .map(e -> e.getPathName())
			                .collect(Collectors.joining("->"));
			    }
			
			    // for backwards compatibility
			    protected String getValueFromConditionPath(String... conditionPathEndsWith) {
			    	return Optional.ofNullable(getValuesFromConditionPath(conditionPathEndsWith))
			    			.flatMap(values -> values.stream().findFirst())
			    			.orElse(null);
			    }
			    
			    protected List getValuesFromConditionPath(String... conditionPathEndsWith) {
			    	if (conditionPathEndsWith == null || conditionPathEndsWith.length == 0) {
			    		return null;
			    	}
			    	String conditionPathEndsWithAsStr = Arrays.toString(conditionPathEndsWith);
			    	return conditionPathCache.computeIfAbsent(Arrays.toString(conditionPathEndsWith), key -> {
			    		List values = mappingContext.getMappings().stream()
							.filter(m -> m.getXmlValue() != null)
							.filter(m -> m.getXmlPath().endsWith(conditionPathEndsWith))
							.map(m -> m.getXmlValue())
							.map(o -> String.valueOf(o))
							.distinct()
							.collect(Collectors.toList());
			    		LOGGER.debug("Condition-func path {} found values {}", conditionPathEndsWithAsStr, values);
			    		return values;
			    	});
			    }
			    
				public Injector getInjector() {
					return injector;
				}
			
				public MappingContext getMappingContext() {
					return mappingContext;
				}
			}


			''')

		return map
	}
}