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

com.regnosys.rosetta.translate.util.SchemaMerge Maven / Gradle / Ivy

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

import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.regnosys.rosetta.common.util.UrlUtils;
import com.regnosys.rosetta.translate.datamodel.Attribute;
import com.regnosys.rosetta.translate.datamodel.AttributeImpl;
import com.regnosys.rosetta.translate.datamodel.Cardinality;
import com.regnosys.rosetta.translate.datamodel.Entity;
import com.regnosys.rosetta.translate.datamodel.EntityImpl;
import com.regnosys.rosetta.translate.datamodel.ModelParser;
import com.regnosys.rosetta.translate.datamodel.NamespaceName;
import com.regnosys.rosetta.translate.datamodel.Schema;
import com.regnosys.rosetta.translate.datamodel.SchemaSerialise;
import com.regnosys.rosetta.translate.datamodel.json.CreateiQJsonSchemaParser;

public class SchemaMerge {
	
	private final static Logger LOGGER = LoggerFactory.getLogger(SchemaMerge.class);
	private final static String schemasToMergeDir = "/Users/hugohills/dev/github/REGnosys/rosetta-cdm/rosetta-source/src/main/resources/schemas/isda-create";
	private final static String outputSchemaFileName = "isda-create-merged.schema";
	private final static List excludedSchemaFileNames = List.of("isda-create-merged.json");
	
	public static void main(String[] args) throws IOException {
		Path schemasDir = Paths.get(schemasToMergeDir);
		Pattern jsonSchemaPattern = Pattern.compile(".*json");
		Stream schemasToMerge = Files.list(schemasDir)
				.filter(p -> jsonSchemaPattern.matcher(p.getFileName().toString()).matches())
				.filter(p -> !excludedSchemaFileNames.contains(p.getFileName().toString()));
		ModelParser parser = new CreateiQJsonSchemaParser();
		List schemas = schemasToMerge
				.peek(System.out::println)
				.map(s->parser.parseModel(UrlUtils.toUrl(s)))
				.collect(Collectors.toList());
		Schema merged = schemas.stream().reduce(null, SchemaMerge::mergeSchemas);
		
		Path mergedSchemaPath = schemasDir.resolve(outputSchemaFileName);
		SchemaSerialise serialise = new SchemaSerialise();
		try (OutputStream newOutputStream = Files.newOutputStream(mergedSchemaPath)) {
			serialise.serialiseObject(merged, newOutputStream);
		} catch (Exception e) {
			LOGGER.error("Failed to merge schema", e);
		}
	}

	private static Schema mergeSchemas(Schema s1, Schema s2) {
		if (s1==null) return s2;
		if (s2==null) return s1;
		
		Map mergedEntities = new IdentityHashMap<>();
		Map mergedAttributesMap = new IdentityHashMap<>();
		List mergedGlobals = mergeEntities(s1.getGlobalTypes(), s2.getGlobalTypes(), mergedEntities, mergedAttributesMap);
		List mergedAttributes = mergeAttributes(s1.getAttributes(), s2.getAttributes(), mergedEntities, mergedAttributesMap);
		return new Schema(mergedAttributes, mergedGlobals);
	}
	
	

	private static List mergeEntities(Collection globalTypes1, Collection globalTypes2,
			Map mergedEntities, Map mergedAttributes) {
		List result = new ArrayList<>();
		
		Map> collect = Stream.concat(globalTypes1.stream(), globalTypes2.stream()).collect(Collectors.groupingBy(a->a.getName(), LinkedHashMap::new, Collectors.toList()));
		collect.entrySet().stream().forEach(e->{
			List atts = e.getValue();
			if (atts.size()==1) {
				result.add(atts.get(0));
			}
			else {
				result.add(mergeEntity(atts, mergedEntities, mergedAttributes));
			}
		});
		return result;
	}

	private static Entity mergeEntity(List ents, Map mergedEntities, Map mergedAttributes) {
		if (ents.size()!=2) {
			throw new RuntimeException("One of the inpus schemas had duplicate Entities named "+ents.get(0).getName());
		}
		Entity ent1 = ents.get(0);
		Entity ent2 = ents.get(1);
		
		return mergeType(ent1, ent2, mergedEntities, mergedAttributes);
	}

	private static List mergeAttributes(Collection attributes1, Collection attributes2, Map mergedEntities, Map mergedAttributes) {
		List result = new ArrayList<>();
		
		Map> collect = Stream.concat(attributes1.stream(), attributes2.stream()).collect(Collectors.groupingBy(a->a.getName(), LinkedHashMap::new, Collectors.toList()));
		collect.entrySet().stream().forEach(e->{
			List atts = e.getValue();
			if (atts.size()==1) {
				result.add(atts.get(0));
			}
			else {
				result.add(mergeAttribute(atts, mergedEntities, mergedAttributes));
			}
		});
		return result;
	}

	private static Attribute mergeAttribute(List atts, Map mergedEntities, Map mergedAttributes) {
		if (atts.size()!=2) {
			throw new RuntimeException("One of the inpus schemas had duplicate attributes named "+atts.get(0).getName());
		}
		Attribute att1 = atts.get(0);
		Attribute att2 = atts.get(1);
		
		if (mergedAttributes.containsKey(att1)) {
			return mergedAttributes.get(att1);
		}
		
		AttributeImpl attributeImpl = new AttributeImpl(att1.getName(), Cardinality.max(att1.getCardinality(), att2.getCardinality()), mergeType(att1.getType(), att2.getType(), mergedEntities, mergedAttributes));
		mergedAttributes.put(att1, attributeImpl);
		return attributeImpl;
		
	}

	private static Entity mergeType(Entity type, Entity type2, Map mergedEntities, Map mergedAttributes) {
		NamespaceName name = type.getName();
		NamespaceName name2 = type2.getName();
		if (!name.equals(name2)) {
			throw new RuntimeException("schemas had differnt entities of ("+name + "|"+name2+")");
		}
		if (mergedEntities.containsKey(type)) {
			return mergedEntities.get(type);
		}
		Entity mergedExtended = mergeExtended(type.getExtendedEntity(), type2.getExtendedEntity(), mergedEntities, mergedAttributes);
		boolean hasValue = type.hasData() || type2.hasData();
		EntityImpl e = new EntityImpl(name, mergedExtended, hasValue);
		
		e.getAttributes().addAll(mergeAttributes(type.getAttributes(), type2.getAttributes(), mergedEntities, mergedAttributes));
		
		mergedEntities.put(type, e);
		return e;
	}

	private static Entity mergeExtended(Entity e1, Entity e2, Map mergedEntities, Map mergedAttributes) {
		if (e1==null) return e2;
		if (e2==null) return e1;
		return mergeType(e1, e2, mergedEntities, mergedAttributes);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy