![JAR search and dependency download from the Maven repository](/logo.png)
com.regnosys.rosetta.translate.synonymmap.SynonymMapBuilder Maven / Gradle / Ivy
package com.regnosys.rosetta.translate.synonymmap;
import static com.regnosys.rosetta.generator.util.RosettaAttributeExtensions.getExpandedAttributes;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.apache.log4j.Logger;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.util.Strings;
import com.codahale.metrics.Timer;
import com.codahale.metrics.Timer.Context;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import com.regnosys.rosetta.common.util.StreamUtils;
import com.regnosys.rosetta.generator.java.RosettaJavaPackages;
import com.regnosys.rosetta.generator.java.types.JavaTypeTranslator;
import com.regnosys.rosetta.generator.java.types.JavaTypeUtil;
import com.regnosys.rosetta.generator.object.ExpandedAttribute;
import com.regnosys.rosetta.generator.object.ExpandedSynonym;
import com.regnosys.rosetta.generator.object.ExpandedSynonymValue;
import com.regnosys.rosetta.generator.object.ExpandedType;
import com.regnosys.rosetta.generator.util.RosettaAttributeExtensions;
import com.regnosys.rosetta.rosetta.ExternalValueOperator;
import com.regnosys.rosetta.rosetta.RosettaClassSynonym;
import com.regnosys.rosetta.rosetta.RosettaEnumeration;
import com.regnosys.rosetta.rosetta.RosettaExternalClassSynonym;
import com.regnosys.rosetta.rosetta.RosettaExternalEnumValue;
import com.regnosys.rosetta.rosetta.RosettaExternalRegularAttribute;
import com.regnosys.rosetta.rosetta.RosettaExternalSynonymSource;
import com.regnosys.rosetta.rosetta.RosettaFactory;
import com.regnosys.rosetta.rosetta.RosettaMappingInstance;
import com.regnosys.rosetta.rosetta.RosettaMergeSynonymValue;
import com.regnosys.rosetta.rosetta.RosettaModel;
import com.regnosys.rosetta.rosetta.RosettaNamed;
import com.regnosys.rosetta.rosetta.RosettaRootElement;
import com.regnosys.rosetta.rosetta.RosettaType;
import com.regnosys.rosetta.rosetta.RosettaTypeAlias;
import com.regnosys.rosetta.rosetta.TypeCall;
import com.regnosys.rosetta.rosetta.simple.AnnotationRef;
import com.regnosys.rosetta.rosetta.simple.Attribute;
import com.regnosys.rosetta.rosetta.simple.Data;
import com.regnosys.rosetta.rosetta.simple.SimpleFactory;
import com.regnosys.rosetta.translate.IngesterGenerator;
import com.regnosys.rosetta.translate.datamodel.NamespaceName;
import com.regnosys.rosetta.types.TypeSystem;
import com.regnosys.rosetta.types.builtin.RBuiltinTypeService;
import com.rosetta.util.DottedPath;
import com.rosetta.util.types.JavaClass;
import com.rosetta.util.types.JavaReferenceType;
import com.rosetta.util.types.generated.GeneratedJavaClass;
public class SynonymMapBuilder {
private static final Logger LOGGER = Logger.getLogger(SynonymMapBuilder.class);
private final List externalSynonyms;
private final Collection synonymSourceNames;
private final JavaTypeTranslator typeTranslator; // TODO: inject instead
private final RosettaJavaPackages packages; // TODO: inject instead
private final JavaTypeUtil typeUtil;
private final TypeSystem typeSystem;
private final RBuiltinTypeService builtins;
private Map typeCache;
public SynonymMapBuilder(String synonymSourceName, JavaTypeTranslator typeTranslator) {
this(Collections.singletonList(synonymSourceName), Collections.emptyList(), typeTranslator);
}
public SynonymMapBuilder(Collection synonymSourceNames, List externalSynonyms, JavaTypeTranslator typeTranslator) {
this(synonymSourceNames, externalSynonyms, null, typeTranslator);
}
public SynonymMapBuilder(Collection synonymSourceNames, List externalSynonyms, Map typeCache, JavaTypeTranslator typeTranslator) {
this.synonymSourceNames = synonymSourceNames;
this.externalSynonyms = externalSynonyms;
this.typeCache = typeCache;
this.typeTranslator = typeTranslator;
this.packages = getPrivateField(typeTranslator, "packages");
this.typeUtil = getPrivateField(typeTranslator, "typeUtil");
this.typeSystem = getPrivateField(typeTranslator, "typeSystem");
this.builtins = getPrivateField(typeTranslator, "builtins");
}
// Hackery
@SuppressWarnings("unchecked")
private T getPrivateField(Object owner, String field) {
Field f;
try {
f = owner.getClass().getDeclaredField(field);
} catch (NoSuchFieldException | SecurityException | IllegalArgumentException e) {
try {
f = owner.getClass().getSuperclass().getDeclaredField(field);
} catch (NoSuchFieldException | SecurityException e1) {
throw new RuntimeException(e);
}
}
f.setAccessible(true);
try {
return (T)f.get(owner);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public SynonymMap buildMap(RosettaType topClass) {
Timer timer = IngesterGenerator.GENERATOR_METRICS.timer("Building synoym map");
Context time = timer.time();
if (topClass==null) {
return null;
}
Map maps = new HashMap<>();
Map enumMaps = new HashMap<>();
SynonymMap buildMap = buildMap(topClass, maps, enumMaps);
time.stop();
return buildMap;
}
public SynonymMap buildMap(RosettaType topType, Map classMaps,
Map enumMaps) {
if (topType==null) return null;
topType = resolveType(topType);
if (classMaps.containsKey(topType)) {
return classMaps.get(topType);
}
if (enumMaps.containsKey(topType)) {
return enumMaps.get(topType);
}
if (topType instanceof Data) {
LOGGER.trace("building map for "+topType.getName());
Data topClass = (Data) topType;
Data superType = topClass.getSuperType();
SynonymMap result = classMaps.get(topType);
if (result == null) {
result = new SynonymMap(topClass, buildMap(superType, classMaps, enumMaps));
classMaps.put(topClass, result);
}
Map mappings = buildMappings(topClass,
Collections.emptyList(),
classMaps,
enumMaps,
false,
Collections.emptySet(),
HashMultimap.create());
result.addMappings(mappings);
Multimap conditionCaptures = findCaptures(mappings);
result.getConditionalCaptures().putAll(conditionCaptures);
return result;
}
else if (topType instanceof RosettaEnumeration) {
LOGGER.trace("building enum map for " +topType.getName());
RosettaEnumeration rEnum = (RosettaEnumeration)topType;
SynonymMap result = enumMaps.get(topType);
if (result == null) {
result = new SynonymMap(rEnum, buildMap(rEnum.getParent(), classMaps, enumMaps));
enumMaps.put(rEnum, result);
}
Map buildMappings = buildEnumMappings(rEnum, Collections.emptyList());
result.addMappings(buildMappings);
return result;
}
else if (topType instanceof RosettaTypeAlias) {
return buildMap(((RosettaTypeAlias)topType).getTypeCall().getType(), classMaps, enumMaps);
}
else {
return new SynonymMap();
}
}
private Multimap findCaptures(Map mappings) {
ArrayListMultimap res = ArrayListMultimap.create();
//find all the conditional paths that need capturing inside this classes mappings
for (AttributeGroup pp:mappings.keySet()) {
for (SynonymGroup sg:pp.getSynonymGroups()) {
for (SynonymCondition cond:sg.getConditions()) {
for (SynonymTest test:cond.getCondition()) {
for (SynonymValue val:test.getPaths()) {
res.put(val, cond);
}
}
}
}
}
return res;
}
private Map buildEnumMappings(RosettaEnumeration rEnum, List attPath) {
Map result = new HashMap<>();
for (ExpandedAttribute enumVal:getAllEnumValue(rEnum)) {
List enumPath = new ArrayList<>(attPath);
enumPath.add(enumVal);
List enumSyns = getEnumSynonyms(enumVal);
List groups = enumSyns.stream().map(s->toGroup(s, rEnum.getModel().getName())).collect(Collectors.toList());
result.put(new AttributeGroup(groups, enumPath), new SynonymMap((RosettaType)null));
}
return result;
}
public List getEnumSynonyms(ExpandedAttribute enumVal) {
List enumSyns = enumVal.getSynonyms().stream()
.filter(s-> sourcesMatch(s))
.collect(Collectors.toList());
List copy = new ArrayList<>(externalSynonyms);
Collections.reverse(copy);
// loop through ext syn srcs from top of heirarchy to bottom
copy.forEach(extSynSrc -> {
LOGGER.trace("External Synonym src: " + extSynSrc.getName());
List externalAttributes = getRosettaExternalEnums(enumVal.getEnclosingType(), enumVal, extSynSrc);
List additions = externalAttributes.stream().filter(x -> x.getOperator().equals(ExternalValueOperator.PLUS)).collect(Collectors.toList());
List removals = externalAttributes.stream().filter(x -> x.getOperator().equals(ExternalValueOperator.MINUS)).collect(Collectors.toList());
enumSyns.removeIf(s -> removals.stream()
.map(c -> c.getEnumRef())
.map(c -> c.getName())
.anyMatch(n -> n.equals(enumVal.getName())));
// add in extra mappings from a mapping file
enumSyns.addAll(addExternalEnumSynonyms(additions));
});
return enumSyns;
}
private Map buildMappings(RosettaType clazz,
List attPath,
Map maps,
Map enumMaps,
boolean includeSupers,
Collection alreadySearched,
Multimap attMergeSyns) {
Map result = new HashMap<>();
Collection searchAttributes = new ArrayList<>();
List copy = new ArrayList<>(externalSynonyms);
Collections.reverse(copy);
if(clazz instanceof Data) {
searchAttributes = getAllAttributes((Data)clazz, includeSupers);
Data data = (Data)clazz;
if (data.getAnnotations() != null && data.getAnnotations().stream()
.map(AnnotationRef::getAttribute)
.filter(Objects::nonNull)
.map(Attribute::getName)
.filter(Objects::nonNull)
.anyMatch(a->a.equals("key"))) {
addKeySynonyms(
data.getSynonyms().stream().filter(s->sourcesMatch(s)).collect(Collectors.toList()),
getRosettaExternalClassSynonyms(clazz.getName()),
attPath,
result);
}
if (data.getSuperType()!=null && ! includeSupers) {
searchAttributes.addAll(addsSynonyms(copy, searchAttributes, (Data)clazz));
}
}
for (ExpandedAttribute att: searchAttributes) {
List newPath = new ArrayList<>(attPath);//the path of attributes we have recursed down in order to find synonyms
if (att.hasMetas()) {
if (att.refIndex()>=0) {
//This could be a reference or a value - add the path to map the value
newPath.add(referenceTo(att));
newPath.add(metadFieldValue(att));
}
else {
newPath.add(metadField(att));
newPath.add(metadFieldValue(att));
}
}
else {
newPath.add(att);
}
List allAttSyns = att.getSynonyms().stream()
.filter(s->sourcesMatch(s))
.collect(Collectors.toList());
// Updates allAttSyns with external synonyms, and returns the delta
List delta = getSynonymDeltas(att, allAttSyns, copy, clazz);
// exclude any merge syns
List attSyns = allAttSyns.stream()
.filter(s->s.getMerge() == null)
.collect(Collectors.toList());
// include only merge syns
List mergeSyns = allAttSyns.stream()
.map(s->s.getMerge())
.filter(Objects::nonNull)
.collect(Collectors.toList());
if (!mergeSyns.isEmpty()) {
attMergeSyns.putAll(att, mergeSyns);
}
TypeCall tc = att.getRosettaType();
RosettaType type = null;
if (tc != null) {
type = tc.getType();
}
//TODO check ExpandedType usage
if (!attSyns.isEmpty()) {
List groups = attSyns.stream()
.map(s->toGroup(s, clazz.getModel().getName()))
.collect(Collectors.toList());
if (!groups.isEmpty()) {
SynonymMap map = buildMap(type, maps, enumMaps);
if (!attMergeSyns.isEmpty()) {
// merge synonyms indicate any mappings for that synonym/attribute should be added to same list item (rather than create a new list item)
List attMergeSynValues = attMergeSyns.values().stream()
.map(RosettaMergeSynonymValue::getName)
.collect(Collectors.toList());
// determine if the merge synonym matches any of the synonym paths mapped to the current attribute
boolean matchesSyn = groups.stream()
.flatMap(group -> group.getSynonymValues().stream())
.flatMap(synValue -> synValue.getSynonymPath().stream())
.map(Element::getName)
.anyMatch(attMergeSynValues::contains);
// add to the attribute's synonym path
if (matchesSyn) {
map.getMergeSynonyms().putAll(attMergeSyns);
}
}
result.put(new AttributeGroup(groups, newPath), map);
}
if (att.hasMetas()) {
Map metaSynonyms = metaSynonyms(att, newPath.subList(0, newPath.size()-1), delta, clazz.getModel().getName());
result.putAll(metaSynonyms);
}
List hints = attSyns.stream().flatMap(s->s.getHints().stream()).collect(Collectors.toList());
//this attribute has a hint - that means we search inside it for synonyms starting with the hint
if (!hints.isEmpty() && type instanceof Data) {
if (!alreadySearched.contains(type)) {
Collection searched = new HashSet<>(alreadySearched);
RosettaType attClazz = type;
searched.add(attClazz);
Map hintMappings = buildMappings(attClazz, newPath, maps, enumMaps, true, searched, attMergeSyns);
hintMappings = filtertoHinted(hintMappings, hints);
result.putAll(hintMappings);
}
}
}
else {
//this attribute has no synonyms - search inside it for synonyms instead
if (type instanceof Data && att.refIndex()<0) {
if (!alreadySearched.contains(type)) {
Collection searched = new HashSet<>(alreadySearched);
RosettaType attClazz = type;
searched.add(attClazz);
result.putAll(buildMappings(attClazz, newPath, maps, enumMaps, true, searched, attMergeSyns));
}
}
else {
//a basic type with no mapping - ignore it
}
}
}
return result;
}
//add in the attributes from super classes for which the external synonyms have added a mapping in this class
private Collection extends ExpandedAttribute> addsSynonyms(List copy, Collection searchAttributes, Data clazz) {
//get all possible additional attributes from super classes
Collection allSuperAttributes = getAllAttributes(clazz.getSuperType(), true);
return copy.stream().flatMap(extSynSrc ->{
//for each external source
//for each possible addition attribute
return allSuperAttributes.stream()
//find the external synonyms added to that attribute
.filter(a -> addsASynonym(a, extSynSrc, clazz));
//if they exist then return this attribute
}).collect(Collectors.toSet());
}
private boolean addsASynonym(ExpandedAttribute att, RosettaExternalSynonymSource extSynSrc, Data clazz) {
List externalSynonymsForType = getRosettaExternalRegularAttributes(clazz, att, extSynSrc, false);
boolean additions = externalSynonymsForType.stream().anyMatch(x->x.getOperator().equals(ExternalValueOperator.PLUS));
return additions;
}
public List getSynonymDeltas(ExpandedAttribute att, List attSyns,
List copy, RosettaType clazz) {
List delta = new ArrayList<>();
// loop through ext syn srcs from top of hierarchy to bottom
copy.forEach(extSynSrc -> {
LOGGER.trace("External Synonym src: " + extSynSrc.getName());
List externalAttributes = getRosettaExternalRegularAttributes(clazz, att, extSynSrc, true);
List additions = externalAttributes.stream().filter(x -> x.getOperator().equals(ExternalValueOperator.PLUS)).collect(Collectors.toList());
List removals = externalAttributes.stream().filter(x -> x.getOperator().equals(ExternalValueOperator.MINUS)).collect(Collectors.toList());
delta.removeIf(s -> removals.stream()
.map(c -> c.getAttributeRef())
.map(c -> c.getName())
.anyMatch(n -> n.equals(att.getName())));
delta.addAll(additions);
attSyns.removeIf(s -> removals.stream()
.map(c -> c.getAttributeRef())
.map(c -> c.getName())
.anyMatch(n -> n.equals(att.getName())));
//add in extra mappings from a mapping file
attSyns.addAll(addExternalSynonyms(additions));
});
return delta;
}
private void addKeySynonyms(List synonyms, List externalSynonyms, List attPath, Map result) {
List synonymGroups = new ArrayList<>();
// inline synonyms
List expandedSynonyms = synonyms.stream()
.filter(syn -> syn.getMetaValue()!=null)
.map(RosettaAttributeExtensions::toRosettaExpandedSynonym)
.collect(Collectors.toList());
// external synonyms
expandedSynonyms.addAll(externalSynonyms.stream()
.filter(syn -> syn.getMetaValue()!=null)
.map(RosettaAttributeExtensions::toRosettaExpandedSynonym)
.collect(Collectors.toList()));
for (ExpandedSynonym rosettaExpandedSynonym:expandedSynonyms) {
List synonymValues = Collections.singletonList(toList(rosettaExpandedSynonym.getMetaValues().get(0)));
SynonymGroup synGroup = new SynonymGroup(synonymValues, Collections.emptyList(), null, null, null, null, false);
synonymGroups.add(synGroup);
}
if (!synonymGroups.isEmpty()) {
List newPath = new ArrayList<>(attPath);
newPath.add(metaAtt());
newPath.add(externalKeyAtt());
AttributeGroup attgroup = new AttributeGroup(synonymGroups, newPath);
result.put(attgroup, new SynonymMap());
}
}
private Map filtertoHinted(Map hintMappings, List hints) {
Map result = new HashMap<>();
for (Map.Entry entry:hintMappings.entrySet()) {
List filteredGroups = new ArrayList<>();
for (SynonymGroup group:entry.getKey().getSynonymGroups()) {
List filteredValues = group.getSynonymValues().stream().filter(v->hints.contains(v.getSynonymPath().get(0).getName())).collect(Collectors.toList());
if (!filteredValues.isEmpty()) {
SynonymGroup filteredGroup = new SynonymGroup(filteredValues, group.getConditions(), group.getMapperName(), group.getFormatString(), group.getPatternMatcher(), group.getPatternReplace(), group.isRemoveHtml());
filteredGroups.add(filteredGroup);
}
List filteredConditions = group.getConditions().stream().map(c->filteredCondition(c, hints)).filter(c->!c.getCondition().isEmpty()).collect(Collectors.toList());
if (!filteredConditions.isEmpty()) {
SynonymGroup filteredGroup = new SynonymGroup(Collections.emptyList(), filteredConditions, group.getMapperName(), group.getFormatString(), group.getPatternMatcher(), group.getPatternReplace(), group.isRemoveHtml());
filteredGroups.add(filteredGroup);
}
}
if (!filteredGroups.isEmpty()) {
AttributeGroup fillteredAtt = new AttributeGroup(filteredGroups, entry.getKey().getAttributePath());
result.put(fillteredAtt, entry.getValue());
}
}
return result;
}
private SynonymCondition filteredCondition(SynonymCondition condition, List hints) {
List conditions = condition.getCondition().stream().filter(t->filterTest(t, hints)).collect(Collectors.toList());
return new SynonymCondition(condition.getSetToValue(), conditions);
}
private boolean filterTest(SynonymTest test, List hints) {
return test.getPaths().stream().anyMatch(v->hints.contains(v.getSynonymPath().get(0).getName()));
}
private Map metaSynonyms(ExpandedAttribute att, List newPath, List externalRegularAttributes, String enclosingPackageName) {
Map metaSynonyms = new HashMap<>();
List metas = att.getMetas();
for (int metaIndex = 0; metaIndex < metas.size(); metaIndex++) {
ExpandedAttribute metaAtt = metas.get(metaIndex);
String name = metaAtt.getName();
List sourceSyns = metaAtt.getSynonyms().stream()
.filter(s->sourcesMatch(s))
.collect(Collectors.toList());
List addExternalMetaSynonyms = findExternalMetaSynonyms(externalRegularAttributes, metaIndex);
sourceSyns.addAll(addExternalMetaSynonyms);
List metaPath = new ArrayList<>(newPath);
if (name.equals("reference")) {
metaPath.add(refField());
}
else if (name.equals("address")) {
metaPath.add(addressField());
} else {
metaPath.add(metaAtt());
metaPath.add(metaDataField(metaAtt));
}
List groups = sourceSyns.stream()
.map(s->toGroup(s, enclosingPackageName)).collect(Collectors.toList());
SynonymMap map = new SynonymMap((RosettaType)null);
if (!groups.isEmpty()) {
metaSynonyms.put(new AttributeGroup(groups, metaPath), map);
}
}
return metaSynonyms;
}
private List findExternalMetaSynonyms(List externalRegularAttributes, int metaIndex) {
List expandedSynonyms = new ArrayList<>();
IntStream.range(0, externalRegularAttributes.size())
.forEach(i -> {
RosettaExternalRegularAttribute rosettaExternalRegularAttribute = externalRegularAttributes.get(i);
List rosettaExpandedSynonym = RosettaAttributeExtensions.toRosettaExpandedSynonym(null,
rosettaExternalRegularAttribute.getExternalSynonyms(), metaIndex);
expandedSynonyms.addAll(rosettaExpandedSynonym);
});
return expandedSynonyms;
}
private List addExternalEnumSynonyms(List externalAttributes) {
return externalAttributes.stream()
.map(a -> a.getExternalEnumSynonyms())
.flatMap(Collection::stream)
// now convert to a ExpandedSynonym
.map(RosettaAttributeExtensions::toExpandedSynonym)
.collect(Collectors.toList());
}
private List getRosettaExternalEnums(String enclosingTypeName, ExpandedAttribute att, RosettaExternalSynonymSource extSynSrc) {
return extSynSrc.getExternalEnums().stream()
// filter to the clazz passed in and get its attributes
.filter(c -> c.getTypeRef().getName().equals(enclosingTypeName))
.map(c -> c.getRegularValues())
.flatMap(Collection::stream)
// filter to the att passed in and get its synonyms
.filter(c -> c.getEnumRef().getName().equals(att.getName()))
.collect(Collectors.toList());
}
private List addExternalSynonyms(List externalAttributes) {
return externalAttributes.stream()
.map(a -> a.getExternalSynonyms())
.flatMap(Collection::stream)
// now convert to a ExpandedSynonym
.map(RosettaAttributeExtensions::toRosettaExpandedSynonym)
.collect(Collectors.toList());
}
private List getRosettaExternalRegularAttributes(RosettaType enclosingType, ExpandedAttribute att, RosettaExternalSynonymSource extSynSrc, boolean includeSupers) {
Set enclosingTypeNames = getEnclosingTypes(enclosingType, includeSupers).map(RosettaType::getName).collect(Collectors.toSet());
return extSynSrc.getExternalClasses().stream()
// filter to the clazz passed in and get its attributes
.filter(c -> enclosingTypeNames.contains(c.getTypeRef().getName()))
.map(c -> c.getRegularAttributes())
.flatMap(Collection::stream)
// filter to the att passed in and get its synonyms
.filter(c -> c.getAttributeRef().getName().equals(att.getName()))
.collect(Collectors.toList());
}
private Stream extends RosettaType> getEnclosingTypes(RosettaType enclosingType, boolean includeSupers) {
if (!includeSupers) return Stream.of(enclosingType);
if (enclosingType instanceof Data) return StreamUtils.recurse((Data)enclosingType, Data::getSuperType);
if (enclosingType instanceof RosettaEnumeration) return StreamUtils.recurse((RosettaEnumeration)enclosingType, e->e.getParent());
else return Stream.of(enclosingType);
}
private List getRosettaExternalClassSynonyms(String enclosingTypeName) {
return externalSynonyms.stream()
// get the external class cross ref
.map(RosettaExternalSynonymSource::getExternalClasses)
.flatMap(Collection::stream)
// filter to the clazz passed in and get its class synonyms
.filter(c -> c.getTypeRef().getName().equals(enclosingTypeName))
.map(c -> c.getExternalClassSynonyms())
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
private Collection getAllAttributes(Data clazz, boolean includeSupers) {
List result = new ArrayList<>(getExpandedAttributes(clazz));
if (clazz.getSuperType() != null && includeSupers) {
result.addAll(getAllAttributes(clazz.getSuperType(), includeSupers));
}
return result;
}
public Collection getAllEnumValue(RosettaEnumeration rEnum) {
if (rEnum.getParent()==null) {
return getExpandedAttributes(rEnum);
}
List result = new ArrayList<>(getExpandedAttributes(rEnum));
result.addAll(getAllEnumValue(rEnum.getParent()));
return result;
}
private SynonymGroup toGroup(ExpandedSynonym synonym, String enclosingPackageName) {
String mapperName = synonym.getMapperName()==null?null:enclosingPackageName+".processor."+synonym.getMapperName();
if (synonym.getValues()!=null && synonym.getMetaValues()!=null) {
return new SynonymGroup(synonym.getValues().stream().map(this::toList).collect(Collectors.toList()),
toConditions(synonym), mapperName, synonym.getFormat(), synonym.getPatternMatcher(), synonym.getPatternReplace(), synonym.isRemoveHtml());
}
//this is a set to style synonym
return new SynonymGroup(toConditions(synonym));
}
private List toConditions(ExpandedSynonym synonym) {
if (synonym.getMappingLogic()==null) return Collections.emptyList();
List instances = synonym.getMappingLogic().getInstances();
return instances.stream().map(i->toCondition(i)).collect(Collectors.toList());
}
private SynonymCondition toCondition(RosettaMappingInstance instance) {
return SynonymCondition.create(instance.getSet(), instance.getWhen()==null?Collections.emptyList():instance.getWhen().getTests());
}
private SynonymValue toList(ExpandedSynonymValue value) {
if (value.getPath()==null || value.getPath().isEmpty()) {
return new SynonymValue(ImmutableList.of(new Element(value.getName())), value.getMaps(), value.isMeta());
}
List r = Element.toElementList(value.getPath());
r.add(new Element(value.getName()));
return new SynonymValue(r, value.getMaps(), value.isMeta());
}
private boolean sourcesMatch(ExpandedSynonym s) {
return s.getSources().stream().anyMatch(ss -> synonymSourceNames.contains(ss.getName()));
}
private boolean sourcesMatch(RosettaClassSynonym s) {
return s.getSources().stream().anyMatch(ss -> synonymSourceNames.contains(ss.getName()));
}
private T resolveType(T typeReference) {
if (typeCache!=null) {
NamespaceName name = new NamespaceName(typeReference.getModel().getName(), typeReference.getName());
RosettaNamed rosettaNamed = typeCache.get(name);
@SuppressWarnings("unchecked")
T result = (T) rosettaNamed;
if (result!=null) return result;
}
return typeReference;
}
/*
* Methods below are moved from RosettaAttributeExtensions
*/
private ExpandedAttribute referenceTo(ExpandedAttribute att) {
return new ExpandedAttribute(att.getName(), att.getEnclosingType(), RosettaAttributeExtensions.toExpandedType(referenceType(att).getType()),
referenceType(att),
true, // True to indicate that this is a ReferenceWithMeta
att.getInf(), att.getSup(), att.isUnbound(),
Collections.emptyList(), null, Collections.emptyList(), false, Collections.emptyList());
}
static private String toFirstUpper(String name) {
return Strings.toFirstUpper(name);
}
static private ExpandedAttribute refField() {
return new ExpandedAttribute("externalReference", null, provideStringType(), null, false, 1, 1, false, Collections.emptyList(), null, Collections.emptyList(), false, Collections.emptyList());
}
static private ExpandedAttribute addressField() {
return new ExpandedAttribute("reference", null, new ExpandedType(null, "ReferenceBuilder", false, false, false), null, false, 1, 1, false, Collections.emptyList(), null, Collections.emptyList(), false, Collections.emptyList());
}
static private ExpandedAttribute metadField(ExpandedAttribute att) {
return new ExpandedAttribute(att.getName(),
att.getEnclosingType(),
RosettaAttributeExtensions.toExpandedType(metadType(att.getType()).getType()),
metadType(att.getType()),
true, // True to indicate that this is a FieldWithMeta
att.getInf(),
att.getSup(),
att.isUnbound(),
Collections.emptyList(),
null,
Collections.emptyList(),
false,
Collections.emptyList());
}
static private ExpandedAttribute metadFieldValue(ExpandedAttribute att) {
return new ExpandedAttribute("value", att.getEnclosingType(), att.getType(), att.getRosettaType(), false, 1, 1, false, Collections.emptyList(), null, Collections.emptyList(), false, Collections.emptyList());
}
static ExpandedAttribute metaDataField(ExpandedAttribute att) {
String name = att.getName();
if ("id".equals(name)) {
name = "externalKey";//the id meta attribute is implemented as externalkey
}
return new ExpandedAttribute(name, att.getEnclosingType(), att.getType(), null, false, 1, 1, false, Collections.emptyList(), null, Collections.emptyList(), false, Collections.emptyList());
}
static private ExpandedAttribute metaAtt() {
return new ExpandedAttribute("meta", null, RosettaAttributeExtensions.toExpandedType(META_TYPE.getType()), META_TYPE, false, 1, 1, false, Collections.emptyList(), null, Collections.emptyList(),false, Collections.emptyList());
}
static private ExpandedAttribute externalKeyAtt() {
return new ExpandedAttribute("externalKey", null, provideStringType(), null, false, 1, 1, false, Collections.emptyList(), null, Collections.emptyList(),false, Collections.emptyList());
}
private static ExpandedType provideStringType() {
return new ExpandedType(null, "string", false, false, false);
}
private TypeCall referenceType(ExpandedAttribute genAttr) {
JavaClass> metaJavaType = toMetaJavaType(genAttr);
Data res = SimpleFactory.eINSTANCE.createData();
res.setName(metaJavaType.getSimpleName());
res.setDefinition(genAttr.getName());
// Create a model so that the code generator knows which package the reference type is in
RosettaModel model = RosettaFactory.eINSTANCE.createRosettaModel();
model.setName(metaJavaType.getPackageName().withDots());
res.setModel(model);
TypeCall typeCall = RosettaFactory.eINSTANCE.createTypeCall();
typeCall.setType(res);
return typeCall;
}
private JavaClass> toMetaJavaType(ExpandedAttribute expAttr) {
JavaReferenceType attrType;
if (expAttr.getRosettaType() != null) {
attrType = typeTranslator.toJavaReferenceType(typeSystem.typeCallToRType(expAttr.getRosettaType()));
} else {
attrType = expandedTypeToJavaType(expAttr.getType());
}
DottedPath namespace = getModelPackage(expAttr.getRosettaType().getType());
return toMetaJavaType(attrType, expAttr.refIndex() < 0, namespace);
}
private JavaClass> toMetaJavaType(JavaReferenceType base, boolean hasMetaFieldAnnotations, DottedPath namespace) {
String attributeTypeName = base.getSimpleName();
String name;
if (hasMetaFieldAnnotations) {
name = "FieldWithMeta" + attributeTypeName;
} else {
name = "ReferenceWithMeta" + attributeTypeName;
}
DottedPath pkg = metaField(namespace);
return new GeneratedJavaClass<>(pkg, name, Object.class);
}
private DottedPath metaField(DottedPath p) {
return p.child("metafields");
}
private DottedPath getModelPackage(RosettaNamed object) {
RosettaRootElement rootElement = EcoreUtil2.getContainerOfType(object, RosettaRootElement.class);
RosettaModel model = rootElement.getModel();
if (model == null)
// Artificial attributes
throw new IllegalArgumentException("Can not compute package name for " + object.eClass().getName() + " " + object.getName() + ". Element is not attached to a RosettaModel.");
return modelPackage(model);
}
private DottedPath modelPackage(RosettaModel model) {
return DottedPath.splitOnDots(model.getName());
}
private JavaReferenceType expandedTypeToJavaType(ExpandedType type) {
if (type.getName().equals(RosettaAttributeExtensions.METAFIELDS_CLASS_NAME) || type.getName().equals(RosettaAttributeExtensions.META_AND_TEMPLATE_FIELDS_CLASS_NAME)) {
return new GeneratedJavaClass<>(packages.basicMetafields(), type.getName(), Object.class);
}
if (type.isMetaType()) {//TODO ExpandedType needs to store the underlying type for meta types if we want them to be anything other than strings
return typeUtil.STRING;
}
if (type.isBuiltInType()) {
return typeTranslator.toJavaReferenceType(builtins.getType(type.getName(), Collections.emptyMap()));
}
return new GeneratedJavaClass<>(modelPackage(type.getModel()), type.getName(), Object.class);
}
private static TypeCall metadType(ExpandedType genType) {
Data res = SimpleFactory.eINSTANCE.createData();
res.setName("FieldWithMeta"+toFirstUpper(genType.getName()));
res.setDefinition(genType.getName());
// Create a model so that the code generator knows which package the reference type is in
RosettaModel model = RosettaFactory.eINSTANCE.createRosettaModel();
model.setName(genType.getModel().getName() + ".metafields");
res.setModel(model);
TypeCall typeCall = RosettaFactory.eINSTANCE.createTypeCall();
typeCall.setType(res);
return typeCall;
}
static TypeCall META_TYPE = null;
{
Data res = SimpleFactory.eINSTANCE.createData();
res.setName("MetaFields");
TypeCall typeCall = RosettaFactory.eINSTANCE.createTypeCall();
typeCall.setType(res);
META_TYPE = typeCall;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy