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

cdc.mf.transform.MfTransformer Maven / Gradle / Ivy

There is a newer version: 0.41.0
Show newest version
package cdc.mf.transform;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import cdc.mf.model.MfAbstractChildElement;
import cdc.mf.model.MfAggregation;
import cdc.mf.model.MfAssociation;
import cdc.mf.model.MfClass;
import cdc.mf.model.MfComposition;
import cdc.mf.model.MfConstraint;
import cdc.mf.model.MfDocumentation;
import cdc.mf.model.MfElement;
import cdc.mf.model.MfEnumeration;
import cdc.mf.model.MfEnumerationValue;
import cdc.mf.model.MfImplementation;
import cdc.mf.model.MfInterface;
import cdc.mf.model.MfModel;
import cdc.mf.model.MfOperation;
import cdc.mf.model.MfPackage;
import cdc.mf.model.MfParameter;
import cdc.mf.model.MfProperty;
import cdc.mf.model.MfSpecialization;
import cdc.mf.model.MfTag;
import cdc.mf.model.MfTip;
import cdc.util.lang.Checks;

/**
 * Class used to recursively transform a source model into a target one.
 * 

* * * @author Damien Carbonne */ public final class MfTransformer { /** The model transformer. */ private final MfModelTransformer modelTransformer; /** The transformer to use for each child element class. */ private final Map, MfChildTransformer> best = new HashMap<>(); private MfTransformer(Builder builder) { this.modelTransformer = Checks.isNotNull(builder.modelTransformer, "modelTransformer"); final List> sorted = new ArrayList<>(builder.childTransformers); // Last matching transformer must be selected, so we reverse the order Collections.reverse(sorted); // Select the best transformer for each child element class addBest(MfAggregation.class, sorted); addBest(MfAssociation.class, sorted); addBest(MfClass.class, sorted); addBest(MfComposition.class, sorted); addBest(MfConstraint.class, sorted); addBest(MfDocumentation.class, sorted); addBest(MfEnumeration.class, sorted); addBest(MfEnumerationValue.class, sorted); addBest(MfImplementation.class, sorted); addBest(MfInterface.class, sorted); addBest(MfOperation.class, sorted); addBest(MfPackage.class, sorted); addBest(MfParameter.class, sorted); addBest(MfProperty.class, sorted); addBest(MfSpecialization.class, sorted); addBest(MfTag.class, sorted); addBest(MfTip.class, sorted); } /** * @param The child element type. * @param

The parent type. * @param cls The child element class. * @param sorted The sorted list of available transformers where the selection must be done. * @return The first matching transformer in {@code sorted}, or a cloner if no matching transformer is found. */ private static , P extends MfElement> MfChildTransformer getFirstOrDef(Class cls, List> sorted) { for (final MfChildTransformer t : sorted) { if (t.getChildClass().isAssignableFrom(cls)) { return t; } } return MfChildTransformer.cloner(cls); } /** * Selects and adds the best transformer that should be used for a class. * * @param The child element type. * @param

The parent type. * @param cls The child element class. * @param sorted The sorted list of available transformers where the selection must be done. */ private , P extends MfElement> void addBest(Class cls, List> sorted) { best.put(cls, getFirstOrDef(cls, sorted)); } /** * @param src The source child element. * @return The child element transformer to use for {@code src}. */ private MfChildTransformer getBest(MfElement src) { return best.get(src.getClass()); } /** * Transforms a source model into a target model. * * @param srcModel The source model. * @return The transformation of {@code srcModel} into a target model. */ public MfModel transform(MfModel srcModel) { // Locally transform model final MfModel tgtModel = modelTransformer.transform(srcModel); // Recursively transform children recurse(srcModel, tgtModel); return tgtModel; } /** * Recursively transform all children of a source parent into children of a target parent. * * @param srcParent The source parent element. * @param tgtParent The target parent element. */ private void recurse(MfElement srcParent, MfElement tgtParent) { // Iterate on all source children for (final MfElement srcChild : srcParent.getChildren()) { // Retrieve the appropriate transformer final MfChildTransformer t = getBest(srcChild); // Transform the child final MfElement tgtChild = t.transformRaw(srcChild, tgtParent); if (tgtChild != null) { recurse(srcChild, tgtChild); } } } public static Builder builder() { return new Builder(); } /** * Builder of {@link MfTransformer}. * * @author Damien Carbonne */ public static final class Builder { private MfModelTransformer modelTransformer = MfModelTransformer.cloner(); private final List> childTransformers = new ArrayList<>(); Builder() { } /** * Sets the model local transformer. * * @param transformer The transformer. * @return This builder. */ public Builder modelTransformer(MfModelTransformer transformer) { this.modelTransformer = transformer; return this; } /** * Adds a child element local transformer. *

* WARNING: the order of additions matters. * For each element, the last matching transformer is selected. * * @param transformer The transformer. * @return This builder. */ public Builder childTransformer(MfChildTransformer transformer) { this.childTransformers.add(transformer); return this; } public MfTransformer build() { return new MfTransformer(this); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy