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

com.regnosys.rosetta.translate.IngesterGenerator Maven / Gradle / Ivy

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

import com.codahale.metrics.MetricRegistry;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.TreeMultimap;
import com.regnosys.rosetta.common.util.UrlUtils;
import com.regnosys.rosetta.generator.java.RosettaJavaPackages;
import com.regnosys.rosetta.generator.java.enums.EnumHelper;
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.ExpandedType;
import com.regnosys.rosetta.generator.util.IterableUtil;
import com.regnosys.rosetta.generator.util.RosettaAttributeExtensions;
import com.regnosys.rosetta.interpreter.RosettaValue;
import com.regnosys.rosetta.rosetta.Import;
import com.regnosys.rosetta.rosetta.RosettaAttributeReference;
import com.regnosys.rosetta.rosetta.RosettaAttributeReferenceSegment;
import com.regnosys.rosetta.rosetta.RosettaBuiltinType;
import com.regnosys.rosetta.rosetta.RosettaDataReference;
import com.regnosys.rosetta.rosetta.RosettaEnumValueReference;
import com.regnosys.rosetta.rosetta.RosettaEnumeration;
import com.regnosys.rosetta.rosetta.RosettaExternalSynonymSource;
import com.regnosys.rosetta.rosetta.RosettaMapTestExpression;
import com.regnosys.rosetta.rosetta.RosettaMergeSynonymValue;
import com.regnosys.rosetta.rosetta.RosettaModel;
import com.regnosys.rosetta.rosetta.RosettaRootElement;
import com.regnosys.rosetta.rosetta.RosettaSynonymSource;
import com.regnosys.rosetta.rosetta.RosettaType;
import com.regnosys.rosetta.rosetta.RosettaTypeAlias;
import com.regnosys.rosetta.rosetta.TypeCall;
import com.regnosys.rosetta.rosetta.expression.RosettaBooleanLiteral;
import com.regnosys.rosetta.rosetta.expression.RosettaIntLiteral;
import com.regnosys.rosetta.rosetta.expression.RosettaLiteral;
import com.regnosys.rosetta.rosetta.expression.RosettaNumberLiteral;
import com.regnosys.rosetta.rosetta.expression.RosettaStringLiteral;
import com.regnosys.rosetta.translate.CustomDeserialise;
import com.regnosys.rosetta.translate.datamodel.Cardinality;
import com.regnosys.rosetta.translate.datamodel.ModelParser;
import com.regnosys.rosetta.translate.datamodel.Schema;
import com.regnosys.rosetta.translate.datamodel.SchemaDeserialise;
import com.regnosys.rosetta.translate.datamodel.SchemaSerialise;
import com.regnosys.rosetta.translate.datamodel.json.JsonSchemaParser;
import com.regnosys.rosetta.translate.datamodel.xsd.BeansXsdParser;
import com.regnosys.rosetta.translate.synonymmap.AttributeGroup;
import com.regnosys.rosetta.translate.synonymmap.AttributeGroupMapping;
import com.regnosys.rosetta.translate.synonymmap.CardinalityChecker;
import com.regnosys.rosetta.translate.synonymmap.Element;
import com.regnosys.rosetta.translate.synonymmap.ModelCombiner;
import com.regnosys.rosetta.translate.synonymmap.SynonymAbsentTest;
import com.regnosys.rosetta.translate.synonymmap.SynonymBinaryTest;
import com.regnosys.rosetta.translate.synonymmap.SynonymCondition;
import com.regnosys.rosetta.translate.synonymmap.SynonymConditionFuncTest;
import com.regnosys.rosetta.translate.synonymmap.SynonymExistsTest;
import com.regnosys.rosetta.translate.synonymmap.SynonymGroup;
import com.regnosys.rosetta.translate.synonymmap.SynonymMap;
import com.regnosys.rosetta.translate.synonymmap.SynonymMapBuilder;
import com.regnosys.rosetta.translate.synonymmap.SynonymPathTest;
import com.regnosys.rosetta.translate.synonymmap.SynonymRosettaPathTest;
import com.regnosys.rosetta.translate.synonymmap.SynonymTest;
import com.regnosys.rosetta.translate.synonymmap.SynonymValue;
import com.regnosys.rosetta.types.RType;
import com.regnosys.rosetta.types.builtin.RBuiltinTypeService;
import com.rosetta.model.lib.RosettaModelObject;
import com.rosetta.util.DottedPath;
import com.rosetta.util.types.JavaClass;
import com.rosetta.util.types.generated.GeneratedJavaClass;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
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.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import javax.inject.Inject;
import org.apache.commons.text.StringEscapeUtils;
import org.apache.log4j.Logger;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xtend.lib.annotations.Data;
import org.eclipse.xtend2.lib.StringConcatenation;
import org.eclipse.xtend2.lib.StringConcatenationClient;
import org.eclipse.xtext.xbase.lib.CollectionExtensions;
import org.eclipse.xtext.xbase.lib.CollectionLiterals;
import org.eclipse.xtext.xbase.lib.Conversions;
import org.eclipse.xtext.xbase.lib.Exceptions;
import org.eclipse.xtext.xbase.lib.Extension;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ListExtensions;
import org.eclipse.xtext.xbase.lib.Pair;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
import org.eclipse.xtext.xbase.lib.Pure;
import org.eclipse.xtext.xbase.lib.StringExtensions;
import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;

@SuppressWarnings("all")
public class IngesterGenerator {
  @Data
  public static class GeneratedIngesters {
    private final GeneratedNameAndSource generatedFactory;

    private final List generatedHandlers;

    private final List errors;

    public Map classNameToDef() {
      final HashMap classes = CollectionLiterals.newHashMap();
      classes.put(this.generatedFactory.getClassName(), this.generatedFactory.getSource());
      final Consumer _function = (GeneratedNameAndSource it) -> {
        classes.put(it.getClassName(), it.getSource());
      };
      this.generatedHandlers.forEach(_function);
      return classes;
    }

    public GeneratedIngesters(final GeneratedNameAndSource generatedFactory, final List generatedHandlers, final List errors) {
      super();
      this.generatedFactory = generatedFactory;
      this.generatedHandlers = generatedHandlers;
      this.errors = errors;
    }

    @Override
    @Pure
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((this.generatedFactory== null) ? 0 : this.generatedFactory.hashCode());
      result = prime * result + ((this.generatedHandlers== null) ? 0 : this.generatedHandlers.hashCode());
      return prime * result + ((this.errors== null) ? 0 : this.errors.hashCode());
    }

    @Override
    @Pure
    public boolean equals(final Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      IngesterGenerator.GeneratedIngesters other = (IngesterGenerator.GeneratedIngesters) obj;
      if (this.generatedFactory == null) {
        if (other.generatedFactory != null)
          return false;
      } else if (!this.generatedFactory.equals(other.generatedFactory))
        return false;
      if (this.generatedHandlers == null) {
        if (other.generatedHandlers != null)
          return false;
      } else if (!this.generatedHandlers.equals(other.generatedHandlers))
        return false;
      if (this.errors == null) {
        if (other.errors != null)
          return false;
      } else if (!this.errors.equals(other.errors))
        return false;
      return true;
    }

    @Override
    @Pure
    public String toString() {
      ToStringBuilder b = new ToStringBuilder(this);
      b.add("generatedFactory", this.generatedFactory);
      b.add("generatedHandlers", this.generatedHandlers);
      b.add("errors", this.errors);
      return b.toString();
    }

    @Pure
    public GeneratedNameAndSource getGeneratedFactory() {
      return this.generatedFactory;
    }

    @Pure
    public List getGeneratedHandlers() {
      return this.generatedHandlers;
    }

    @Pure
    public List getErrors() {
      return this.errors;
    }
  }

  @Data
  public static class ParseHandlersAndMappingErrors {
    private final List parseHandlers;

    private final List errors;

    public ParseHandlersAndMappingErrors(final List parseHandlers, final List errors) {
      super();
      this.parseHandlers = parseHandlers;
      this.errors = errors;
    }

    @Override
    @Pure
    public int hashCode() {
      final int prime = 31;
      int result = 1;
      result = prime * result + ((this.parseHandlers== null) ? 0 : this.parseHandlers.hashCode());
      return prime * result + ((this.errors== null) ? 0 : this.errors.hashCode());
    }

    @Override
    @Pure
    public boolean equals(final Object obj) {
      if (this == obj)
        return true;
      if (obj == null)
        return false;
      if (getClass() != obj.getClass())
        return false;
      IngesterGenerator.ParseHandlersAndMappingErrors other = (IngesterGenerator.ParseHandlersAndMappingErrors) obj;
      if (this.parseHandlers == null) {
        if (other.parseHandlers != null)
          return false;
      } else if (!this.parseHandlers.equals(other.parseHandlers))
        return false;
      if (this.errors == null) {
        if (other.errors != null)
          return false;
      } else if (!this.errors.equals(other.errors))
        return false;
      return true;
    }

    @Override
    @Pure
    public String toString() {
      ToStringBuilder b = new ToStringBuilder(this);
      b.add("parseHandlers", this.parseHandlers);
      b.add("errors", this.errors);
      return b.toString();
    }

    @Pure
    public List getParseHandlers() {
      return this.parseHandlers;
    }

    @Pure
    public List getErrors() {
      return this.errors;
    }
  }

  public static class UniqueFilter implements Predicate {
    private Set seen = CollectionLiterals.newHashSet();

    private Function propExtract;

    public UniqueFilter(final Function propExt) {
      this.propExtract = propExt;
    }

    @Override
    public boolean test(final T t) {
      return this.seen.add(this.propExtract.apply(t));
    }
  }

  private static final Logger LOGGER = Logger.getLogger(IngesterGenerator.class);

  public static final MetricRegistry GENERATOR_METRICS = new MetricRegistry();

  @Inject
  @Extension
  private JavaTypeTranslator typeTranslator;

  @Inject
  private JsonSchemaParser jsonSchemaParser;

  @Inject
  private RBuiltinTypeService builtins;

  public IngesterGenerator.GeneratedIngesters generateXml(final String envName, final String factoryName, final List generatorParamsList) {
    BeansXsdParser _beansXsdParser = new BeansXsdParser();
    final IngesterGenerator.ParseHandlersAndMappingErrors handlersAndErrors = this.parseHandlersAndMappingErrors(_beansXsdParser, generatorParamsList);
    final String factory = this.generateXmlFactory(envName, factoryName, generatorParamsList);
    GenerationResult _generationResult = new GenerationResult(false, factory);
    GeneratedNameAndSource _generatedNameAndSource = new GeneratedNameAndSource(((envName + ".") + factoryName), _generationResult);
    return new IngesterGenerator.GeneratedIngesters(_generatedNameAndSource, 
      handlersAndErrors.parseHandlers, 
      handlersAndErrors.errors);
  }

  public IngesterGenerator.GeneratedIngesters generateJson(final String envName, final String factoryName, final List generatorParamsList) {
    String _simpleName = this.jsonSchemaParser.getClass().getSimpleName();
    String _plus = ("JSON model parser " + _simpleName);
    IngesterGenerator.LOGGER.info(_plus);
    final IngesterGenerator.ParseHandlersAndMappingErrors handlersAndErrors = this.parseHandlersAndMappingErrors(this.jsonSchemaParser, generatorParamsList);
    final String factory = this.generateJsonFactory(envName, factoryName, generatorParamsList);
    GenerationResult _generationResult = new GenerationResult(false, factory);
    GeneratedNameAndSource _generatedNameAndSource = new GeneratedNameAndSource(((envName + ".") + factoryName), _generationResult);
    return new IngesterGenerator.GeneratedIngesters(_generatedNameAndSource, 
      handlersAndErrors.parseHandlers, 
      handlersAndErrors.errors);
  }

  private IngesterGenerator.ParseHandlersAndMappingErrors parseHandlersAndMappingErrors(final ModelParser modelParser, final List params) {
    IngesterGenerator.ParseHandlersAndMappingErrors _xblockexpression = null;
    {
      final ArrayList parseHandlers = CollectionLiterals.newArrayList();
      final ArrayList errors = CollectionLiterals.newArrayList();
      for (final GeneratorParams param : params) {
        {
          final Pair, Collection> parsers = this.generateParsers(modelParser, 
            param.getSchema(), 
            param.getRosettaEntities(), 
            param.getSources(), 
            param.getTopLevelTags(), 
            param.getChildPackageName());
          final Function1, GeneratedNameAndSource> _function = (Map.Entry it) -> {
            String _childPackageName = param.getChildPackageName();
            String _plus = (_childPackageName + ".");
            String _key = it.getKey();
            String _plus_1 = (_plus + _key);
            String _plus_2 = (_plus_1 + "ParseHandler");
            GenerationResult _value = it.getValue();
            return new GeneratedNameAndSource(_plus_2, _value);
          };
          Iterables.addAll(parseHandlers, IterableExtensions., GeneratedNameAndSource>map(parsers.getKey().entrySet(), _function));
          errors.addAll(parsers.getValue());
        }
      }
      _xblockexpression = new IngesterGenerator.ParseHandlersAndMappingErrors(parseHandlers, errors);
    }
    return _xblockexpression;
  }

  private Pair, Collection> generateParsers(final ModelParser modelParser, final URL modelUrl, final Collection rosettaEntities, final Collection sources, final Collection topLevelTags, final String childPackageName) {
    Pair, Collection> _xblockexpression = null;
    {
      final Schema schema = this.getSchema(modelParser, modelUrl, childPackageName);
      _xblockexpression = this.generateParsers(sources, rosettaEntities, schema, topLevelTags, childPackageName);
    }
    return _xblockexpression;
  }

  public Schema getSchema(final ModelParser modelParser, final URL modelUrl, final String childPackageName) {
    try {
      Schema _xblockexpression = null;
      {
        String _baseFileName = UrlUtils.getBaseFileName(modelUrl);
        final String jschemaFileName = (_baseFileName + ".schema");
        final URL schemaURL = new URL(modelUrl, jschemaFileName);
        try {
          final long loadStart = System.currentTimeMillis();
          final SchemaDeserialise deserial = new SchemaDeserialise();
          Object _deserialise = deserial.deserialise(schemaURL.openStream());
          final Schema schema = ((Schema) _deserialise);
          long _currentTimeMillis = System.currentTimeMillis();
          long _minus = (_currentTimeMillis - loadStart);
          String _plus = ((("Loaded schema from file " + schemaURL) + " in ") + Long.valueOf(_minus));
          IngesterGenerator.LOGGER.info(_plus);
          return schema;
        } catch (final Throwable _t) {
          if (_t instanceof IOException || _t instanceof CustomDeserialise.ParseException) {
            IngesterGenerator.LOGGER.info(("Failed to read schema file from " + schemaURL));
          } else {
            throw Exceptions.sneakyThrow(_t);
          }
        }
        String _xifexpression = null;
        String _lowerCase = UrlUtils.getFileExtension(modelUrl).toLowerCase();
        boolean _equals = Objects.equal(_lowerCase, "xsd");
        if (_equals) {
          _xifexpression = "XSD";
        } else {
          _xifexpression = "JSON";
        }
        final String type = _xifexpression;
        IngesterGenerator.LOGGER.info(((("Parsing " + type) + " model for ") + childPackageName));
        final Schema schema = modelParser.parseModel(modelUrl);
        boolean _isOpaque = schemaURL.toURI().isOpaque();
        boolean _not = (!_isOpaque);
        if (_not) {
          URI _uRI = schemaURL.toURI();
          final File schemaFile = new File(_uRI);
          final SchemaSerialise serialise = new SchemaSerialise();
          FileOutputStream _fileOutputStream = new FileOutputStream(schemaFile);
          serialise.serialiseObject(schema, _fileOutputStream);
        }
        _xblockexpression = schema;
      }
      return _xblockexpression;
    } catch (Throwable _e) {
      throw Exceptions.sneakyThrow(_e);
    }
  }

  public Pair, Collection> generateParsers(final Collection sources, final Collection rosettaEntities, final Schema schema, final Collection topLevelTags, final String childPackageName) {
    IngesterGenerator.LOGGER.info("Building synonym map");
    final List synonymSourceNames = GeneratorUtil.synonymSourceNames(sources);
    final List externalSynonyms = GeneratorUtil.externalSynonymSources(sources);
    final SynonymMapBuilder mappingBuilder = new SynonymMapBuilder(synonymSourceNames, externalSynonyms, this.typeTranslator);
    HashMap _hashMap = new HashMap();
    return this.generateParsers(mappingBuilder, sources, rosettaEntities, schema, topLevelTags, childPackageName, _hashMap);
  }

  public Pair, Collection> generateParsers(final SynonymMapBuilder mappingBuilder, final Collection sources, final Collection rosettaEntities, final Schema schema, final Collection topLevelTags, final String childPackageName, final Map synHashCache) {
    final Function1 _function = (RosettaType c) -> {
      return mappingBuilder.buildMap(c);
    };
    List syns = IterableExtensions.toList(IterableExtensions.map(rosettaEntities, _function));
    IngesterGenerator.LOGGER.info("Validating synonyms");
    final ModelCombiner combiner = new ModelCombiner();
    final ArrayList combineErrors = CollectionLiterals.newArrayList();
    syns = combiner.combineModels(schema, syns, combineErrors, topLevelTags);
    IngesterGenerator.LOGGER.info("Pruning synonyms");
    syns = combiner.prune(syns);
    final Predicate _function_1 = (MappingError e) -> {
      MappingError.MappingErrorLevel _level = e.getLevel();
      return Objects.equal(_level, MappingError.MappingErrorLevel.ERROR);
    };
    boolean _anyMatch = combineErrors.stream().anyMatch(_function_1);
    if (_anyMatch) {
    }
    IngesterGenerator.LOGGER.info("Checking cardinalities");
    combineErrors.addAll(new CardinalityChecker().checkCardinalities(syns));
    Map _generateParsers = this.generateParsers(syns, sources, childPackageName, synHashCache);
    return new Pair, Collection>(_generateParsers, combineErrors);
  }

  public Map generateParsers(final Collection topLevels, final Collection sources, final String childName, final Map synHashCache) {
    IngesterGenerator.LOGGER.debug("Creating java files");
    final Map generated = new HashMap();
    for (final SynonymMap mapping : topLevels) {
      this.generateParsers(mapping, generated, sources, childName, synHashCache);
    }
    return generated;
  }

  private void generateParsers(final SynonymMap mapping, final Map generated, final Collection sources, final String childPackageName, final Map synHashCache) {
    boolean _containsKey = generated.containsKey(mapping.getRosetta().getName());
    if (_containsKey) {
      return;
    }
    boolean _isClassOrData = this.isClassOrData(mapping.getRosetta());
    if (_isClassOrData) {
      this.generateClassParsers(mapping, generated, sources, childPackageName, synHashCache);
    } else {
      RosettaType _rosetta = mapping.getRosetta();
      if ((_rosetta instanceof RosettaEnumeration)) {
        this.generateEnumParsers(mapping, generated, childPackageName, synHashCache);
      }
    }
  }

  private boolean validNamespaces(final RosettaModel model, final String importedNamespace) {
    Set _xifexpression = null;
    ResourceSet _resourceSet = model.eResource().getResourceSet();
    EList _resources = null;
    if (_resourceSet!=null) {
      _resources=_resourceSet.getResources();
    }
    boolean _tripleEquals = (_resources == null);
    if (_tripleEquals) {
      HashSet _xblockexpression = null;
      {
        String _string = model.eResource().getURI().toString();
        String _plus = ("No resource set found for " + _string);
        IngesterGenerator.LOGGER.warn(_plus);
        _xblockexpression = CollectionLiterals.newHashSet();
      }
      _xifexpression = _xblockexpression;
    } else {
      final Function1> _function = (Resource it) -> {
        return it.getContents();
      };
      final Function1> _function_1 = (RosettaModel it) -> {
        return it.getElements();
      };
      final Function1 _function_2 = (RosettaRootElement it) -> {
        return Boolean.valueOf(((it instanceof com.regnosys.rosetta.rosetta.simple.Data) || (it instanceof RosettaEnumeration)));
      };
      final Function1 _function_3 = (RosettaRootElement it) -> {
        return RosettaType.class.cast(it);
      };
      final Function1 _function_4 = (RosettaType it) -> {
        return it.getModel().getName();
      };
      _xifexpression = IterableExtensions.toSet(IterableExtensions.map(IterableExtensions.map(IterableExtensions.filter(IterableExtensions.flatMap(Iterables.filter(IterableExtensions.flatMap(model.eResource().getResourceSet().getResources(), _function), RosettaModel.class), _function_1), _function_2), _function_3), _function_4));
    }
    final Set validNamespacesSet = _xifexpression;
    final String namespace = importedNamespace.substring(0, this.indexOrLength(importedNamespace, '.'));
    return validNamespacesSet.contains(namespace);
  }

  private int indexOrLength(final String toSearch, final char find) {
    int _xblockexpression = (int) 0;
    {
      final int index = toSearch.lastIndexOf(find);
      int _xifexpression = (int) 0;
      if ((index == (-1))) {
        _xifexpression = toSearch.length();
      } else {
        _xifexpression = index;
      }
      _xblockexpression = _xifexpression;
    }
    return _xblockexpression;
  }

  private void generateClassParsers(final SynonymMap mapping, final Map generated, final Collection synonymSources, final String envName, final Map synHashCache) {
    boolean _containsKey = generated.containsKey(IterableUtil.fullname(mapping.getRosetta()));
    if (_containsKey) {
      return;
    }
    EObject _eContainer = mapping.getRosetta().eContainer();
    final RosettaModel rosettaModel = ((RosettaModel) _eContainer);
    Resource _eResource = rosettaModel.eResource();
    boolean _tripleEquals = (_eResource == null);
    if (_tripleEquals) {
      IngesterGenerator.LOGGER.warn(("Unable to generate translate parsers. No resource found for rosetta model: " + rosettaModel));
      return;
    }
    final Long prevHash = synHashCache.get(IterableUtil.fullname(mapping.getRosetta()));
    final long newHash = mapping.hashForGeneration();
    if (((prevHash == null) || (newHash != (prevHash).longValue()))) {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("package ");
      _builder.append(envName);
      _builder.append(".");
      String _packageName = IterableUtil.packageName(mapping.getRosetta());
      _builder.append(_packageName);
      _builder.append(";");
      _builder.newLineIfNotEmpty();
      _builder.newLine();
      _builder.append("import java.math.BigDecimal;");
      _builder.newLine();
      _builder.append("import java.time.LocalDate;");
      _builder.newLine();
      _builder.append("import java.time.LocalTime;");
      _builder.newLine();
      _builder.append("import java.util.Collections;");
      _builder.newLine();
      _builder.append("import java.util.ArrayList;");
      _builder.newLine();
      _builder.append("import java.util.List;");
      _builder.newLine();
      _builder.append("import java.util.Set;");
      _builder.newLine();
      _builder.append("import java.util.Optional;");
      _builder.newLine();
      _builder.append("import java.util.Map;");
      _builder.newLine();
      _builder.append("import java.util.HashMap;");
      _builder.newLine();
      _builder.append("import java.util.LinkedHashMap;");
      _builder.newLine();
      _builder.append("import java.util.concurrent.atomic.AtomicBoolean;");
      _builder.newLine();
      _builder.append("import java.util.stream.Collectors;");
      _builder.newLine();
      _builder.newLine();
      _builder.append("import com.google.common.collect.ImmutableList;");
      _builder.newLine();
      _builder.append("import com.google.common.collect.ImmutableMultimap;");
      _builder.newLine();
      _builder.append("import com.google.inject.Injector;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.translate.HandlerSupplier;");
      _builder.newLine();
      _builder.append("import com.rosetta.model.lib.meta.Reference;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.translate.GeneratorPathUtil;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.translate.HandlerCache;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.translate.IngestMerger;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.translate.MappingProcessorSupplier;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.translate.SynonymValueGroup;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.translate.ROMParseHandler;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.common.translation.Mapping;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.common.translation.MappingContext;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.common.translation.Path;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.common.util.PathUtils;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.translate.basic.*;");
      _builder.newLine();
      _builder.append("import com.regnosys.rosetta.common.translation.Path.PathElement;");
      _builder.newLine();
      {
        EList _imports = rosettaModel.getImports();
        for(final Import importResources : _imports) {
          final String importedNamespace = importResources.getImportedNamespace();
          _builder.newLineIfNotEmpty();
          {
            boolean _validNamespaces = this.validNamespaces(rosettaModel, importedNamespace);
            if (_validNamespaces) {
              _builder.append("import ");
              _builder.append(importedNamespace);
              _builder.append(";");
              _builder.newLineIfNotEmpty();
            }
          }
        }
      }
      _builder.append("import ");
      String _name = rosettaModel.getName();
      _builder.append(_name);
      _builder.append(".*;");
      _builder.newLineIfNotEmpty();
      _builder.newLine();
      {
        List _traversedImports = this.getTraversedImports(mapping);
        for(final String traversedImports : _traversedImports) {
          _builder.append("import ");
          _builder.append(traversedImports);
          _builder.append(";");
          _builder.newLineIfNotEmpty();
        }
      }
      _builder.newLine();
      _builder.append("import com.rosetta.model.lib.records.*;");
      _builder.newLine();
      _builder.append("import com.rosetta.model.lib.RosettaModelObjectBuilder;");
      _builder.newLine();
      _builder.append("import com.rosetta.model.lib.path.RosettaPath;");
      _builder.newLine();
      _builder.append("import com.rosetta.model.lib.process.BuilderProcessor;");
      _builder.newLine();
      _builder.append("import com.rosetta.model.metafields.MetaFields;");
      _builder.newLine();
      _builder.newLine();
      final String header = _builder.toString();
      StringConcatenation _builder_1 = new StringConcatenation();
      _builder_1.append("public ");
      {
        boolean _isAbstract = this.isAbstract(mapping.getRosetta());
        if (_isAbstract) {
          _builder_1.append("abstract ");
        }
      }
      _builder_1.append("class ");
      CharSequence _pNameW = this.pNameW(mapping);
      _builder_1.append(_pNameW);
      _builder_1.append(" ");
      CharSequence _romExtends = this.romExtends(mapping, envName);
      _builder_1.append(_romExtends);
      _builder_1.append(" {");
      _builder_1.newLineIfNotEmpty();
      _builder_1.append("\t");
      _builder_1.newLine();
      _builder_1.append("\t");
      String _pathConstants = this.pathConstants(mapping);
      _builder_1.append(_pathConstants, "\t");
      _builder_1.newLineIfNotEmpty();
      _builder_1.append("\t");
      _builder_1.newLine();
      _builder_1.append("\t");
      CharSequence _conditionalValues = this.conditionalValues(mapping);
      _builder_1.append(_conditionalValues, "\t");
      _builder_1.newLineIfNotEmpty();
      _builder_1.append("\t");
      _builder_1.newLine();
      _builder_1.append("\t");
      CharSequence _handlerCaches = this.handlerCaches(mapping, envName);
      _builder_1.append(_handlerCaches, "\t");
      _builder_1.newLineIfNotEmpty();
      _builder_1.append("\t");
      _builder_1.newLine();
      _builder_1.append("\t");
      CharSequence _constructor = this.constructor(mapping);
      _builder_1.append(_constructor, "\t");
      _builder_1.newLineIfNotEmpty();
      _builder_1.append("\t");
      _builder_1.newLine();
      _builder_1.append("\t");
      _builder_1.append("// regular handlers");
      _builder_1.newLine();
      {
        final Function1 _function = (AttributeGroupMapping it) -> {
          final Function1 _function_1 = (SynonymGroup it_1) -> {
            return Boolean.valueOf(((!it_1.getSynonymValues().isEmpty()) && IterableExtensions.forall(it_1.getConditions(), ((Function1) (SynonymCondition it_2) -> {
              return Boolean.valueOf(it_2.getCondition().isEmpty());
            }))));
          };
          return Boolean.valueOf(IterableExtensions.exists(it.getGroup().getSynonymGroups(), _function_1));
        };
        final Function1 _function_1 = (AttributeGroupMapping it) -> {
          return it.getGroup();
        };
        final Function1 _function_2 = (AttributeGroupMapping it) -> {
          return this.toHandlerMethodName(it.getGroup());
        };
        List _sortBy = IterableExtensions.sortBy(IterableExtensions.sortBy(IterableExtensions.filter(mapping.getMappedGroups(), _function), _function_1), _function_2);
        boolean _hasElements = false;
        for(final AttributeGroupMapping h : _sortBy) {
          if (!_hasElements) {
            _hasElements = true;
          } else {
            _builder_1.appendImmediate("\n", "\t");
          }
          _builder_1.append("\t");
          CharSequence _handler = this.handler(h, mapping, envName);
          _builder_1.append(_handler, "\t");
          _builder_1.newLineIfNotEmpty();
        }
      }
      _builder_1.append("\t");
      _builder_1.newLine();
      _builder_1.append("\t");
      _builder_1.append("// conditional handlers");
      _builder_1.newLine();
      {
        final Function1 _function_3 = (AttributeGroupMapping it) -> {
          final Function1 _function_4 = (SynonymGroup it_1) -> {
            return Boolean.valueOf(((!it_1.getSynonymValues().isEmpty()) && IterableExtensions.exists(it_1.getConditions(), ((Function1) (SynonymCondition it_2) -> {
              boolean _isEmpty = it_2.getCondition().isEmpty();
              return Boolean.valueOf((!_isEmpty));
            }))));
          };
          return Boolean.valueOf(IterableExtensions.exists(it.getGroup().getSynonymGroups(), _function_4));
        };
        final Function1 _function_4 = (AttributeGroupMapping it) -> {
          return it.getGroup();
        };
        List _sortBy_1 = IterableExtensions.sortBy(IterableExtensions.filter(mapping.getMappedGroups(), _function_3), _function_4);
        boolean _hasElements_1 = false;
        for(final AttributeGroupMapping h_1 : _sortBy_1) {
          if (!_hasElements_1) {
            _hasElements_1 = true;
          } else {
            _builder_1.appendImmediate("\n", "\t");
          }
          _builder_1.append("\t");
          CharSequence _condHandler = this.condHandler(h_1, mapping, envName);
          _builder_1.append(_condHandler, "\t");
          _builder_1.newLineIfNotEmpty();
        }
      }
      _builder_1.append("\t");
      _builder_1.newLine();
      _builder_1.append("\t");
      _builder_1.append("// conditional capture handlers");
      _builder_1.newLine();
      {
        final Function1>, String> _function_5 = (Map.Entry> e) -> {
          return this.toConditionalHandlerMethodName(e.getKey());
        };
        List>> _sortBy_2 = IterableExtensions.>, String>sortBy(mapping.getConditionalCaptures().asMap().entrySet(), _function_5);
        boolean _hasElements_2 = false;
        for(final Map.Entry> ent : _sortBy_2) {
          if (!_hasElements_2) {
            _hasElements_2 = true;
          } else {
            _builder_1.appendImmediate("\n", "\t");
          }
          _builder_1.append("\t");
          CharSequence _conditionalCaptureHandler = this.conditionalCaptureHandler(ent, mapping);
          _builder_1.append(_conditionalCaptureHandler, "\t");
          _builder_1.newLineIfNotEmpty();
        }
      }
      _builder_1.append("\t");
      _builder_1.newLine();
      _builder_1.append("\t");
      _builder_1.append("// regular handler getter (for nested \'set to\' conditional mapping with path predicate)");
      _builder_1.newLine();
      _builder_1.append("\t");
      final HashSet alreadyGenerated = CollectionLiterals.newHashSet();
      _builder_1.newLineIfNotEmpty();
      {
        final Function1 _function_6 = (AttributeGroupMapping it) -> {
          final Function1 _function_7 = (SynonymGroup it_1) -> {
            return Boolean.valueOf(it_1.getSynonymValues().isEmpty());
          };
          return Boolean.valueOf(IterableExtensions.exists(it.getGroup().getSynonymGroups(), _function_7));
        };
        final Function1 _function_7 = (AttributeGroupMapping it) -> {
          final Function1> _function_8 = (SynonymGroup it_1) -> {
            return it_1.getConditions();
          };
          final Function1> _function_9 = (SynonymCondition it_1) -> {
            return it_1.getCondition();
          };
          final Function1 _function_10 = (SynonymTest it_1) -> {
            return Boolean.valueOf((it_1 instanceof SynonymPathTest));
          };
          return Boolean.valueOf(IterableExtensions.exists(IterableExtensions.flatMap(IterableExtensions.flatMap(it.getGroup().getSynonymGroups(), _function_8), _function_9), _function_10));
        };
        final Function1> _function_8 = (AttributeGroupMapping it) -> {
          return it.getGroup().getAttributePath();
        };
        final Function1, Boolean> _function_9 = (List it) -> {
          int _size = it.size();
          return Boolean.valueOf((_size > 1));
        };
        Iterable> _filter = IterableExtensions.>filter(IterableExtensions.>map(IterableExtensions.filter(IterableExtensions.filter(mapping.getMappedGroups(), _function_6), _function_7), _function_8), _function_9);
        boolean _hasElements_3 = false;
        for(final List p : _filter) {
          if (!_hasElements_3) {
            _hasElements_3 = true;
          } else {
            _builder_1.appendImmediate("\n", "\t");
          }
          _builder_1.append("\t");
          CharSequence _nestedSetToHandler = this.nestedSetToHandler(p, mapping, alreadyGenerated);
          _builder_1.append(_nestedSetToHandler, "\t");
          _builder_1.newLineIfNotEmpty();
        }
      }
      _builder_1.append("\t");
      _builder_1.newLine();
      _builder_1.append("\t");
      _builder_1.append("// mappers");
      _builder_1.newLine();
      {
        final Function1 _function_10 = (AttributeGroupMapping it) -> {
          final Function1 _function_11 = (SynonymGroup it_1) -> {
            String _mapperName = it_1.getMapperName();
            return Boolean.valueOf((_mapperName != null));
          };
          return Boolean.valueOf(IterableExtensions.exists(it.getGroup().getSynonymGroups(), _function_11));
        };
        final Function1 _function_11 = (AttributeGroupMapping it) -> {
          return it.getGroup();
        };
        List _sortBy_3 = IterableExtensions.sortBy(IterableExtensions.filter(mapping.getMappedGroups(), _function_10), _function_11);
        boolean _hasElements_4 = false;
        for(final AttributeGroupMapping h_2 : _sortBy_3) {
          if (!_hasElements_4) {
            _hasElements_4 = true;
          } else {
            _builder_1.appendImmediate("\n", "\t");
          }
          _builder_1.append("\t");
          CharSequence _mappingProcessor = this.mappingProcessor(h_2, mapping);
          _builder_1.append(_mappingProcessor, "\t");
          _builder_1.newLineIfNotEmpty();
        }
      }
      _builder_1.append("\t");
      _builder_1.newLine();
      {
        boolean _isAbstract_1 = this.isAbstract(mapping.getRosetta());
        boolean _not = (!_isAbstract_1);
        if (_not) {
          _builder_1.append("\t");
          _builder_1.append("// builder proxy");
          _builder_1.newLine();
          _builder_1.append("\t");
          CharSequence _generateBuilderProxy = this.generateBuilderProxy(mapping);
          _builder_1.append(_generateBuilderProxy, "\t");
          _builder_1.newLineIfNotEmpty();
        }
      }
      _builder_1.append("}");
      _builder_1.newLine();
      final String body = _builder_1.toString();
      StringConcatenation _builder_3 = new StringConcatenation();
      _builder_3.append(header);
      _builder_3.newLineIfNotEmpty();
      _builder_3.newLine();
      _builder_3.append(body);
      _builder_3.newLineIfNotEmpty();
      String parser = _builder_3.toString();
      String _fullname = IterableUtil.fullname(mapping.getRosetta());
      GenerationResult _generationResult = new GenerationResult(false, parser);
      generated.put(_fullname, _generationResult);
      synHashCache.put(IterableUtil.fullname(mapping.getRosetta()), Long.valueOf(newHash));
    } else {
      String _fullname_1 = IterableUtil.fullname(mapping.getRosetta());
      GenerationResult _generationResult_1 = new GenerationResult(true, null);
      generated.put(_fullname_1, _generationResult_1);
    }
    SynonymMap _superMap = mapping.getSuperMap();
    boolean _tripleNotEquals = (_superMap != null);
    if (_tripleNotEquals) {
      this.generateParsers(mapping.getSuperMap(), generated, synonymSources, envName, synHashCache);
    }
    Collection _childMappings = mapping.childMappings();
    for (final SynonymMap subParser : _childMappings) {
      RosettaType _rosetta = subParser.getRosetta();
      boolean _tripleNotEquals_1 = (_rosetta != null);
      if (_tripleNotEquals_1) {
        this.generateParsers(subParser, generated, synonymSources, envName, synHashCache);
      }
    }
  }

  private List getTraversedImports(final SynonymMap mapping) {
    final Function1> _function = (AttributeGroup it) -> {
      return it.getAttributePath();
    };
    final Function1 _function_1 = (ExpandedAttribute it) -> {
      TypeCall _rosettaType = it.getRosettaType();
      RosettaType _type = null;
      if (_rosettaType!=null) {
        _type=_rosettaType.getType();
      }
      return Boolean.valueOf((_type != null));
    };
    final Function1 _function_2 = (ExpandedAttribute it) -> {
      TypeCall _rosettaType = it.getRosettaType();
      RosettaType _type = null;
      if (_rosettaType!=null) {
        _type=_rosettaType.getType();
      }
      boolean _isBuiltInType = RosettaAttributeExtensions.toExpandedType(_type).isBuiltInType();
      return Boolean.valueOf((!_isBuiltInType));
    };
    final Function1 _function_3 = (ExpandedAttribute it) -> {
      RosettaModel _model = it.getType().getModel();
      return Boolean.valueOf((_model != null));
    };
    final Function1 _function_4 = (ExpandedAttribute it) -> {
      String _name = it.getType().getModel().getName();
      String _plus = (_name + ".");
      String _name_1 = it.getType().getName();
      return (_plus + _name_1);
    };
    return IterableExtensions.sort(IterableUtil.distinct(IterableExtensions.map(IterableExtensions.filter(IterableExtensions.filter(IterableExtensions.filter(IterableExtensions.flatMap(mapping.attributeGroups(), _function), _function_1), _function_2), _function_3), _function_4)));
  }

  protected boolean _isAbstract(final RosettaType type) {
    return true;
  }

  protected boolean _isAbstract(final com.regnosys.rosetta.rosetta.simple.Data type) {
    return false;
  }

  public Multimap captureList(final List groups) {
    final Multimap conditionals = LinkedListMultimap.create();
    for (final SynonymGroup sg : groups) {
      List _synonymValues = sg.getSynonymValues();
      for (final SynonymValue sv : _synonymValues) {
        conditionals.putAll(sv, sg.getConditions());
      }
    }
    return conditionals;
  }

  private String toPathName(final SynonymValue synonymValue) {
    final Function1 _function = (Element it) -> {
      return it.getName();
    };
    return StringExtensions.toFirstLower(IterableExtensions.join(ListExtensions.map(synonymValue.getSynonymPath(), _function), "_"));
  }

  private CharSequence romExtends(final SynonymMap mapping, final String envName) {
    CharSequence _xifexpression = null;
    SynonymMap _superMap = mapping.getSuperMap();
    boolean _tripleEquals = (_superMap == null);
    if (_tripleEquals) {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("extends ROMParseHandler");
      _xifexpression = _builder;
    } else {
      StringConcatenation _builder_1 = new StringConcatenation();
      _builder_1.append("extends ");
      CharSequence _pFullNameW = this.pFullNameW(mapping.getSuperMap(), envName);
      _builder_1.append(_pFullNameW);
      _builder_1.append("");
      _xifexpression = _builder_1;
    }
    return _xifexpression;
  }

  private CharSequence pNameW(final SynonymMap mapping) {
    return this.pNameW(mapping.getRosetta());
  }

  private CharSequence pFullNameT(final SynonymMap mapping, final String packageName) {
    return this.pFullNameT(mapping.getRosetta(), packageName);
  }

  private CharSequence pNameW(final RosettaType rosetta) {
    StringConcatenation _builder = new StringConcatenation();
    String _name = rosetta.getName();
    _builder.append(_name);
    _builder.append("ParseHandler");
    return _builder;
  }

  private CharSequence pFullNameT(final ExpandedType rosetta, final String envName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append(envName);
    _builder.append(".");
    String _name = rosetta.getModel().getName();
    _builder.append(_name);
    _builder.append(".");
    String _name_1 = rosetta.getName();
    _builder.append(_name_1);
    return _builder;
  }

  private CharSequence pFullNameW(final ExpandedType rosetta, final String envName) {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _pFullNameT = this.pFullNameT(rosetta, envName);
    _builder.append(_pFullNameT);
    _builder.append("ParseHandler");
    return _builder;
  }

  private CharSequence pFullNameW(final SynonymMap mapping, final String envName) {
    return this.pFullNameW(mapping.getRosetta(), envName);
  }

  private CharSequence pFullNameW(final RosettaType rosetta, final String envName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append(envName);
    _builder.append(".");
    String _fullname = IterableUtil.fullname(rosetta);
    _builder.append(_fullname);
    _builder.append("ParseHandler");
    return _builder;
  }

  private CharSequence pFullNameT(final RosettaType rosetta, final String envName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append(envName);
    _builder.append(".");
    String _fullname = IterableUtil.fullname(rosetta);
    _builder.append(_fullname);
    _builder.append("ParseHandler<");
    StringConcatenationClient _builder_1 = this.toBuilder(rosetta);
    _builder.append(_builder_1);
    _builder.append(">");
    return _builder;
  }

  private CharSequence expandedTypeToBuilder(final ExpandedType type) {
    CharSequence _xifexpression = null;
    boolean _isType = type.isType();
    if (_isType) {
      StringConcatenation _builder = new StringConcatenation();
      JavaClass _expandedTypeToJavaType = this.expandedTypeToJavaType(type);
      JavaClass _builderType = this.typeTranslator.toBuilderType(((JavaClass) _expandedTypeToJavaType));
      _builder.append(_builderType);
      _xifexpression = _builder;
    } else {
      StringConcatenation _builder_1 = new StringConcatenation();
      JavaClass _expandedTypeToJavaType_1 = this.expandedTypeToJavaType(type);
      _builder_1.append(_expandedTypeToJavaType_1);
      _xifexpression = _builder_1;
    }
    return _xifexpression;
  }

  @Inject
  private RosettaJavaPackages packages;

  @Inject
  private JavaTypeUtil typeUtil;

  private JavaClass expandedTypeToJavaType(final ExpandedType type) {
    if ((Objects.equal(type.getName(), RosettaAttributeExtensions.METAFIELDS_CLASS_NAME) || Objects.equal(type, RosettaAttributeExtensions.META_AND_TEMPLATE_FIELDS_CLASS_NAME))) {
      DottedPath _basicMetafields = this.packages.basicMetafields();
      String _name = type.getName();
      return new GeneratedJavaClass(_basicMetafields, _name, Object.class);
    }
    boolean _isMetaType = type.isMetaType();
    if (_isMetaType) {
      return this.typeUtil.STRING;
    }
    boolean _isBuiltInType = type.isBuiltInType();
    if (_isBuiltInType) {
      return this.typeTranslator.toJavaReferenceType(this.builtins.getType(type.getName(), Collections.emptyMap()));
    }
    DottedPath _modelPackage = this.modelPackage(type.getModel());
    String _name_1 = type.getName();
    return new GeneratedJavaClass(_modelPackage, _name_1, Object.class);
  }

  private DottedPath modelPackage(final RosettaModel model) {
    return DottedPath.splitOnDots(model.getName());
  }

  private StringConcatenationClient _toBuilder(final com.regnosys.rosetta.rosetta.simple.Data type) {
    StringConcatenationClient _xblockexpression = null;
    {
      boolean _endsWith = type.getName().endsWith("WithMeta");
      if (_endsWith) {
        StringConcatenationClient _client = new StringConcatenationClient() {
          @Override
          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
            String _fullname = IterableUtil.fullname(type);
            _builder.append(_fullname);
            _builder.append(".");
            String _name = type.getName();
            _builder.append(_name);
            _builder.append("Builder");
            String _firstUpper = StringExtensions.toFirstUpper(type.getDefinition());
            _builder.append(_firstUpper);
          }
        };
        return _client;
      }
      StringConcatenationClient _client_1 = new StringConcatenationClient() {
        @Override
        protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
          String _fullname = IterableUtil.fullname(type);
          _builder.append(_fullname);
          _builder.append(".");
          String _name = type.getName();
          _builder.append(_name);
          _builder.append("Builder");
        }
      };
      _xblockexpression = _client_1;
    }
    return _xblockexpression;
  }

  private StringConcatenationClient _toBuilder(final RosettaEnumeration type) {
    StringConcatenationClient _client = new StringConcatenationClient() {
      @Override
      protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
        String _name = type.getName();
        _builder.append(_name);
      }
    };
    return _client;
  }

  private StringConcatenationClient _toBuilder(final RosettaBuiltinType type) {
    StringConcatenationClient _client = new StringConcatenationClient() {
      @Override
      protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
        Optional _type = IngesterGenerator.this.builtins.getType(type.getName(), CollectionLiterals.newHashMap());
        _builder.append(_type);
      }
    };
    return _client;
  }

  private StringConcatenationClient _toBuilder(final RosettaTypeAlias type) {
    return this.toBuilder(type.getTypeCall().getType());
  }

  private String pathConstants(final SynonymMap mapping) {
    final LinkedHashSet svs = new LinkedHashSet();
    final Function1> _function = (AttributeGroup it) -> {
      return it.getSynonymGroups();
    };
    Iterables.addAll(svs, IterableExtensions.flatMap(mapping.attributeGroups(), _function));
    final Function1 _function_1 = (SynonymValue it) -> {
      List _singletonList = Collections.singletonList(it);
      List _emptyList = Collections.emptyList();
      return new SynonymGroup(_singletonList, _emptyList, null, null, null, null, false);
    };
    Iterables.addAll(svs, IterableExtensions.map(mapping.getConditionalCaptures().keySet(), _function_1));
    return this.pathConstants(svs);
  }

  private String pathConstants(final Iterable sgs) {
    final Function1> _function = (SynonymGroup it) -> {
      return it.getSynonymValues();
    };
    final Function1 _function_1 = (SynonymValue it) -> {
      return this.toPathName(it);
    };
    final Function1 _function_2 = (SynonymValue synonymValue) -> {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("private final static ImmutableList ");
      String _pathName = this.toPathName(synonymValue);
      _builder.append(_pathName);
      _builder.append("Path = ImmutableList.of(");
      CharSequence _list = this.list(synonymValue.getSynonymPath());
      _builder.append(_list);
      _builder.append(");");
      return _builder.toString();
    };
    return IterableExtensions.join(IterableUtil.distinct(ListExtensions.map(IterableExtensions.sortBy(IterableExtensions.flatMap(sgs, _function), _function_1), _function_2)), "\n");
  }

  /**
   * There are two types of temporary conditional values
   * one where a primitive typed mapping has a condition meaning that the value may or may not be used
   * the other where there is a path in a when clause and we need to capture the value of that path
   */
  private CharSequence conditionalValues(final SynonymMap mapping) {
    StringConcatenation _builder = new StringConcatenation();
    final Function1 _function = (AttributeGroup it) -> {
      return this.toAttPathName(it);
    };
    final List groups = IterableExtensions.sortBy(mapping.attributeGroups(), _function);
    _builder.newLineIfNotEmpty();
    {
      final Function1 _function_1 = (AttributeGroup it) -> {
        final Function1 _function_2 = (SynonymGroup it_1) -> {
          return Boolean.valueOf(((!it_1.getSynonymValues().isEmpty()) && IterableExtensions.exists(it_1.getConditions(), ((Function1) (SynonymCondition it_2) -> {
            boolean _isEmpty = it_2.getCondition().isEmpty();
            return Boolean.valueOf((!_isEmpty));
          }))));
        };
        return Boolean.valueOf(IterableExtensions.exists(it.getSynonymGroups(), _function_2));
      };
      Iterable _filter = IterableExtensions.filter(groups, _function_1);
      for(final AttributeGroup group : _filter) {
        _builder.append("protected Maplast(group.getAttributePath()).getType());
        _builder.append(_expandedTypeToBuilder);
        _builder.append("> ");
        String _attPathName = this.toAttPathName(group);
        _builder.append(_attPathName);
        _builder.append("Values = new LinkedHashMap<>();");
        _builder.newLineIfNotEmpty();
      }
    }
    {
      final Function1>, String> _function_2 = (Map.Entry> it) -> {
        return this.toPathName(it.getKey());
      };
      List>> _sortBy = IterableExtensions.>, String>sortBy(mapping.getConditionalCaptures().asMap().entrySet(), _function_2);
      for(final Map.Entry> e : _sortBy) {
        {
          final Function1 _function_3 = (Element it) -> {
            Cardinality _cardinality = it.getCardinality();
            return Boolean.valueOf((_cardinality == Cardinality.MULTIPLE));
          };
          boolean _exists = IterableExtensions.exists(e.getKey().getSynonymPath(), _function_3);
          if (_exists) {
            _builder.append("protected Map ");
            String _pathName = this.toPathName(e.getKey());
            _builder.append(_pathName);
            _builder.append("Values = new HashMap<>();");
            _builder.newLineIfNotEmpty();
          } else {
            _builder.append("protected String ");
            String _pathName_1 = this.toPathName(e.getKey());
            _builder.append(_pathName_1);
            _builder.append("Value;");
            _builder.newLineIfNotEmpty();
          }
        }
      }
    }
    return _builder;
  }

  private CharSequence handlerCaches(final SynonymMap mapping, final String packageName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// basic");
    _builder.newLine();
    CharSequence _basicTypeCaches = this.basicTypeCaches(mapping);
    _builder.append(_basicTypeCaches);
    _builder.newLineIfNotEmpty();
    _builder.append("// rosetta");
    _builder.newLine();
    CharSequence _rosettaTypeCaches = this.rosettaTypeCaches(mapping, packageName);
    _builder.append(_rosettaTypeCaches);
    _builder.newLineIfNotEmpty();
    return _builder;
  }

  private CharSequence basicTypeCaches(final SynonymMap mapping) {
    CharSequence _xblockexpression = null;
    {
      final Function1 _function = (AttributeGroupMapping it) -> {
        boolean _isClassOrData = this.isClassOrData(it.getMappings().getRosetta());
        return Boolean.valueOf((!_isClassOrData));
      };
      final Function1 _function_1 = (AttributeGroupMapping it) -> {
        return it.getGroup();
      };
      final Iterable attrPathSynGroups = IterableExtensions.map(IterableExtensions.filter(mapping.getMappedGroups(), _function), _function_1);
      final Function1 _function_2 = (AttributeGroup it) -> {
        int _size = it.getAttributePath().size();
        return Boolean.valueOf((_size > 1));
      };
      final Function1 _function_3 = (AttributeGroup it) -> {
        return this.toAttPathName(this.toFirstMultiple(it));
      };
      final Map> chopped = IterableExtensions.groupBy(IterableExtensions.filter(attrPathSynGroups, _function_2), _function_3);
      _xblockexpression = this.handlerCache(chopped);
    }
    return _xblockexpression;
  }

  private ArrayList toFirstMultiple(final AttributeGroup group) {
    return this.toFirstMultiple(group.getAttributePath());
  }

  /**
   * @param atts - list of attributes represents a path (with attribute name/type for each path element).
   * @returns the first attribute that has multiple cardinality
   */
  private ArrayList toFirstMultiple(final Iterable atts) {
    ArrayList _xblockexpression = null;
    {
      final ArrayList result = CollectionLiterals.newArrayList();
      boolean multiple = false;
      int i = 0;
      while (((!multiple) && (i <= (IterableExtensions.size(atts) - 2)))) {
        {
          int _plusPlus = i++;
          final ExpandedAttribute att = ((ExpandedAttribute[])Conversions.unwrapArray(atts, ExpandedAttribute.class))[_plusPlus];
          result.add(att);
          multiple = att.isMultiple();
        }
      }
      _xblockexpression = result;
    }
    return _xblockexpression;
  }

  private CharSequence handlerCache(final Map> attributeGroupMap) {
    StringConcatenation _builder = new StringConcatenation();
    {
      final Function1>, String> _function = (Map.Entry> it) -> {
        final Function1 _function_1 = (AttributeGroup it_1) -> {
          return this.toAttPathName(it_1);
        };
        return this.toAttPathName(IterableExtensions.last(IterableExtensions.sortBy(it.getValue(), _function_1)));
      };
      List>> _sortBy = IterableExtensions.>, String>sortBy(attributeGroupMap.entrySet(), _function);
      for(final Map.Entry> attrPathSynGroups : _sortBy) {
        {
          final Function1 _function_1 = (AttributeGroup it) -> {
            return this.removeLast(it);
          };
          final Function1 _function_2 = (AttributeGroup it) -> {
            return Boolean.valueOf(this.multipleCardinality(it));
          };
          boolean _exists = IterableExtensions.exists(ListExtensions.map(attrPathSynGroups.getValue(), _function_1), _function_2);
          if (_exists) {
            _builder.append("protected HandlerCache<");
            CharSequence _expandedTypeToBuilder = this.expandedTypeToBuilder(IterableExtensions.last(this.toFirstMultiple(IterableExtensions.last(attrPathSynGroups.getValue()))).getType());
            _builder.append(_expandedTypeToBuilder);
            _builder.append("> ");
            String _key = attrPathSynGroups.getKey();
            _builder.append(_key);
            _builder.append("Underlyers =");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("new HandlerCache<>(ImmutableMultimap.builder()");
            _builder.newLine();
            {
              List _sort = IterableExtensions.sort(attrPathSynGroups.getValue());
              for(final AttributeGroup attrPathSynGroup : _sort) {
                {
                  final Function1 _function_3 = (SynonymGroup it) -> {
                    return this.toSVG(it);
                  };
                  List _sortBy_1 = IterableExtensions.sortBy(attrPathSynGroup.getSynonymGroups(), _function_3);
                  for(final SynonymGroup sg : _sortBy_1) {
                    _builder.append("\t\t\t");
                    _builder.append(".put(\"");
                    String _attributeName = AttributeGroup.attributeName(IterableExtensions.last(attrPathSynGroup.getAttributePath()));
                    _builder.append(_attributeName, "\t\t\t");
                    _builder.append("\", new SynonymValueGroup(");
                    String _sVG = this.toSVG(sg);
                    _builder.append(_sVG, "\t\t\t");
                    _builder.append("))");
                    _builder.newLineIfNotEmpty();
                  }
                }
              }
            }
            _builder.append("\t\t\t");
            _builder.append(".build());");
            _builder.newLine();
          } else {
            _builder.append("protected AnonHandler<");
            CharSequence _expandedTypeToBuilder_1 = this.expandedTypeToBuilder(IterableExtensions.last(this.removeLast(IterableExtensions.last(attrPathSynGroups.getValue()).getAttributePath())).getType());
            _builder.append(_expandedTypeToBuilder_1);
            _builder.append("> ");
            String _attPathName = this.toAttPathName(this.removeLast(IterableExtensions.last(attrPathSynGroups.getValue())));
            _builder.append(_attPathName);
            _builder.append("UnderlyerB;");
            _builder.newLineIfNotEmpty();
          }
        }
      }
    }
    return _builder;
  }

  private CharSequence rosettaTypeCaches(final SynonymMap mapping, final String packageName) {
    StringConcatenation _builder = new StringConcatenation();
    {
      final Function1 _function = (AttributeGroupMapping it) -> {
        return Boolean.valueOf(this.isClassOrData(it.getMappings().getRosetta()));
      };
      final Function1 _function_1 = (AttributeGroupMapping it) -> {
        return this.toAttPathName(it.getGroup());
      };
      List _sortBy = IterableExtensions.sortBy(IterableExtensions.filter(mapping.getMappedGroups(), _function), _function_1);
      for(final AttributeGroupMapping mappedGroup : _sortBy) {
        {
          boolean _multipleCardinality = this.multipleCardinality(mappedGroup.getGroup());
          if (_multipleCardinality) {
            _builder.append("protected HandlerCache<");
            CharSequence _expandedTypeToBuilder = this.expandedTypeToBuilder(IterableExtensions.last(mappedGroup.getGroup().getAttributePath()).getType());
            _builder.append(_expandedTypeToBuilder);
            _builder.append("> ");
            CharSequence _handlerFieldName = this.toHandlerFieldName(mappedGroup.getGroup());
            _builder.append(_handlerFieldName);
            _builder.append(" =");
            _builder.newLineIfNotEmpty();
            _builder.append("\t\t");
            _builder.append("new HandlerCache<>(ImmutableMultimap.builder()");
            _builder.newLine();
            {
              final Function1 _function_2 = (SynonymGroup it) -> {
                return this.toSVG(it);
              };
              List _sortBy_1 = IterableExtensions.sortBy(mappedGroup.getGroup().getSynonymGroups(), _function_2);
              for(final SynonymGroup sg : _sortBy_1) {
                _builder.append("\t\t\t\t");
                _builder.append(".put(\"");
                String _attributeName = AttributeGroup.attributeName(IterableExtensions.last(mappedGroup.getGroup().getAttributePath()));
                _builder.append(_attributeName, "\t\t\t\t");
                _builder.append("\", new SynonymValueGroup(");
                String _sVG = this.toSVG(sg);
                _builder.append(_sVG, "\t\t\t\t");
                _builder.append("))");
                _builder.newLineIfNotEmpty();
              }
            }
            _builder.append("\t\t\t\t");
            _builder.append(".build());");
            _builder.newLine();
          } else {
            {
              final Function1 _function_3 = (SynonymGroup it) -> {
                return Boolean.valueOf(it.getConditions().isEmpty());
              };
              boolean _exists = IterableExtensions.exists(mappedGroup.getGroup().getSynonymGroups(), _function_3);
              if (_exists) {
                _builder.append("protected ");
                CharSequence _pFullNameT = this.pFullNameT(mappedGroup.getMappings(), packageName);
                _builder.append(_pFullNameT);
                _builder.append(" ");
                CharSequence _handlerFieldName_1 = this.toHandlerFieldName(mappedGroup.getGroup());
                _builder.append(_handlerFieldName_1);
                _builder.append(";");
                _builder.newLineIfNotEmpty();
              }
            }
          }
        }
      }
    }
    return _builder;
  }

  private String toSVG(final SynonymGroup group) {
    boolean _isEmpty = group.getSynonymValues().isEmpty();
    if (_isEmpty) {
      final Function1> _function = (SynonymCondition it) -> {
        return it.getCondition();
      };
      final Function1 _function_1 = (SynonymPathTest it) -> {
        return it.getPathWithDots();
      };
      final Iterable pathExprs = IterableExtensions.map(Iterables.filter((Iterables.concat(ListExtensions.>map(group.getConditions(), _function))), SynonymPathTest.class), _function_1);
      final Function1> _function_2 = (SynonymCondition it) -> {
        return it.getCondition();
      };
      final Function1> _function_3 = (SynonymBinaryTest it) -> {
        return it.getPaths();
      };
      final Function1 _function_4 = (SynonymValue p) -> {
        final Function1 _function_5 = (Element it) -> {
          return it.getName();
        };
        return IterableExtensions.join(ListExtensions.map(p.getSynonymPath(), _function_5), ".");
      };
      final Iterable binExprs = IterableExtensions.map(Iterables.concat(IterableExtensions.>map(Iterables.filter((Iterables.concat(ListExtensions.>map(group.getConditions(), _function_2))), SynonymBinaryTest.class), _function_3)), _function_4);
      final Function1 _function_5 = (String it) -> {
        return it;
      };
      return IterableExtensions.join(IterableExtensions.toSet(Iterables.concat(CollectionLiterals.>newArrayList(pathExprs, binExprs))), "\"", "\", \"", "\"", _function_5);
    } else {
      final Function1> _function_6 = (SynonymValue it) -> {
        return this.toFirstLeaf(it.getSynonymPath());
      };
      final Function1, CharSequence> _function_7 = (ArrayList p) -> {
        final Function1 _function_8 = (Element e) -> {
          return e.getName();
        };
        return IterableExtensions.join(ListExtensions.map(p, _function_8), ".");
      };
      return IterableExtensions.>join(ListExtensions.>map(group.getSynonymValues(), _function_6), "\"", "\", \"", "\"", _function_7);
    }
  }

  private CharSequence toHandlerFieldName(final AttributeGroup attrPathSynGroup) {
    String _xifexpression = null;
    boolean _multipleCardinality = this.multipleCardinality(attrPathSynGroup);
    if (_multipleCardinality) {
      _xifexpression = "Handlers";
    } else {
      _xifexpression = "Handler";
    }
    String handlerSuffix = _xifexpression;
    String _attPathName = this.toAttPathName(attrPathSynGroup);
    return (_attPathName + handlerSuffix);
  }

  /**
   * Simple handlers require one handler method per attribute
   */
  private String toHandlerMethodName(final AttributeGroup attrPathSynGroup) {
    String _attPathName = this.toAttPathName(attrPathSynGroup);
    return (_attPathName + "Handler");
  }

  private CharSequence toCondHandlerMethodName(final AttributeGroup attrPathSynGroup) {
    String _attPathName = this.toAttPathName(attrPathSynGroup);
    return (_attPathName + "ConditionalHandler");
  }

  /**
   * Conditional handlers require one handler method per synonym path (each attribute can have multiple synonym paths)
   */
  private String toConditionalHandlerMethodName(final SynonymValue synonymValue) {
    String _pathName = this.toPathName(synonymValue);
    return (_pathName + "ConditionalCaptureHandler");
  }

  private CharSequence toMappingProcessorMethodName(final AttributeGroup attrPathSynGroup, final SynonymGroup group) {
    String _attPathName = this.toAttPathName(attrPathSynGroup);
    final Function1> _function = (SynonymValue it) -> {
      return it.getSynonymPath();
    };
    final Function1 _function_1 = (Element it) -> {
      return it.getName();
    };
    String _firstUpper = StringExtensions.toFirstUpper(IterableExtensions.join(IterableExtensions.map(IterableExtensions.flatMap(group.getSynonymValues(), _function), _function_1)));
    String _plus = (_attPathName + _firstUpper);
    return (_plus + 
      "MappingProcessor");
  }

  private Set toSynonymLastElementName(final SynonymGroup group) {
    final Function1> _function = (SynonymValue it) -> {
      return it.getSynonymPath();
    };
    final Function1, String> _function_1 = (List it) -> {
      final Function1 _function_2 = (Element it_1) -> {
        return it_1.getName();
      };
      return IterableExtensions.last(ListExtensions.map(it, _function_2));
    };
    return IterableExtensions.toSet(ListExtensions., String>map(ListExtensions.>map(group.getSynonymValues(), _function), _function_1));
  }

  private ArrayList toFirstLeaf(final List elements) {
    ArrayList _xblockexpression = null;
    {
      ArrayList result = CollectionLiterals.newArrayList();
      boolean isLeaf = false;
      int i = 0;
      while (((!isLeaf) && (i < elements.size()))) {
        {
          int _plusPlus = i++;
          final Element e = elements.get(_plusPlus);
          result.add(e);
          isLeaf = false;
        }
      }
      _xblockexpression = result;
    }
    return _xblockexpression;
  }

  private boolean multipleCardinality(final AttributeGroup attrPathSynGroup) {
    final Function1 _function = (ExpandedAttribute it) -> {
      return Boolean.valueOf(RosettaAttributeExtensions.cardinalityIsListValue(it));
    };
    return IterableExtensions.exists(attrPathSynGroup.getAttributePath(), _function);
  }

  private boolean multipleCardinality(final List attributePath) {
    final Function1 _function = (ExpandedAttribute it) -> {
      return Boolean.valueOf(RosettaAttributeExtensions.cardinalityIsListValue(it));
    };
    return IterableExtensions.exists(attributePath, _function);
  }

  private boolean getterMultipleCardinality(final List attributePath) {
    final Function1 _function = (ExpandedAttribute it) -> {
      return Boolean.valueOf(RosettaAttributeExtensions.cardinalityIsListValue(it));
    };
    return IterableExtensions.exists(this.removeLast(attributePath), _function);
  }

  private String toAttPathName(final AttributeGroup attrPathSynGroup) {
    return this.toAttPathName(attrPathSynGroup.getAttributePath());
  }

  private String toAttPathName(final List attributePath) {
    final Function1 _function = (ExpandedAttribute s) -> {
      return AttributeGroup.attributeName(s);
    };
    return StringExtensions.toFirstLower(IterableExtensions.join(ListExtensions.map(attributePath, _function), ""));
  }

  private CharSequence list(final List path) {
    StringConcatenation _builder = new StringConcatenation();
    {
      final Function1 _function = (Element s) -> {
        return s.getName();
      };
      List _map = ListExtensions.map(path, _function);
      boolean _hasElements = false;
      for(final String string : _map) {
        if (!_hasElements) {
          _hasElements = true;
        } else {
          _builder.appendImmediate(", ", "");
        }
        _builder.append("\"");
        _builder.append(string);
        _builder.append("\"");
      }
    }
    return _builder;
  }

  private  CharSequence constructor(final SynonymMap mapping) {
    StringConcatenation _builder = new StringConcatenation();
    {
      boolean _isAbstract = this.isAbstract(mapping.getRosetta());
      boolean _not = (!_isAbstract);
      if (_not) {
        _builder.append("@SuppressWarnings(\"unchecked\")");
      }
    }
    _builder.newLineIfNotEmpty();
    _builder.append("public ");
    CharSequence _pNameW = this.pNameW(mapping);
    _builder.append(_pNameW);
    _builder.append("(Injector injector, MappingContext mappingContext) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("super(injector, mappingContext);");
    _builder.newLine();
    _builder.append("\t");
    {
      boolean _isAbstract_1 = this.isAbstract(mapping.getRosetta());
      boolean _not_1 = (!_isAbstract_1);
      if (_not_1) {
        _builder.append("setUnderlying((T)new BuilderProxy());");
      }
    }
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("handlers = ImmutableMultimap., HandlerSupplier>builder()");
    _builder.newLine();
    {
      SynonymMap _superMap = mapping.getSuperMap();
      boolean _tripleNotEquals = (_superMap != null);
      if (_tripleNotEquals) {
        _builder.append("\t\t");
        _builder.append(".putAll(super.handlers)");
        _builder.newLine();
      }
    }
    _builder.append("\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("// unconditional handlers");
    _builder.newLine();
    {
      List _unconditionalHandlerPaths = this.unconditionalHandlerPaths(mapping);
      for(final SynonymAttributePath path : _unconditionalHandlerPaths) {
        _builder.append("\t\t");
        _builder.append(".put(");
        String _synonymPath = path.getSynonymPath();
        _builder.append(_synonymPath, "\t\t");
        _builder.append("Path, this::");
        String _attributePath = path.getAttributePath();
        _builder.append(_attributePath, "\t\t");
        _builder.append("Handler_");
        int _index = path.getIndex();
        _builder.append(_index, "\t\t");
        _builder.append(")");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t\t");
    _builder.append("// conditional handlers");
    _builder.newLine();
    {
      List _conditionalHandlerPaths = this.conditionalHandlerPaths(mapping);
      for(final SynonymAttributePath path_1 : _conditionalHandlerPaths) {
        _builder.append("\t\t");
        _builder.append(".put(");
        String _synonymPath_1 = path_1.getSynonymPath();
        _builder.append(_synonymPath_1, "\t\t");
        _builder.append("Path, this::");
        String _attributePath_1 = path_1.getAttributePath();
        _builder.append(_attributePath_1, "\t\t");
        _builder.append("ConditionalHandler)");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t\t");
    _builder.append("// conditional captures");
    _builder.newLine();
    {
      List _sort = IterableExtensions.sort(IterableUtil.distinct(this.condCaptures(mapping)));
      for(final String conditional : _sort) {
        _builder.append("\t\t");
        _builder.append(conditional, "\t\t");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t\t");
    _builder.append(".build();");
    _builder.newLine();
    _builder.newLine();
    _builder.append("\t");
    _builder.append("mappingProcessors = ImmutableMultimap., MappingProcessorSupplier>builder()");
    _builder.newLine();
    {
      SynonymMap _superMap_1 = mapping.getSuperMap();
      boolean _tripleNotEquals_1 = (_superMap_1 != null);
      if (_tripleNotEquals_1) {
        _builder.append("\t\t");
        _builder.append(".putAll(super.mappingProcessors)");
        _builder.newLine();
      }
    }
    {
      final Function1 _function = (AttributeGroup it) -> {
        final Function1 _function_1 = (SynonymGroup it_1) -> {
          String _mapperName = it_1.getMapperName();
          return Boolean.valueOf((_mapperName != null));
        };
        return Boolean.valueOf(IterableExtensions.exists(it.getSynonymGroups(), _function_1));
      };
      List _sort_1 = IterableExtensions.sort(IterableExtensions.filter(mapping.attributeGroups(), _function));
      for(final AttributeGroup attrPathSynGroup : _sort_1) {
        {
          final Function1 _function_1 = (SynonymGroup it) -> {
            String _mapperName = it.getMapperName();
            return Boolean.valueOf((_mapperName != null));
          };
          Iterable _filter = IterableExtensions.filter(attrPathSynGroup.getSynonymGroups(), _function_1);
          for(final SynonymGroup mapperSynGroup : _filter) {
            {
              final Function _function_2 = (SynonymValue it) -> {
                return this.toPathName(it);
              };
              final Function1 _function_3 = (SynonymValue it) -> {
                return this.toPathName(it);
              };
              List _sortBy = IterableExtensions.sortBy(IterableUtil.distinctBy(mapperSynGroup.getSynonymValues(), _function_2), _function_3);
              for(final SynonymValue synonymValue : _sortBy) {
                _builder.append("\t\t");
                _builder.append(".put(");
                String _pathName = this.toPathName(synonymValue);
                _builder.append(_pathName, "\t\t");
                _builder.append("Path, this::");
                CharSequence _mappingProcessorMethodName = this.toMappingProcessorMethodName(attrPathSynGroup, mapperSynGroup);
                _builder.append(_mappingProcessorMethodName, "\t\t");
                _builder.append(")");
                _builder.newLineIfNotEmpty();
              }
            }
          }
        }
      }
    }
    _builder.append("\t\t");
    _builder.append(".build();");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  private List unconditionalHandlerPaths(final SynonymMap mapping) {
    final ArrayList paths = CollectionLiterals.newArrayList();
    final Function1 _function = (AttributeGroup it) -> {
      final Function1 _function_1 = (SynonymGroup it_1) -> {
        final Function1 _function_2 = (SynonymCondition it_2) -> {
          return Boolean.valueOf(it_2.getCondition().isEmpty());
        };
        return Boolean.valueOf(IterableExtensions.forall(it_1.getConditions(), _function_2));
      };
      return Boolean.valueOf(IterableExtensions.exists(it.getSynonymGroups(), _function_1));
    };
    List _sort = IterableExtensions.sort(IterableExtensions.filter(mapping.attributeGroups(), _function));
    for (final AttributeGroup attrPathSynGroup : _sort) {
      final Procedure2 _function_1 = (SynonymGroup sg, Integer i) -> {
        Integer _xblockexpression = null;
        {
          final ExpandedAttribute last = IterableExtensions.last(attrPathSynGroup.getAttributePath());
          Integer _xifexpression = null;
          if ((last.getType().isType() || Objects.equal(last.getType().getName(), "RosettaReference"))) {
            _xifexpression = Integer.valueOf(0);
          } else {
            _xifexpression = i;
          }
          _xblockexpression = _xifexpression;
        }
        final Integer index = _xblockexpression;
        if (((!sg.getSynonymValues().isEmpty()) && IterableExtensions.forall(sg.getConditions(), ((Function1) (SynonymCondition it) -> {
          return Boolean.valueOf(it.getCondition().isEmpty());
        })))) {
          final Function _function_2 = (SynonymValue it) -> {
            return this.toPathName(it);
          };
          final Function1 _function_3 = (SynonymValue it) -> {
            return this.toPathName(it);
          };
          final Consumer _function_4 = (SynonymValue sv) -> {
            String _pathName = this.toPathName(sv);
            String _attPathName = this.toAttPathName(attrPathSynGroup);
            SynonymAttributePath _synonymAttributePath = new SynonymAttributePath(_pathName, _attPathName, (index).intValue());
            paths.add(_synonymAttributePath);
          };
          IterableExtensions.sortBy(IterableUtil.distinctBy(sg.getSynonymValues(), _function_2), _function_3).forEach(_function_4);
        }
      };
      IterableExtensions.forEach(attrPathSynGroup.getSynonymGroups(), _function_1);
    }
    return IterableExtensions.sort(paths);
  }

  private List conditionalHandlerPaths(final SynonymMap mapping) {
    final ArrayList paths = CollectionLiterals.newArrayList();
    final Function1 _function = (AttributeGroup it) -> {
      final Function1 _function_1 = (SynonymGroup it_1) -> {
        final Function1 _function_2 = (SynonymCondition it_2) -> {
          boolean _isEmpty = it_2.getCondition().isEmpty();
          return Boolean.valueOf((!_isEmpty));
        };
        return Boolean.valueOf(IterableExtensions.exists(it_1.getConditions(), _function_2));
      };
      return Boolean.valueOf(IterableExtensions.exists(it.getSynonymGroups(), _function_1));
    };
    List _sort = IterableExtensions.sort(IterableExtensions.filter(mapping.attributeGroups(), _function));
    for (final AttributeGroup attrPathSynGroup : _sort) {
      final Function1 _function_1 = (SynonymGroup it) -> {
        return Boolean.valueOf(((!it.getSynonymValues().isEmpty()) && IterableExtensions.exists(it.getConditions(), ((Function1) (SynonymCondition it_1) -> {
          boolean _isEmpty = it_1.getCondition().isEmpty();
          return Boolean.valueOf((!_isEmpty));
        }))));
      };
      final Function1> _function_2 = (SynonymGroup sg) -> {
        return sg.getSynonymValues();
      };
      final Function _function_3 = (SynonymValue it) -> {
        return this.toPathName(it);
      };
      final Function1 _function_4 = (SynonymValue it) -> {
        return this.toPathName(it);
      };
      List _sortBy = IterableExtensions.sortBy(IterableUtil.distinctBy(IterableExtensions.flatMap(IterableExtensions.filter(attrPathSynGroup.getSynonymGroups(), _function_1), _function_2), _function_3), _function_4);
      for (final SynonymValue synonymValue : _sortBy) {
        String _pathName = this.toPathName(synonymValue);
        String _attPathName = this.toAttPathName(attrPathSynGroup);
        SynonymAttributePath _synonymAttributePath = new SynonymAttributePath(_pathName, _attPathName, 0);
        paths.add(_synonymAttributePath);
      }
    }
    return IterableExtensions.sort(paths);
  }

  private Iterable condCaptures(final SynonymMap mapping) {
    final Function1 _function = (SynonymValue it) -> {
      return this.toPathName(it);
    };
    final Function1 _function_1 = (String name) -> {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append(".put(");
      _builder.append(name);
      _builder.append("Path, this::");
      _builder.append(name);
      _builder.append("ConditionalCaptureHandler)");
      return _builder.toString();
    };
    return IterableExtensions.map(IterableExtensions.map(mapping.getConditionalCaptures().keySet(), _function), _function_1);
  }

  private CharSequence handler(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final String packageName) {
    CharSequence _xblockexpression = null;
    {
      final ExpandedAttribute last = IterableExtensions.last(mappedGroup.getGroup().getAttributePath());
      CharSequence _xifexpression = null;
      if ((last.getType().isType() || Objects.equal(last.getType().getName(), "RosettaReference"))) {
        _xifexpression = this.romHandler(mappedGroup, mapping, packageName);
      } else {
        final ArrayList handlers = CollectionLiterals.newArrayList();
        final Procedure2 _function = (SynonymGroup sg, Integer i) -> {
          boolean _isEnumeration = last.getType().isEnumeration();
          if (_isEnumeration) {
            CharSequence _basicHandler = this.basicHandler(mappedGroup, mapping, this.pFullNameT(last.getType(), packageName), (i).intValue());
            handlers.add(_basicHandler);
          } else {
            CharSequence _basicHandler_1 = this.basicHandler(mappedGroup, mapping, StringExtensions.toFirstUpper(last.getType().getName()), (i).intValue());
            handlers.add(_basicHandler_1);
          }
        };
        IterableExtensions.forEach(mappedGroup.getGroup().getSynonymGroups(), _function);
        return IterableExtensions.join(handlers, "\n");
      }
      _xblockexpression = _xifexpression;
    }
    return _xblockexpression;
  }

  private boolean isClassOrData(final RosettaType t) {
    return (t instanceof com.regnosys.rosetta.rosetta.simple.Data);
  }

  private CharSequence nestedSetToHandler(final List attributePath, final SynonymMap mapping, final Set alreadyGenerated) {
    CharSequence _xblockexpression = null;
    {
      int _size = attributePath.size();
      int _minus = (_size - 1);
      final Function1 _function = (ExpandedAttribute it) -> {
        return Boolean.valueOf(RosettaAttributeExtensions.cardinalityIsListValue(it));
      };
      final boolean multiple = IterableExtensions.exists(IterableExtensions.take(attributePath, _minus), _function);
      String _attPathName = this.toAttPathName(this.removeLast(attributePath));
      final String underlyerAttrName = (_attPathName + "UnderlyerB");
      CharSequence _xifexpression = null;
      if (((!multiple) && alreadyGenerated.add(underlyerAttrName))) {
        CharSequence _xblockexpression_1 = null;
        {
          final Object underlyerType = this.firstMultipleBuilder(attributePath, mapping);
          StringConcatenation _builder = new StringConcatenation();
          _builder.append("protected AnonHandler<");
          _builder.append(underlyerType);
          _builder.append("> get");
          String _firstUpper = StringExtensions.toFirstUpper(underlyerAttrName);
          _builder.append(_firstUpper);
          _builder.append("() {");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          _builder.append("// nested (set-to conditional mapping with path predicate) anon handler");
          _builder.newLine();
          _builder.append("\t");
          _builder.append("return ");
          _builder.append(underlyerAttrName, "\t");
          _builder.append(" != null ?");
          _builder.newLineIfNotEmpty();
          _builder.append("\t\t");
          _builder.append(underlyerAttrName, "\t\t");
          _builder.append(" :");
          _builder.newLineIfNotEmpty();
          _builder.append("\t\t");
          _builder.append("useOrNew(");
          _builder.append(underlyerAttrName, "\t\t");
          _builder.append(",");
          _builder.newLineIfNotEmpty();
          _builder.append("\t\t\t");
          _builder.append("() -> {");
          _builder.newLine();
          _builder.append("\t\t\t\t");
          _builder.append(underlyerType, "\t\t\t\t");
          _builder.append(" chainBuilder;");
          _builder.newLineIfNotEmpty();
          _builder.append("\t\t\t\t");
          CharSequence _builderChain = this.builderChain(attributePath, mapping);
          _builder.append(_builderChain, "\t\t\t\t");
          _builder.newLineIfNotEmpty();
          _builder.append("\t\t\t\t");
          _builder.append("return new AnonHandler<>(injector, mappingContext, rosettaPath, chainBuilder);");
          _builder.newLine();
          _builder.append("\t\t\t");
          _builder.append("});");
          _builder.newLine();
          _builder.append("}");
          _builder.newLine();
          _builder.newLine();
          _xblockexpression_1 = _builder;
        }
        _xifexpression = _xblockexpression_1;
      }
      _xblockexpression = _xifexpression;
    }
    return _xblockexpression;
  }

  private CharSequence condHandler(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final String envName) {
    CharSequence _xblockexpression = null;
    {
      final ExpandedType t = IterableExtensions.last(mappedGroup.getGroup().getAttributePath()).getType();
      CharSequence _xifexpression = null;
      boolean _isType = t.isType();
      if (_isType) {
        _xifexpression = this.romCondHandler(mappedGroup, mapping, envName);
      } else {
        CharSequence _xifexpression_1 = null;
        boolean _isEnumeration = t.isEnumeration();
        if (_isEnumeration) {
          _xifexpression_1 = this.enumCondHandler(mappedGroup, mapping, t, envName);
        } else {
          _xifexpression_1 = this.basicCondHandler(mappedGroup, mapping, StringExtensions.toFirstUpper(t.getName()));
        }
        _xifexpression = _xifexpression_1;
      }
      _xblockexpression = _xifexpression;
    }
    return _xblockexpression;
  }

  private CharSequence builderChain(final List attributePath, final SynonymMap mapping) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("Path rosettaPath = getRosettaPath();");
    _builder.newLine();
    ArrayList attList = this.toFirstMultiple(attributePath);
    _builder.newLineIfNotEmpty();
    String lastBuilderName = "getUnderlying()";
    _builder.newLineIfNotEmpty();
    String nextBuilderName = "";
    _builder.newLineIfNotEmpty();
    {
      for(final ExpandedAttribute att : attList) {
        {
          boolean _cardinalityIsListValue = RosettaAttributeExtensions.cardinalityIsListValue(att);
          if (_cardinalityIsListValue) {
            _builder.append("int ");
            String _name = att.getName();
            _builder.append(_name);
            _builder.append("Index = getMappingListIndex(");
            _builder.append(lastBuilderName);
            _builder.append(".get");
            String _firstUpper = StringExtensions.toFirstUpper(att.getName());
            _builder.append(_firstUpper);
            _builder.append("(), ");
            CharSequence _asList = this.asList(this.mergeSynonyms(attributePath, mapping));
            _builder.append(_asList);
            _builder.append(");");
            _builder.newLineIfNotEmpty();
            CharSequence _expandedTypeToBuilder = this.expandedTypeToBuilder(att.getType());
            _builder.append(_expandedTypeToBuilder);
            _builder.append(" ");
            String _firstLower = StringExtensions.toFirstLower(att.getType().getName());
            String _plus = (_firstLower + "Builder");
            String _nextBuilderName = nextBuilderName = _plus;
            _builder.append(_nextBuilderName);
            _builder.append(" = ");
            _builder.append(lastBuilderName);
            _builder.append(".getOrCreate");
            String _firstUpper_1 = StringExtensions.toFirstUpper(att.getName());
            _builder.append(_firstUpper_1);
            _builder.append("(");
            String _name_1 = att.getName();
            _builder.append(_name_1);
            _builder.append("Index);");
            _builder.newLineIfNotEmpty();
            _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
            String _name_2 = att.getName();
            _builder.append(_name_2);
            _builder.append("\", ");
            String _name_3 = att.getName();
            _builder.append(_name_3);
            _builder.append("Index));");
            _builder.newLineIfNotEmpty();
          } else {
            CharSequence _expandedTypeToBuilder_1 = this.expandedTypeToBuilder(att.getType());
            _builder.append(_expandedTypeToBuilder_1);
            _builder.append(" ");
            String _firstLower_1 = StringExtensions.toFirstLower(att.getType().getName());
            String _plus_1 = (_firstLower_1 + "Builder");
            String _nextBuilderName_1 = nextBuilderName = _plus_1;
            _builder.append(_nextBuilderName_1);
            _builder.append(" = ");
            _builder.append(lastBuilderName);
            _builder.append(".getOrCreate");
            String _firstUpper_2 = StringExtensions.toFirstUpper(att.getName());
            _builder.append(_firstUpper_2);
            _builder.append("();");
            _builder.newLineIfNotEmpty();
            _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
            String _name_4 = att.getName();
            _builder.append(_name_4);
            _builder.append("\"));");
            _builder.newLineIfNotEmpty();
          }
        }
        String _xblockexpression = null;
        {
          lastBuilderName = nextBuilderName;
          _xblockexpression = "";
        }
        _builder.append(_xblockexpression);
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("chainBuilder = (");
    Object _firstMultipleBuilder = this.firstMultipleBuilder(attributePath, mapping);
    _builder.append(_firstMultipleBuilder);
    _builder.append(")");
    _builder.append(lastBuilderName);
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    return _builder;
  }

  /**
   * Find merge synonyms for the given model path.
   */
  public List mergeSynonyms(final List attributePath, final SynonymMap mapping) {
    final Function1 _function = (AttributeGroupMapping it) -> {
      List _attributePath = it.getGroup().getAttributePath();
      return Boolean.valueOf((_attributePath == attributePath));
    };
    final Function1> _function_1 = (AttributeGroupMapping it) -> {
      return it.getMappings().getMergeSynonyms().values();
    };
    return IterableExtensions.toList(IterableExtensions.flatMap(IterableExtensions.filter(mapping.getMappedGroups(), _function), _function_1));
  }

  /**
   * Write merge synonym values out as an list of MergeSynonymValue
   */
  public CharSequence asList(final List mergeSyns) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("java.util.Arrays.asList(");
    final Function1 _function = (RosettaMergeSynonymValue it) -> {
      StringConcatenation _builder_1 = new StringConcatenation();
      _builder_1.append("new com.regnosys.rosetta.translate.MergeSynonymValue(\"");
      String _name = it.getName();
      _builder_1.append(_name);
      _builder_1.append("\", \"");
      String _excludePath = it.getExcludePath();
      _builder_1.append(_excludePath);
      _builder_1.append("\")");
      return _builder_1.toString();
    };
    String _join = IterableExtensions.join(ListExtensions.map(mergeSyns, _function), ",");
    _builder.append(_join);
    _builder.append(")");
    return _builder;
  }

  public CharSequence postAnon(final AttributeGroup group, final SynonymMap mapping) {
    CharSequence _xblockexpression = null;
    {
      final List afterMultiple = this.postFirstMultiple(group);
      String lastBuilderName = "foundbuilder.getUnderlying()";
      String nextBuilderName = null;
      StringConcatenation _builder = new StringConcatenation();
      {
        List _removeLast = this.removeLast(afterMultiple);
        for(final ExpandedAttribute att : _removeLast) {
          {
            boolean _cardinalityIsListValue = RosettaAttributeExtensions.cardinalityIsListValue(att);
            if (_cardinalityIsListValue) {
              _builder.append("int ");
              String _name = att.getName();
              _builder.append(_name);
              _builder.append("Index = sizeOf(");
              _builder.append(lastBuilderName);
              _builder.append(".get");
              String _firstUpper = StringExtensions.toFirstUpper(att.getName());
              _builder.append(_firstUpper);
              _builder.append("());");
              _builder.newLineIfNotEmpty();
              CharSequence _expandedTypeToBuilder = this.expandedTypeToBuilder(att.getType());
              _builder.append(_expandedTypeToBuilder);
              _builder.append(" ");
              String _firstLower = StringExtensions.toFirstLower(att.getType().getName());
              String _plus = (_firstLower + "Builder");
              String _nextBuilderName = nextBuilderName = _plus;
              _builder.append(_nextBuilderName);
              _builder.append(" = ");
              _builder.append(lastBuilderName);
              _builder.append(".getOrCreate");
              String _firstUpper_1 = StringExtensions.toFirstUpper(att.getName());
              _builder.append(_firstUpper_1);
              _builder.append("(");
              String _name_1 = att.getName();
              _builder.append(_name_1);
              _builder.append("Index);");
              _builder.newLineIfNotEmpty();
              _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
              String _name_2 = att.getName();
              _builder.append(_name_2);
              _builder.append("\", ");
              String _name_3 = att.getName();
              _builder.append(_name_3);
              _builder.append("Index));");
              _builder.newLineIfNotEmpty();
            } else {
              CharSequence _expandedTypeToBuilder_1 = this.expandedTypeToBuilder(att.getType());
              _builder.append(_expandedTypeToBuilder_1);
              _builder.append(" ");
              String _firstLower_1 = StringExtensions.toFirstLower(att.getType().getName());
              String _plus_1 = (_firstLower_1 + "Builder");
              String _nextBuilderName_1 = nextBuilderName = _plus_1;
              _builder.append(_nextBuilderName_1);
              _builder.append(" = ");
              _builder.append(lastBuilderName);
              _builder.append(".getOrCreate");
              String _firstUpper_2 = StringExtensions.toFirstUpper(att.getName());
              _builder.append(_firstUpper_2);
              _builder.append("();");
              _builder.newLineIfNotEmpty();
              _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
              String _name_4 = att.getName();
              _builder.append(_name_4);
              _builder.append("\"));");
              _builder.newLineIfNotEmpty();
            }
          }
          String _xblockexpression_1 = null;
          {
            lastBuilderName = nextBuilderName;
            _xblockexpression_1 = "";
          }
          _builder.append(_xblockexpression_1);
          _builder.newLineIfNotEmpty();
        }
      }
      Object _penultimateBuilder = this.penultimateBuilder(group.getAttributePath(), mapping);
      _builder.append(_penultimateBuilder);
      _builder.append(" builder = ");
      _builder.append(lastBuilderName);
      _builder.append(";");
      _builder.newLineIfNotEmpty();
      _xblockexpression = _builder;
    }
    return _xblockexpression;
  }

  protected List postFirstMultiple(final AttributeGroup group) {
    return group.getAttributePath().subList(this.toFirstMultiple(group).size(), group.getAttributePath().size());
  }

  protected List postFirstMultiple(final List attributePath) {
    return attributePath.subList(this.toFirstMultiple(attributePath).size(), attributePath.size());
  }

  private CharSequence conditionalCaptureHandler(final Map.Entry> sv, final SynonymMap mapping) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("private StringParseHandler ");
    String _conditionalHandlerMethodName = this.toConditionalHandlerMethodName(sv.getKey());
    _builder.append(_conditionalHandlerMethodName);
    _builder.append("(Path localPath, Path parentPath) {");
    _builder.newLineIfNotEmpty();
    {
      final Function1 _function = (Element e) -> {
        return Boolean.valueOf(((e.getEntity() != null) && (e.getCardinality() == Cardinality.MULTIPLE)));
      };
      boolean _exists = IterableExtensions.exists(sv.getKey().getSynonymPath(), _function);
      if (_exists) {
        {
          final Function1 _function_1 = (SynonymCondition c) -> {
            final Function1 _function_2 = (SynonymTest c2) -> {
              return Boolean.valueOf(((c2 instanceof SynonymExistsTest) || (c2 instanceof SynonymAbsentTest)));
            };
            return Boolean.valueOf(IterableExtensions.forall(c.getCondition(), _function_2));
          };
          boolean _forall = IterableExtensions.forall(sv.getValue(), _function_1);
          if (_forall) {
            _builder.append("\t");
            String _pathName = this.toPathName(sv.getKey());
            _builder.append(_pathName, "\t");
            _builder.append("Values.put(localPath, \"Exists\");");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("StringParseHandler res = new StringParseHandler(true, true);");
            _builder.newLine();
            _builder.append("\t");
            _builder.append("res.setParentSetter(a -> {});");
            _builder.newLine();
            _builder.append("\t");
            _builder.append("res.setParentSupplier(() -> Optional.empty());");
            _builder.newLine();
            _builder.append("\t");
            _builder.append("return res;");
            _builder.newLine();
          } else {
            _builder.append("\t");
            _builder.append("StringParseHandler handler = new StringParseHandler(true, true);");
            _builder.newLine();
            _builder.append("\t");
            _builder.append("useConditionalCache(handler, localPath, ");
            String _pathName_1 = this.toPathName(sv.getKey());
            _builder.append(_pathName_1, "\t");
            _builder.append("Values);");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("return handler;");
            _builder.newLine();
          }
        }
      } else {
        {
          final Function1 _function_2 = (SynonymCondition c) -> {
            final Function1 _function_3 = (SynonymTest c2) -> {
              return Boolean.valueOf(((c2 instanceof SynonymExistsTest) || (c2 instanceof SynonymAbsentTest)));
            };
            return Boolean.valueOf(IterableExtensions.forall(c.getCondition(), _function_3));
          };
          boolean _forall_1 = IterableExtensions.forall(sv.getValue(), _function_2);
          if (_forall_1) {
            _builder.append("\t");
            String _pathName_2 = this.toPathName(sv.getKey());
            _builder.append(_pathName_2, "\t");
            _builder.append("Value = \"Exists\";");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("StringParseHandler res = new StringParseHandler(true, true);");
            _builder.newLine();
            _builder.append("\t");
            _builder.append("res.setParentSetter(a -> {});");
            _builder.newLine();
            _builder.append("\t");
            _builder.append("res.setParentSupplier(() -> Optional.empty());");
            _builder.newLine();
            _builder.append("\t");
            _builder.append("return res;");
            _builder.newLine();
          } else {
            _builder.append("\t");
            _builder.append("StringParseHandler handler = new StringParseHandler(true, true);");
            _builder.newLine();
            _builder.append("\t");
            _builder.append("handler.setParentSetter(val -> ");
            String _pathName_3 = this.toPathName(sv.getKey());
            _builder.append(_pathName_3, "\t");
            _builder.append("Value = val);");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("handler.setParentSupplier(() -> Optional.ofNullable(");
            String _pathName_4 = this.toPathName(sv.getKey());
            _builder.append(_pathName_4, "\t");
            _builder.append("Value));");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("return handler;");
            _builder.newLine();
          }
        }
      }
    }
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  private CharSequence basicHandler(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final CharSequence type, final int index) {
    CharSequence _xblockexpression = null;
    {
      final AttributeGroup attrPathSynGroup = mappedGroup.getGroup();
      final ExpandedAttribute lastAttribute = IterableExtensions.last(attrPathSynGroup.getAttributePath());
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("private ");
      _builder.append(type);
      _builder.append("ParseHandler ");
      String _handlerMethodName = this.toHandlerMethodName(attrPathSynGroup);
      _builder.append(_handlerMethodName);
      _builder.append("_");
      _builder.append(index);
      _builder.append("(Path localPath, Path parentPath) {");
      _builder.newLineIfNotEmpty();
      _builder.append("\t");
      _builder.append("Path xmlPath = parentPath.addElement(localPath.getLastElement());");
      _builder.newLine();
      _builder.append("\t");
      CharSequence _generateAnonHandler = this.generateAnonHandler(attrPathSynGroup, mapping, lastAttribute, "localPath", "xmlPath");
      _builder.append(_generateAnonHandler, "\t");
      _builder.newLineIfNotEmpty();
      _builder.append("\t");
      _builder.append(type, "\t");
      _builder.append("ParseHandler handler = new ");
      CharSequence _basicHandlerConstructor = this.basicHandlerConstructor(type, attrPathSynGroup.getSynonymGroups().get(index));
      _builder.append(_basicHandlerConstructor, "\t");
      _builder.newLineIfNotEmpty();
      _builder.append("\t");
      _builder.append("handler.addXmlPath(xmlPath);");
      _builder.newLine();
      {
        boolean _cardinalityIsSingleValue = RosettaAttributeExtensions.cardinalityIsSingleValue(lastAttribute);
        if (_cardinalityIsSingleValue) {
          _builder.append("\t");
          _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
          String _name = lastAttribute.getName();
          _builder.append(_name, "\t");
          _builder.append("\"));");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          _builder.append("handler.setParentSetter(val -> builder.set");
          String _firstUpper = StringExtensions.toFirstUpper(AttributeGroup.attributeName(lastAttribute));
          _builder.append(_firstUpper, "\t");
          _builder.append("(val));");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          _builder.append("handler.setParentSupplier(() -> ");
          CharSequence _supplier = this.supplier(mappedGroup.getGroup().getAttributePath());
          _builder.append(_supplier, "\t");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          _builder.append(");");
          _builder.newLine();
        } else {
          _builder.append("\t");
          _builder.append("int index = sizeOf(builder.get");
          String _firstUpper_1 = StringExtensions.toFirstUpper(lastAttribute.getName());
          _builder.append(_firstUpper_1, "\t");
          _builder.append("());");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
          String _name_1 = lastAttribute.getName();
          _builder.append(_name_1, "\t");
          _builder.append("\", index));");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          _builder.append("handler.setParentSetter(val -> builder.add");
          String _firstUpper_2 = StringExtensions.toFirstUpper(lastAttribute.getName());
          _builder.append(_firstUpper_2, "\t");
          _builder.append("(val));");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          _builder.append("handler.setParentSupplier(() -> Optional.empty());");
          _builder.newLine();
        }
      }
      _builder.append("\t");
      _builder.append("handler.setRosettaPath(rosettaPath);");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("return handler;");
      _builder.newLine();
      _builder.append("}");
      _builder.newLine();
      _xblockexpression = _builder;
    }
    return _xblockexpression;
  }

  public CharSequence basicHandlerConstructor(final CharSequence type, final SynonymGroup sg) {
    final Function1 _function = (SynonymValue it) -> {
      return Integer.valueOf(it.getMapsTo());
    };
    Integer _max = this.max(ListExtensions.map(sg.getSynonymValues(), _function), Integer.valueOf(0));
    boolean _greaterThan = ((_max).intValue() > 1);
    return this.basicHandlerConstructor(type, _greaterThan, 
      sg.isRemoveHtml(), 
      sg.getFormatString(), 
      sg.getPatternMatcher(), 
      sg.getPatternReplace());
  }

  public CharSequence basicHandlerConstructor(final CharSequence type, final List synonymGroups) {
    final Function1> _function = (SynonymGroup it) -> {
      return it.getSynonymValues();
    };
    final Function1 _function_1 = (SynonymValue it) -> {
      return Integer.valueOf(it.getMapsTo());
    };
    Integer _max = this.max(IterableExtensions.map(IterableExtensions.flatMap(synonymGroups, _function), _function_1), Integer.valueOf(0));
    boolean _greaterThan = ((_max).intValue() > 1);
    final Function1 _function_2 = (SynonymGroup it) -> {
      return Boolean.valueOf(it.isRemoveHtml());
    };
    final Function1 _function_3 = (Boolean it) -> {
      return Boolean.valueOf(true);
    };
    final Function1 _function_4 = (SynonymGroup it) -> {
      return it.getFormatString();
    };
    final Function1 _function_5 = (String it) -> {
      return Boolean.valueOf(true);
    };
    final Function1 _function_6 = (SynonymGroup it) -> {
      return it.getPatternMatcher();
    };
    final Function1 _function_7 = (String it) -> {
      return Boolean.valueOf(true);
    };
    final Function1 _function_8 = (SynonymGroup it) -> {
      return it.getPatternReplace();
    };
    final Function1 _function_9 = (String it) -> {
      return Boolean.valueOf(true);
    };
    return this.basicHandlerConstructor(type, _greaterThan, 
      (IterableExtensions.findFirst(ListExtensions.map(synonymGroups, _function_2), _function_3)).booleanValue(), 
      IterableExtensions.findFirst(ListExtensions.map(synonymGroups, _function_4), _function_5), 
      IterableExtensions.findFirst(ListExtensions.map(synonymGroups, _function_6), _function_7), 
      IterableExtensions.findFirst(ListExtensions.map(synonymGroups, _function_8), _function_9));
  }

  public CharSequence basicHandlerConstructor(final CharSequence type, final boolean hasMapsTo, final boolean removeHtml, final String formatString, final String patternMatcher, final String patternReplace) {
    CharSequence _switchResult = null;
    boolean _matched = false;
    if (Objects.equal(type, "Date")) {
      _matched=true;
    }
    if (!_matched) {
      if (Objects.equal(type, "DateTime")) {
        _matched=true;
      }
    }
    if (!_matched) {
      if (Objects.equal(type, "Time")) {
        _matched=true;
      }
    }
    if (!_matched) {
      if (Objects.equal(type, "ZonedDateTime")) {
        _matched=true;
      }
    }
    if (_matched) {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append(type);
      _builder.append("ParseHandler(");
      _builder.append(hasMapsTo);
      _builder.append(", false, ");
      _builder.append(removeHtml);
      {
        if ((formatString != null)) {
          _builder.append(", \"");
          _builder.append(formatString);
          _builder.append("\"");
        }
      }
      _builder.append(");");
      _switchResult = _builder;
    }
    if (!_matched) {
      StringConcatenation _builder_1 = new StringConcatenation();
      _builder_1.append(type);
      _builder_1.append("ParseHandler(");
      _builder_1.append(hasMapsTo);
      _builder_1.append(", false, ");
      _builder_1.append(removeHtml);
      {
        if ((patternMatcher != null)) {
          _builder_1.append(", \"");
          _builder_1.append(patternMatcher);
          _builder_1.append("\", \"");
          _builder_1.append(patternReplace);
          _builder_1.append("\" ");
        }
      }
      _builder_1.append(");");
      _switchResult = _builder_1;
    }
    return _switchResult;
  }

  public CharSequence enumHandlerConstructor(final ExpandedType type, final List synonymGroups, final String envName) {
    final Function1> _function = (SynonymGroup it) -> {
      return it.getSynonymValues();
    };
    final Function1 _function_1 = (SynonymValue it) -> {
      return Integer.valueOf(it.getMapsTo());
    };
    Integer _max = this.max(IterableExtensions.map(IterableExtensions.flatMap(synonymGroups, _function), _function_1), Integer.valueOf(0));
    boolean _greaterThan = ((_max).intValue() > 1);
    final Function1 _function_2 = (SynonymGroup it) -> {
      return Boolean.valueOf(it.isRemoveHtml());
    };
    final Function1 _function_3 = (Boolean it) -> {
      return Boolean.valueOf(true);
    };
    final Function1 _function_4 = (SynonymGroup it) -> {
      return it.getFormatString();
    };
    final Function1 _function_5 = (String it) -> {
      return Boolean.valueOf(true);
    };
    final Function1 _function_6 = (SynonymGroup it) -> {
      return it.getPatternMatcher();
    };
    final Function1 _function_7 = (String it) -> {
      return Boolean.valueOf(true);
    };
    final Function1 _function_8 = (SynonymGroup it) -> {
      return it.getPatternReplace();
    };
    final Function1 _function_9 = (String it) -> {
      return Boolean.valueOf(true);
    };
    return this.enumHandlerConstructor(type, _greaterThan, 
      (IterableExtensions.findFirst(ListExtensions.map(synonymGroups, _function_2), _function_3)).booleanValue(), 
      IterableExtensions.findFirst(ListExtensions.map(synonymGroups, _function_4), _function_5), 
      IterableExtensions.findFirst(ListExtensions.map(synonymGroups, _function_6), _function_7), 
      IterableExtensions.findFirst(ListExtensions.map(synonymGroups, _function_8), _function_9), envName);
  }

  public CharSequence enumHandlerConstructor(final ExpandedType type, final boolean hasMapsTo, final boolean removeHtml, final String formatString, final String patternMatcher, final String patternReplace, final String envName) {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _pFullNameW = this.pFullNameW(type, envName);
    _builder.append(_pFullNameW);
    _builder.append("(");
    _builder.append(hasMapsTo);
    _builder.append(", false, ");
    _builder.append(removeHtml);
    {
      if ((patternMatcher != null)) {
        _builder.append(", \"");
        _builder.append(patternMatcher);
        _builder.append("\", \"");
        _builder.append(patternReplace);
        _builder.append("\" ");
      }
    }
    _builder.append(");");
    return _builder;
  }

  private > T max(final Iterable iterable, final T defaultVal) {
    T _xifexpression = null;
    boolean _isEmpty = IterableExtensions.isEmpty(iterable);
    if (_isEmpty) {
      _xifexpression = defaultVal;
    } else {
      _xifexpression = IterableExtensions.max(iterable);
    }
    return _xifexpression;
  }

  private CharSequence enumCondHandler(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final ExpandedType type, final String envName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// enum condition handler");
    _builder.newLine();
    final AttributeGroup attrPathSynGroup = mappedGroup.getGroup();
    _builder.newLineIfNotEmpty();
    _builder.append("private ");
    CharSequence _pFullNameW = this.pFullNameW(type, envName);
    _builder.append(_pFullNameW);
    _builder.append(" ");
    CharSequence _condHandlerMethodName = this.toCondHandlerMethodName(attrPathSynGroup);
    _builder.append(_condHandlerMethodName);
    _builder.append("(Path localPath, Path parentPath) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("Path xmlPath = parentPath.addElement(localPath.getLastElement());");
    _builder.newLine();
    _builder.append("\t");
    CharSequence _pFullNameW_1 = this.pFullNameW(type, envName);
    _builder.append(_pFullNameW_1, "\t");
    _builder.append(" handler = new ");
    CharSequence _enumHandlerConstructor = this.enumHandlerConstructor(type, attrPathSynGroup.getSynonymGroups(), envName);
    _builder.append(_enumHandlerConstructor, "\t");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("handler.addXmlPath(xmlPath);");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("Path rosettaPath = getRosettaPath();");
    _builder.newLine();
    {
      List _attributePath = mappedGroup.getGroup().getAttributePath();
      for(final ExpandedAttribute att : _attributePath) {
        _builder.append("\t");
        _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
        String _name = att.getName();
        _builder.append(_name, "\t");
        _builder.append("\"));");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t");
    _builder.append("useConditionalCache(handler, localPath, ");
    String _attPathName = this.toAttPathName(mappedGroup.getGroup());
    _builder.append(_attPathName, "\t");
    _builder.append("Values);");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("handler.setRosettaPath(rosettaPath);");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("return handler;");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  private CharSequence basicCondHandler(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final String type) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// basic type condition handler");
    _builder.newLine();
    final AttributeGroup attrPathSynGroup = mappedGroup.getGroup();
    _builder.newLineIfNotEmpty();
    _builder.append("private ");
    _builder.append(type);
    _builder.append("ParseHandler ");
    CharSequence _condHandlerMethodName = this.toCondHandlerMethodName(attrPathSynGroup);
    _builder.append(_condHandlerMethodName);
    _builder.append("(Path localPath, Path parentPath) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("Path xmlPath = parentPath.addElement(localPath.getLastElement());");
    _builder.newLine();
    _builder.append("\t");
    _builder.append(type, "\t");
    _builder.append("ParseHandler handler = new ");
    CharSequence _basicHandlerConstructor = this.basicHandlerConstructor(type, attrPathSynGroup.getSynonymGroups());
    _builder.append(_basicHandlerConstructor, "\t");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("handler.addXmlPath(xmlPath);");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("Path rosettaPath = getRosettaPath();");
    _builder.newLine();
    {
      List _attributePath = mappedGroup.getGroup().getAttributePath();
      for(final ExpandedAttribute att : _attributePath) {
        _builder.append("\t");
        _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
        String _name = att.getName();
        _builder.append(_name, "\t");
        _builder.append("\"));");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t");
    _builder.append("useConditionalCache(handler, localPath, ");
    String _attPathName = this.toAttPathName(mappedGroup.getGroup());
    _builder.append(_attPathName, "\t");
    _builder.append("Values);");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("handler.setRosettaPath(rosettaPath);");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("return handler;");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  private CharSequence generateAnonHandler(final AttributeGroup group, final SynonymMap mapping, final ExpandedAttribute last, final String localPathVar, final String xmlPathVar) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// anon handler");
    _builder.newLine();
    {
      int _size = group.getAttributePath().size();
      boolean _greaterThan = (_size > 1);
      if (_greaterThan) {
        {
          List _attributePath = group.getAttributePath();
          int _size_1 = group.getAttributePath().size();
          int _minus = (_size_1 - 1);
          final Function1 _function = (ExpandedAttribute it) -> {
            return Boolean.valueOf(RosettaAttributeExtensions.cardinalityIsListValue(it));
          };
          boolean _exists = IterableExtensions.exists(IterableExtensions.take(_attributePath, _minus), _function);
          if (_exists) {
            _builder.append("AnonHandler<");
            Object _firstMultipleBuilder = this.firstMultipleBuilder(group.getAttributePath(), mapping);
            _builder.append(_firstMultipleBuilder);
            _builder.append("> foundbuilder = findOrNew(");
            String _attPathName = this.toAttPathName(this.toFirstMultiple(group));
            _builder.append(_attPathName);
            _builder.append("Underlyers, \"");
            String _name = last.getName();
            _builder.append(_name);
            _builder.append("\", ");
            _builder.append(localPathVar);
            _builder.append(",");
            _builder.newLineIfNotEmpty();
          } else {
            _builder.append("AnonHandler<");
            Object _firstMultipleBuilder_1 = this.firstMultipleBuilder(group.getAttributePath(), mapping);
            _builder.append(_firstMultipleBuilder_1);
            _builder.append("> foundbuilder = ");
            String _attPathName_1 = this.toAttPathName(this.removeLast(group));
            _builder.append(_attPathName_1);
            _builder.append("UnderlyerB = useOrNew(");
            String _attPathName_2 = this.toAttPathName(this.removeLast(group));
            _builder.append(_attPathName_2);
            _builder.append("UnderlyerB,");
            _builder.newLineIfNotEmpty();
          }
        }
        _builder.append("() -> {");
        _builder.newLine();
        _builder.append("\t");
        Object _firstMultipleBuilder_2 = this.firstMultipleBuilder(group.getAttributePath(), mapping);
        _builder.append(_firstMultipleBuilder_2, "\t");
        _builder.append(" chainBuilder;");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        CharSequence _builderChain = this.builderChain(group.getAttributePath(), mapping);
        _builder.append(_builderChain, "\t");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append("AnonHandler<");
        Object _firstMultipleBuilder_3 = this.firstMultipleBuilder(group.getAttributePath(), mapping);
        _builder.append(_firstMultipleBuilder_3, "\t");
        _builder.append("> result = new AnonHandler<>(injector, mappingContext, rosettaPath, chainBuilder);");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append("result.addXmlPath(");
        _builder.append(xmlPathVar, "\t");
        _builder.append(");");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append("return result;");
        _builder.newLine();
        _builder.append("});");
        _builder.newLine();
        _builder.append("Path rosettaPath = foundbuilder.getRosettaPath();");
        _builder.newLine();
        CharSequence _postAnon = this.postAnon(group, mapping);
        _builder.append(_postAnon);
        _builder.newLineIfNotEmpty();
      } else {
        _builder.append("Path rosettaPath = getRosettaPath();");
        _builder.newLine();
        CharSequence _pNameW = this.pNameW(mapping.getRosetta());
        _builder.append(_pNameW);
        _builder.append(" foundbuilder = ");
        CharSequence _pNameW_1 = this.pNameW(mapping.getRosetta());
        _builder.append(_pNameW_1);
        _builder.append(".this;");
        _builder.newLineIfNotEmpty();
        CharSequence _postAnon_1 = this.postAnon(group, mapping);
        _builder.append(_postAnon_1);
        _builder.newLineIfNotEmpty();
      }
    }
    return _builder;
  }

  private CharSequence mappingProcessor(final AttributeGroupMapping mappedGroup, final SynonymMap mapping) {
    CharSequence _xblockexpression = null;
    {
      final AttributeGroup attrPathSynGroup = mappedGroup.getGroup();
      final Function1 _function = (SynonymGroup it) -> {
        String _mapperName = it.getMapperName();
        return Boolean.valueOf((_mapperName != null));
      };
      final Iterable mapperSynGroups = IterableUtil.distinct(IterableExtensions.filter(attrPathSynGroup.getSynonymGroups(), _function));
      StringConcatenation _builder = new StringConcatenation();
      {
        for(final SynonymGroup mapperSynGroup : mapperSynGroups) {
          String _mapperName = mapperSynGroup.getMapperName();
          final String mapperClassName = (_mapperName + "MappingProcessor");
          _builder.newLineIfNotEmpty();
          _builder.append("private Map.Entry ");
          CharSequence _mappingProcessorMethodName = this.toMappingProcessorMethodName(attrPathSynGroup, mapperSynGroup);
          _builder.append(_mappingProcessorMethodName);
          _builder.append("(Path parentPath, MappingContext mappingContext) {");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          CharSequence _builderChainForMapper = this.builderChainForMapper(this.getRemoveLastReference(attrPathSynGroup.getAttributePath()), mapping);
          _builder.append(_builderChainForMapper, "\t");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          _builder.append("RosettaPath modelPath = PathUtils.toRosettaPath(rosettaPath);");
          _builder.newLine();
          _builder.append("\t");
          _builder.append("List synonymPaths = java.util.stream.Stream.of(");
          final Function1 _function_1 = (String it) -> {
            return it;
          };
          String _join = IterableExtensions.join(this.toSynonymLastElementName(mapperSynGroup), "\"", "\", \"", "\"", _function_1);
          _builder.append(_join, "\t");
          _builder.append(")");
          _builder.newLineIfNotEmpty();
          _builder.append("\t\t");
          _builder.append(".map(Path::parse)");
          _builder.newLine();
          _builder.append("\t\t");
          _builder.append(".map(parentPath::append)");
          _builder.newLine();
          _builder.append("\t\t");
          _builder.append(".collect(Collectors.toList());");
          _builder.newLine();
          _builder.append("\t");
          _builder.append("return new java.util.AbstractMap.SimpleEntry<>(modelPath, new ");
          _builder.append(mapperClassName, "\t");
          _builder.append("(modelPath, synonymPaths, mappingContext));");
          _builder.newLineIfNotEmpty();
          _builder.append("}");
          _builder.newLine();
          _builder.newLine();
        }
      }
      _xblockexpression = _builder;
    }
    return _xblockexpression;
  }

  private CharSequence builderChainForMapper(final List attributePath, final SynonymMap mapping) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("Path rosettaPath = getRosettaPath();");
    _builder.newLine();
    List attList = this.removeLast(attributePath);
    _builder.newLineIfNotEmpty();
    String lastBuilderName = "getUnderlying()";
    _builder.newLineIfNotEmpty();
    String nextBuilderName = "";
    _builder.newLineIfNotEmpty();
    {
      for(final ExpandedAttribute att : attList) {
        {
          boolean _cardinalityIsListValue = RosettaAttributeExtensions.cardinalityIsListValue(att);
          if (_cardinalityIsListValue) {
            _builder.append("int ");
            String _name = att.getName();
            _builder.append(_name);
            _builder.append("Index = Math.max(0, getMappingListIndex(");
            _builder.append(lastBuilderName);
            _builder.append(".get");
            String _firstUpper = StringExtensions.toFirstUpper(att.getName());
            _builder.append(_firstUpper);
            _builder.append("(), ");
            CharSequence _asList = this.asList(this.mergeSynonyms(attributePath, mapping));
            _builder.append(_asList);
            _builder.append(") - 1);");
            _builder.newLineIfNotEmpty();
            CharSequence _expandedTypeToBuilder = this.expandedTypeToBuilder(att.getType());
            _builder.append(_expandedTypeToBuilder);
            _builder.append(" ");
            String _firstLower = StringExtensions.toFirstLower(att.getType().getName());
            String _plus = (_firstLower + "Builder");
            String _nextBuilderName = nextBuilderName = _plus;
            _builder.append(_nextBuilderName);
            _builder.append(" = ");
            _builder.append(lastBuilderName);
            _builder.append(".getOrCreate");
            String _firstUpper_1 = StringExtensions.toFirstUpper(att.getName());
            _builder.append(_firstUpper_1);
            _builder.append("(");
            String _name_1 = att.getName();
            _builder.append(_name_1);
            _builder.append("Index);");
            _builder.newLineIfNotEmpty();
            _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
            String _name_2 = att.getName();
            _builder.append(_name_2);
            _builder.append("\", ");
            String _name_3 = att.getName();
            _builder.append(_name_3);
            _builder.append("Index));");
            _builder.newLineIfNotEmpty();
          } else {
            CharSequence _expandedTypeToBuilder_1 = this.expandedTypeToBuilder(att.getType());
            _builder.append(_expandedTypeToBuilder_1);
            _builder.append(" ");
            String _firstLower_1 = StringExtensions.toFirstLower(att.getType().getName());
            String _plus_1 = (_firstLower_1 + "Builder");
            String _nextBuilderName_1 = nextBuilderName = _plus_1;
            _builder.append(_nextBuilderName_1);
            _builder.append(" = ");
            _builder.append(lastBuilderName);
            _builder.append(".getOrCreate");
            String _firstUpper_2 = StringExtensions.toFirstUpper(att.getName());
            _builder.append(_firstUpper_2);
            _builder.append("();");
            _builder.newLineIfNotEmpty();
            _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
            String _name_4 = att.getName();
            _builder.append(_name_4);
            _builder.append("\"));");
            _builder.newLineIfNotEmpty();
          }
        }
        String _xblockexpression = null;
        {
          lastBuilderName = nextBuilderName;
          _xblockexpression = "";
        }
        _builder.append(_xblockexpression);
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
    String _name_5 = IterableExtensions.last(attributePath).getName();
    _builder.append(_name_5);
    _builder.append("\"));");
    _builder.newLineIfNotEmpty();
    return _builder;
  }

  public List getRemoveLastReference(final List attributes) {
    boolean _isParentMeta = this.isParentMeta(attributes);
    if (_isParentMeta) {
      return this.removeLast(attributes);
    }
    return attributes;
  }

  public boolean isMeta(final ExpandedAttribute attribute) {
    return attribute.isOverriding();
  }

  public boolean isParentMeta(final List attributes) {
    ExpandedAttribute _parentAttribute = this.getParentAttribute(attributes);
    boolean _isMeta = false;
    if (_parentAttribute!=null) {
      _isMeta=this.isMeta(_parentAttribute);
    }
    return _isMeta;
  }

  public ExpandedAttribute getParentAttribute(final List attributes) {
    ExpandedAttribute _xifexpression = null;
    int _size = attributes.size();
    boolean _greaterThan = (_size > 1);
    if (_greaterThan) {
      int _size_1 = attributes.size();
      int _minus = (_size_1 - 2);
      _xifexpression = attributes.get(_minus);
    } else {
      _xifexpression = null;
    }
    return _xifexpression;
  }

  private CharSequence supplier(final List atts) {
    CharSequence _xifexpression = null;
    final Function1 _function = (ExpandedAttribute it) -> {
      return Boolean.valueOf(RosettaAttributeExtensions.cardinalityIsListValue(it));
    };
    boolean _exists = IterableExtensions.exists(atts, _function);
    if (_exists) {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("Optional.empty()");
      _xifexpression = _builder;
    } else {
      StringConcatenation _builder_1 = new StringConcatenation();
      _builder_1.append("Optional.of(getUnderlying())");
      _builder_1.newLine();
      {
        final Function1 _function_1 = (ExpandedAttribute it) -> {
          return AttributeGroup.attributeName(it);
        };
        List _map = ListExtensions.map(atts, _function_1);
        for(final String name : _map) {
          _builder_1.append("\t\t");
          _builder_1.append(".map(bu -> bu.get");
          String _firstUpper = StringExtensions.toFirstUpper(name);
          _builder_1.append(_firstUpper, "\t\t");
          _builder_1.append("())");
          _builder_1.newLineIfNotEmpty();
        }
      }
      _xifexpression = _builder_1;
    }
    return _xifexpression;
  }

  private CharSequence romHandler(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final String packageName) {
    CharSequence _xblockexpression = null;
    {
      final ExpandedAttribute last = IterableExtensions.last(mappedGroup.getGroup().getAttributePath());
      CharSequence _xifexpression = null;
      final Function1 _function = (ExpandedAttribute it) -> {
        return Boolean.valueOf(RosettaAttributeExtensions.cardinalityIsListValue(it));
      };
      boolean _exists = IterableExtensions.exists(mappedGroup.getGroup().getAttributePath(), _function);
      if (_exists) {
        _xifexpression = this.romHandlerList(mappedGroup, mapping, last, packageName);
      } else {
        _xifexpression = this.romHandlerSingle(mappedGroup, mapping, last, packageName);
      }
      _xblockexpression = _xifexpression;
    }
    return _xblockexpression;
  }

  private CharSequence romCondHandler(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final String packageName) {
    CharSequence _xblockexpression = null;
    {
      final ExpandedAttribute last = IterableExtensions.last(mappedGroup.getGroup().getAttributePath());
      CharSequence _xifexpression = null;
      final Function1 _function = (ExpandedAttribute it) -> {
        return Boolean.valueOf(RosettaAttributeExtensions.cardinalityIsListValue(it));
      };
      boolean _exists = IterableExtensions.exists(mappedGroup.getGroup().getAttributePath(), _function);
      if (_exists) {
        _xifexpression = this.romCondHandlerList(mappedGroup, mapping, last, packageName);
      } else {
        _xifexpression = this.romCondHandlerSingle(mappedGroup, mapping, packageName);
      }
      _xblockexpression = _xifexpression;
    }
    return _xblockexpression;
  }

  private CharSequence romHandlerSingle(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final ExpandedAttribute last, final String packageName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("private ");
    CharSequence _pFullNameT = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT);
    _builder.append(" ");
    String _handlerMethodName = this.toHandlerMethodName(mappedGroup.getGroup());
    _builder.append(_handlerMethodName);
    _builder.append("_0(Path localPath, Path parentPath) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("Path xmlPath = parentPath.addElement(localPath.getLastElement());");
    _builder.newLine();
    _builder.append("\t");
    String _attPathName = this.toAttPathName(mappedGroup.getGroup());
    _builder.append(_attPathName, "\t");
    _builder.append("Handler = useOrNew(");
    CharSequence _handlerFieldName = this.toHandlerFieldName(mappedGroup.getGroup());
    _builder.append(_handlerFieldName, "\t");
    _builder.append(", ");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t\t");
    CharSequence _romSupllier = this.romSupllier(mappedGroup, mapping, last, packageName);
    _builder.append(_romSupllier, "\t\t\t");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("return ");
    CharSequence _handlerFieldName_1 = this.toHandlerFieldName(mappedGroup.getGroup());
    _builder.append(_handlerFieldName_1, "\t");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  private CharSequence romCondHandlerSingle(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final String packageName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("private ");
    CharSequence _pFullNameT = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT);
    _builder.append(" ");
    CharSequence _condHandlerMethodName = this.toCondHandlerMethodName(mappedGroup.getGroup());
    _builder.append(_condHandlerMethodName);
    _builder.append("(Path localPath, Path parentPath) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("Path xmlPath = parentPath.addElement(localPath.getLastElement());");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("Path rosettaPath = getRosettaPath();");
    _builder.newLine();
    {
      List _attributePath = mappedGroup.getGroup().getAttributePath();
      for(final ExpandedAttribute att : _attributePath) {
        _builder.append("\t");
        _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
        String _name = att.getName();
        _builder.append(_name, "\t");
        _builder.append("\"));");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t");
    CharSequence _pFullNameT_1 = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT_1, "\t");
    _builder.append(" handler = new ");
    CharSequence _pFullNameT_2 = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT_2, "\t");
    _builder.append("(injector, mappingContext);");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("handler.setRosettaPath(rosettaPath);");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("handler.setUnderlying(");
    String _attPathName = this.toAttPathName(mappedGroup.getGroup());
    _builder.append(_attPathName, "\t");
    _builder.append("Values.computeIfAbsent(localPath, a -> handler.getUnderlying()));");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("return handler;");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  private CharSequence romHandlerList(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final ExpandedAttribute last, final String packageName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("private ");
    CharSequence _pFullNameT = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT);
    _builder.append(" ");
    String _handlerMethodName = this.toHandlerMethodName(mappedGroup.getGroup());
    _builder.append(_handlerMethodName);
    _builder.append("_0(Path localPath, Path parentPath) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("Path xmlPath = parentPath.addElement(localPath.getLastElement());");
    _builder.newLine();
    _builder.append("\t");
    CharSequence _pFullNameT_1 = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT_1, "\t");
    _builder.append(" handler = findOrNew(");
    CharSequence _handlerFieldName = this.toHandlerFieldName(mappedGroup.getGroup());
    _builder.append(_handlerFieldName, "\t");
    _builder.append(", \"");
    String _name = last.getName();
    _builder.append(_name, "\t");
    _builder.append("\", localPath,");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t\t");
    CharSequence _romSupllier = this.romSupllier(mappedGroup, mapping, last, packageName);
    _builder.append(_romSupllier, "\t\t\t");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("return handler;");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  private CharSequence romCondHandlerList(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final ExpandedAttribute last, final String packageName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("private ");
    CharSequence _pFullNameT = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT);
    _builder.append(" ");
    CharSequence _condHandlerMethodName = this.toCondHandlerMethodName(mappedGroup.getGroup());
    _builder.append(_condHandlerMethodName);
    _builder.append("(Path localPath, Path parentPath) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("Path xmlPath = parentPath.addElement(localPath.getLastElement());");
    _builder.newLine();
    _builder.append("\t");
    CharSequence _pFullNameT_1 = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT_1, "\t");
    _builder.append(" handler = findOrNew(");
    CharSequence _handlerFieldName = this.toHandlerFieldName(mappedGroup.getGroup());
    _builder.append(_handlerFieldName, "\t");
    _builder.append(", \"");
    String _name = last.getName();
    _builder.append(_name, "\t");
    _builder.append("\", localPath,");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("() -> {");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("Path rosettaPath = getRosettaPath();");
    _builder.newLine();
    _builder.append("\t\t\t");
    CharSequence _pFullNameT_2 = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT_2, "\t\t\t");
    _builder.append(" result = new ");
    CharSequence _pFullNameW = this.pFullNameW(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameW, "\t\t\t");
    _builder.append("<>(injector, mappingContext);");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t\t");
    _builder.append("result.setUnderlying(");
    String _attPathName = this.toAttPathName(mappedGroup.getGroup());
    _builder.append(_attPathName, "\t\t\t");
    _builder.append("Values.computeIfAbsent(localPath, a -> ");
    String _name_1 = mappedGroup.getMappings().getRosetta().getName();
    _builder.append(_name_1, "\t\t\t");
    _builder.append(".builder()));");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t\t");
    boolean cardUsed = false;
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t\t");
    _builder.append("// Model index is guessed at the number of conditional options, e.g., if there\'s 1 option, then the index would be 0");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("int index = ");
    String _attPathName_1 = this.toAttPathName(mappedGroup.getGroup());
    _builder.append(_attPathName_1, "\t\t\t");
    _builder.append("Values.keySet().size() - 1;");
    _builder.newLineIfNotEmpty();
    {
      List _attributePath = mappedGroup.getGroup().getAttributePath();
      for(final ExpandedAttribute att : _attributePath) {
        {
          if ((RosettaAttributeExtensions.cardinalityIsListValue(att) && (!cardUsed))) {
            _builder.append("\t\t\t");
            _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
            String _xblockexpression = null;
            {
              cardUsed = true;
              _xblockexpression = att.getName();
            }
            _builder.append(_xblockexpression, "\t\t\t");
            _builder.append("\", index));");
            _builder.newLineIfNotEmpty();
          } else {
            _builder.append("\t\t\t");
            _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
            String _name_2 = att.getName();
            _builder.append(_name_2, "\t\t\t");
            _builder.append("\"));");
            _builder.newLineIfNotEmpty();
          }
        }
      }
    }
    _builder.append("\t\t\t");
    _builder.append("result.addXmlPath(xmlPath);");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("result.setRosettaPath(rosettaPath);");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("return result;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("});");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("return handler;");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  private CharSequence romSupllier(final AttributeGroupMapping mappedGroup, final SynonymMap mapping, final ExpandedAttribute last, final String packageName) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("()-> {");
    Object _firstMultipleBuilder = this.firstMultipleBuilder(mappedGroup.getGroup().getAttributePath(), mapping);
    _builder.append(_firstMultipleBuilder);
    _builder.append(" chainBuilder;");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    CharSequence _builderChain = this.builderChain(mappedGroup.getGroup().getAttributePath(), mapping);
    _builder.append(_builderChain, "\t\t");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    Object _penultimateBuilder = this.penultimateBuilder(mappedGroup.getGroup().getAttributePath(), mapping);
    _builder.append(_penultimateBuilder, "\t\t");
    _builder.append(" penultimateBuilder;");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    String lastBuilderName = "chainBuilder";
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    String nextBuilderName = "";
    _builder.newLineIfNotEmpty();
    {
      List _attributePath = mappedGroup.getGroup().getAttributePath();
      int _size = this.toFirstMultiple(mappedGroup.getGroup()).size();
      int _size_1 = mappedGroup.getGroup().getAttributePath().size();
      int _minus = (_size_1 - 1);
      List _subList = _attributePath.subList(_size, _minus);
      for(final ExpandedAttribute att : _subList) {
        {
          boolean _cardinalityIsListValue = RosettaAttributeExtensions.cardinalityIsListValue(att);
          if (_cardinalityIsListValue) {
            _builder.append("int ");
            String _name = att.getName();
            _builder.append(_name);
            _builder.append("Index = sizeOf(");
            _builder.append(lastBuilderName);
            _builder.append(".get");
            String _firstUpper = StringExtensions.toFirstUpper(att.getName());
            _builder.append(_firstUpper);
            _builder.append("());");
            _builder.newLineIfNotEmpty();
            CharSequence _expandedTypeToBuilder = this.expandedTypeToBuilder(att.getType());
            _builder.append(_expandedTypeToBuilder);
            _builder.append(" ");
            String _firstLower = StringExtensions.toFirstLower(att.getType().getName());
            String _plus = (_firstLower + "Builder");
            String _nextBuilderName = nextBuilderName = _plus;
            _builder.append(_nextBuilderName);
            _builder.append(" = ");
            _builder.append(lastBuilderName);
            _builder.append(".getOrCreate");
            String _firstUpper_1 = StringExtensions.toFirstUpper(att.getName());
            _builder.append(_firstUpper_1);
            _builder.append("(");
            String _name_1 = att.getName();
            _builder.append(_name_1);
            _builder.append("Index);");
            _builder.newLineIfNotEmpty();
            _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
            String _name_2 = att.getName();
            _builder.append(_name_2);
            _builder.append("\", ");
            String _name_3 = att.getName();
            _builder.append(_name_3);
            _builder.append("Index));");
            _builder.newLineIfNotEmpty();
          } else {
            CharSequence _expandedTypeToBuilder_1 = this.expandedTypeToBuilder(att.getType());
            _builder.append(_expandedTypeToBuilder_1);
            _builder.append(" ");
            String _firstLower_1 = StringExtensions.toFirstLower(att.getType().getName());
            String _plus_1 = (_firstLower_1 + "Builder");
            String _nextBuilderName_1 = nextBuilderName = _plus_1;
            _builder.append(_nextBuilderName_1);
            _builder.append(" = ");
            _builder.append(lastBuilderName);
            _builder.append(".getOrCreate");
            String _firstUpper_2 = StringExtensions.toFirstUpper(att.getName());
            _builder.append(_firstUpper_2);
            _builder.append("();");
            _builder.newLineIfNotEmpty();
            _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
            String _name_4 = att.getName();
            _builder.append(_name_4);
            _builder.append("\"));");
            _builder.newLineIfNotEmpty();
          }
        }
        _builder.append("//");
        _builder.append(lastBuilderName = nextBuilderName);
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t\t");
    _builder.append("penultimateBuilder = ");
    _builder.append(lastBuilderName, "\t\t");
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    CharSequence _pFullNameT = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT, "\t\t");
    _builder.append(" result = new ");
    CharSequence _pFullNameT_1 = this.pFullNameT(mappedGroup.getMappings(), packageName);
    _builder.append(_pFullNameT_1, "\t\t");
    _builder.append("(injector, mappingContext);");
    _builder.newLineIfNotEmpty();
    {
      boolean _cardinalityIsListValue_1 = RosettaAttributeExtensions.cardinalityIsListValue(last);
      if (_cardinalityIsListValue_1) {
        _builder.append("\t\t");
        _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
        String _name_5 = last.getName();
        _builder.append(_name_5, "\t\t");
        _builder.append("\", sizeOf(penultimateBuilder.get");
        String _firstUpper_3 = StringExtensions.toFirstUpper(last.getName());
        _builder.append(_firstUpper_3, "\t\t");
        _builder.append("())));");
        _builder.newLineIfNotEmpty();
        _builder.append("\t\t");
        _builder.append("penultimateBuilder.add");
        String _firstUpper_4 = StringExtensions.toFirstUpper(last.getName());
        _builder.append(_firstUpper_4, "\t\t");
        _builder.append("(result.getUnderlying());");
        _builder.newLineIfNotEmpty();
      } else {
        _builder.append("\t\t");
        _builder.append("rosettaPath = rosettaPath.addElement(new PathElement(\"");
        String _name_6 = last.getName();
        _builder.append(_name_6, "\t\t");
        _builder.append("\"));");
        _builder.newLineIfNotEmpty();
        _builder.append("\t\t");
        _builder.append("penultimateBuilder.set");
        String _firstUpper_5 = StringExtensions.toFirstUpper(last.getName());
        _builder.append(_firstUpper_5, "\t\t");
        _builder.append("(result.getUnderlying());");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t\t");
    _builder.append("result.addXmlPath(xmlPath);");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("result.setRosettaPath(rosettaPath);");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("return result;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("});");
    _builder.newLine();
    return _builder;
  }

  private CharSequence generateBuilderProxy(final SynonymMap mapping) {
    final Function1 _function = (AttributeGroup it) -> {
      final Function1 _function_1 = (SynonymGroup it_1) -> {
        boolean _isEmpty = it_1.getConditions().isEmpty();
        return Boolean.valueOf((!_isEmpty));
      };
      return Boolean.valueOf(IterableExtensions.exists(it.getSynonymGroups(), _function_1));
    };
    final List conditionedPaths = IterableExtensions.toList(IterableExtensions.filter(mapping.attributeGroups(), _function));
    SynonymMap _superMap = mapping.getSuperMap();
    boolean _tripleNotEquals = (_superMap != null);
    if (_tripleNotEquals) {
      final Function1 _function_1 = (AttributeGroup it) -> {
        final Function1 _function_2 = (SynonymGroup it_1) -> {
          boolean _isEmpty = it_1.getConditions().isEmpty();
          return Boolean.valueOf((!_isEmpty));
        };
        return Boolean.valueOf(IterableExtensions.exists(it.getSynonymGroups(), _function_2));
      };
      Iterables.addAll(conditionedPaths, IterableExtensions.filter(mapping.getSuperMap().attributeGroups(), _function_1));
    }
    return this.generateBuilderProxy(mapping, conditionedPaths);
  }

  private CharSequence generateBuilderProxy(final SynonymMap mapping, final List conditionedPaths) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("private class BuilderProxy extends ");
    StringConcatenationClient _builder_1 = this.toBuilder(mapping.getRosetta());
    _builder.append(_builder_1);
    _builder.append("Impl {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("AtomicBoolean evaluatedConditions = new AtomicBoolean();");
    _builder.newLine();
    _builder.append("\t\t\t\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@Override");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    String _fullname = IterableUtil.fullname(mapping.getRosetta());
    _builder.append(_fullname, "\t");
    _builder.append(" build() {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("evaluateConditions();");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("if (super.hasData()) {");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("return super.build();");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("return null;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@Override");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public boolean hasData() {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("evaluateConditions();");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("return super.hasData();");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@Override");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public void process(RosettaPath path, BuilderProcessor processor) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("evaluateConditions();");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("super.process(path, processor);");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    CharSequence _buildEvaluateConditions = this.buildEvaluateConditions(mapping, conditionedPaths);
    _builder.append(_buildEvaluateConditions, "\t");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  protected CharSequence buildEvaluateConditions(final SynonymMap mapping, final Iterable conditionedPaths) {
    CharSequence _xblockexpression = null;
    {
      HashMap counterPerAttribute = new HashMap();
      for (final AttributeGroup path : conditionedPaths) {
        counterPerAttribute.put(StringExtensions.toFirstUpper(this.toAttPathName(path)), Integer.valueOf(0));
      }
      final LinkedHashMap methods = new LinkedHashMap();
      final TreeMultimap methodOrder = TreeMultimap.create();
      final Function1 _function = (AttributeGroup it) -> {
        return it.attsToString();
      };
      List _sortBy = IterableExtensions.sortBy(conditionedPaths, _function);
      for (final AttributeGroup path_1 : _sortBy) {
        final Function1 _function_1 = (SynonymGroup it) -> {
          boolean _isEmpty = it.getConditions().isEmpty();
          return Boolean.valueOf((!_isEmpty));
        };
        Iterable _filter = IterableExtensions.filter(path_1.getSynonymGroups(), _function_1);
        for (final SynonymGroup group : _filter) {
          List _conditions = group.getConditions();
          for (final SynonymCondition cond : _conditions) {
            {
              final Integer perPathCounter = counterPerAttribute.get(StringExtensions.toFirstUpper(this.toAttPathName(path_1)));
              String _firstUpper = StringExtensions.toFirstUpper(this.toAttPathName(path_1));
              String _plus = ("evaluate" + _firstUpper);
              final String methodName = (_plus + perPathCounter);
              counterPerAttribute.put(StringExtensions.toFirstUpper(this.toAttPathName(path_1)), Integer.valueOf(((perPathCounter).intValue() + 1)));
              SynonymTest.TestPriority _xifexpression = null;
              boolean _isEmpty = cond.getCondition().isEmpty();
              if (_isEmpty) {
                _xifexpression = SynonymTest.TestPriority.Last;
              } else {
                final Function1 _function_2 = (SynonymTest it) -> {
                  return it.priority();
                };
                _xifexpression = IterableExtensions.minBy(cond.getCondition(), _function_2).priority();
              }
              final SynonymTest.TestPriority priority = _xifexpression;
              methodOrder.put(priority, methodName);
              final Function1 _function_3 = (SynonymTest it) -> {
                final Function1 _function_4 = (SynonymValue it_1) -> {
                  final Function1 _function_5 = (Element it_2) -> {
                    return Boolean.valueOf(((it_2.getCardinality() == null) || Objects.equal(it_2.getCardinality(), Cardinality.SINGLE)));
                  };
                  return Boolean.valueOf(IterableExtensions.forall(it_1.getSynonymPath(), _function_5));
                };
                return Boolean.valueOf(IterableExtensions.forall(it.getPaths(), _function_4));
              };
              boolean _forall = IterableExtensions.forall(cond.getCondition(), _function_3);
              if (_forall) {
                methods.put(methodName, this.evalSingleCardinality(cond, mapping, path_1.getAttributePath(), this.toPathList(group), (perPathCounter).intValue()));
              } else {
                if (((!IterableExtensions.isEmpty(Iterables.filter(cond.getCondition(), SynonymPathTest.class))) && (!IterableExtensions.isEmpty(Iterables.filter(cond.getCondition(), SynonymBinaryTest.class))))) {
                  methods.put(methodName, this.evalPathAndTest(cond, path_1.getAttributePath(), this.toPathList(group), (perPathCounter).intValue()));
                } else {
                  methods.put(methodName, this.evalMultiCardinality(mapping, cond, path_1));
                }
              }
            }
          }
        }
      }
      StringConcatenation _builder = new StringConcatenation();
      {
        Set> _entrySet = methods.entrySet();
        for(final Map.Entry e : _entrySet) {
          _builder.append("private void ");
          String _key = e.getKey();
          _builder.append(_key);
          _builder.append("() {");
          _builder.newLineIfNotEmpty();
          _builder.append("\t");
          CharSequence _value = e.getValue();
          _builder.append(_value, "\t");
          _builder.newLineIfNotEmpty();
          _builder.append("}");
          _builder.newLine();
        }
      }
      _builder.append("\t\t\t");
      _builder.newLine();
      _builder.append("private void evaluateConditions() {");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("if (evaluatedConditions.compareAndSet(false, true)) {");
      _builder.newLine();
      {
        Set> _entries = methodOrder.entries();
        for(final Map.Entry e_1 : _entries) {
          _builder.append("\t\t");
          String _value_1 = e_1.getValue();
          _builder.append(_value_1, "\t\t");
          _builder.append("();");
          _builder.newLineIfNotEmpty();
        }
      }
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      _builder.newLine();
      _xblockexpression = _builder;
    }
    return _xblockexpression;
  }

  protected CharSequence evalMultiCardinality(final SynonymMap mapping, final SynonymCondition cond, final AttributeGroup group) {
    StringConcatenation _builder = new StringConcatenation();
    {
      boolean _exists = IterableUtil.exists(cond.getCondition(), SynonymRosettaPathTest.class);
      if (_exists) {
        _builder.append("Path rosettaPath = getRosettaPath()");
        {
          List _dropMeta = this.dropMeta(group.getAttributePath());
          for(final ExpandedAttribute att : _dropMeta) {
            _builder.append(".addElement(new PathElement(\"");
            String _name = att.getName();
            _builder.append(_name);
            _builder.append("\"))");
          }
        }
        _builder.append(";");
        _builder.newLineIfNotEmpty();
        _builder.append("if (");
        {
          Iterable _filter = Iterables.filter(cond.getCondition(), SynonymRosettaPathTest.class);
          boolean _hasElements = false;
          for(final SynonymRosettaPathTest test : _filter) {
            if (!_hasElements) {
              _hasElements = true;
            } else {
              _builder.appendImmediate(" && ", "");
            }
            _builder.append("GeneratorPathUtil.matches(rosettaPath, \"");
            CharSequence _dotSep = this.toDotSep(test.getPath());
            _builder.append(_dotSep);
            _builder.append("\")");
          }
        }
        _builder.append(") {");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        CharSequence _evalPathFiltering = this.evalPathFiltering(cond, group, mapping);
        _builder.append(_evalPathFiltering, "\t");
        _builder.newLineIfNotEmpty();
        _builder.append("}");
        _builder.newLine();
      } else {
        CharSequence _evalPathFiltering_1 = this.evalPathFiltering(cond, group, mapping);
        _builder.append(_evalPathFiltering_1);
        _builder.newLineIfNotEmpty();
      }
    }
    return _builder;
  }

  public List dropMeta(final List attributes) {
    ArrayList _xblockexpression = null;
    {
      final ArrayList result = CollectionLiterals.newArrayList();
      for (int i = 0; (i < ((Object[])Conversions.unwrapArray(attributes, Object.class)).length); i++) {
        if ((((attributes.size() > 0) && AttributeGroup.attributeName(attributes.get(i)).equals("value")) && this.isMeta(attributes.get((i - 1))))) {
        } else {
          boolean _equals = AttributeGroup.attributeName(attributes.get(i)).equals("meta");
          if (_equals) {
            i++;
          } else {
            result.add(attributes.get(i));
          }
        }
      }
      _xblockexpression = result;
    }
    return _xblockexpression;
  }

  protected boolean synonymPathHasMultipleCard(final SynonymExistsTest synonymExistsTest) {
    final Function1 _function = (Element it) -> {
      Cardinality _cardinality = it.getCardinality();
      return Boolean.valueOf((_cardinality == Cardinality.MULTIPLE));
    };
    return IterableExtensions.exists(synonymExistsTest.getPath().getSynonymPath(), _function);
  }

  protected CharSequence evalPathFiltering(final SynonymCondition cond, final AttributeGroup group, final SynonymMap mapping) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// evaluate path filtering");
    _builder.newLine();
    _builder.append("Set paths = null;");
    _builder.newLine();
    boolean initialSet = false;
    _builder.newLineIfNotEmpty();
    {
      Iterable _filter = Iterables.filter(cond.getCondition(), SynonymBinaryTest.class);
      for(final SynonymBinaryTest test : _filter) {
        _builder.append("// SynonymBinaryTest");
        _builder.newLine();
        _builder.append("// This next line hard codes a lot of stuff that probably needs to depend on the input");
        _builder.newLine();
        {
          if ((!initialSet)) {
            _builder.append("paths = (");
            String _xblockexpression = null;
            {
              initialSet = true;
              _xblockexpression = "";
            }
            _builder.append(_xblockexpression);
          } else {
            _builder.append(" paths.retainAll(");
          }
        }
        String _pathName = this.toPathName(test.getLeftPath());
        _builder.append(_pathName);
        _builder.append("Values.entrySet()");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append(".stream()");
        _builder.newLine();
        _builder.append("\t");
        _builder.append(".filter(e -> areEqual(e.getValue(), ");
        CharSequence _handleWhenRight = this.handleWhenRight(test.getRightLiteral());
        _builder.append(_handleWhenRight, "\t");
        _builder.append("))");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append(".map(e -> e.getKey())");
        _builder.newLine();
        _builder.append("\t");
        _builder.append(".collect(Collectors.toSet()));");
        _builder.newLine();
      }
    }
    _builder.newLine();
    {
      final Function1 _function = (SynonymExistsTest it) -> {
        return Boolean.valueOf(this.synonymPathHasMultipleCard(it));
      };
      Iterable _filter_1 = IterableExtensions.filter(Iterables.filter(cond.getCondition(), SynonymExistsTest.class), _function);
      for(final SynonymExistsTest test_1 : _filter_1) {
        _builder.append("// SynonymExistsTest");
        _builder.newLine();
        {
          if ((!initialSet)) {
            _builder.append("paths = (");
            String _xblockexpression_1 = null;
            {
              initialSet = true;
              _xblockexpression_1 = "";
            }
            _builder.append(_xblockexpression_1);
          } else {
            _builder.append(" paths.retainAll(");
          }
        }
        String _pathName_1 = this.toPathName(test_1.getPath());
        _builder.append(_pathName_1);
        _builder.append("Values.entrySet()");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append(".stream()");
        _builder.newLine();
        _builder.append("\t");
        _builder.append(".filter(e -> areEqual(e.getValue(), \"Exists\"))");
        _builder.newLine();
        _builder.append("\t");
        _builder.append(".map(e -> e.getKey())");
        _builder.newLine();
        _builder.append("\t");
        _builder.append(".collect(Collectors.toSet()));");
        _builder.newLine();
      }
    }
    {
      Iterable _filter_2 = Iterables.filter(cond.getCondition(), SynonymAbsentTest.class);
      for(final SynonymAbsentTest test_2 : _filter_2) {
        _builder.append("// SynonymAbsentTest");
        _builder.newLine();
        {
          if ((!initialSet)) {
            _builder.append("paths = (");
            String _xblockexpression_2 = null;
            {
              initialSet = true;
              _xblockexpression_2 = "";
            }
            _builder.append(_xblockexpression_2);
          } else {
            _builder.append(" paths.removeAll(");
          }
        }
        String _pathName_2 = this.toPathName(test_2.getPath());
        _builder.append(_pathName_2);
        _builder.append("Values.entrySet()");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append(".stream()");
        _builder.newLine();
        _builder.append("\t");
        _builder.append(".filter(e -> areEqual(e.getValue(), \"Exists\"))");
        _builder.newLine();
        _builder.append("\t");
        _builder.append(".map(e -> e.getKey())");
        _builder.newLine();
        _builder.append("\t");
        _builder.append(".collect(Collectors.toSet()));");
        _builder.newLine();
      }
    }
    {
      final Function1 _function_1 = (SynonymTest c) -> {
        return Boolean.valueOf((!(c instanceof SynonymAbsentTest)));
      };
      boolean _exists = IterableExtensions.exists(cond.getCondition(), _function_1);
      if (_exists) {
        {
          if ((((cond.getSetToValue() == null) && IterableUtil.exists(cond.getCondition(), SynonymExistsTest.class)) && IngesterGeneratorUtils.isConditionalMappingPredicatedOnDifferentPath(IterableExtensions.toList(IterableExtensions.flatMap(group.getSynonymGroups(), ((Function1>) (SynonymGroup it) -> {
            return it.getSynonymValues();
          }))), IterableExtensions.toList(IterableExtensions.map(Iterables.filter(cond.getCondition(), SynonymExistsTest.class), ((Function1) (SynonymExistsTest it) -> {
            return it.getPath();
          })))))) {
            _builder.append("// (a) ");
            final Function1 _function_2 = (SynonymTest it) -> {
              return it.getClass().getSimpleName();
            };
            String _join = IterableExtensions.join(ListExtensions.map(cond.getCondition(), _function_2), ",");
            _builder.append(_join);
            _builder.newLineIfNotEmpty();
            _builder.append("if (!paths.isEmpty()) {");
            _builder.newLine();
            _builder.append("    ");
            _builder.append("int index = 0;");
            _builder.newLine();
            _builder.append("\t");
            String _attPathName = this.toAttPathName(group.getAttributePath());
            _builder.append(_attPathName, "\t");
            _builder.append("Values.values().forEach(v -> ");
            CharSequence _setterChain = this.setterChain(group.getAttributePath());
            _builder.append(_setterChain, "\t");
            _builder.append("(v));");
            _builder.newLineIfNotEmpty();
            _builder.append("}");
            _builder.newLine();
          } else {
            _builder.append("for (Path p : paths) {");
            _builder.newLine();
            _builder.append("\t");
            _builder.append("// in evalPathFiltering");
            _builder.newLine();
            {
              boolean _multipleCardinality = this.multipleCardinality(group.getAttributePath());
              if (_multipleCardinality) {
                _builder.append("\t");
                _builder.append("int index = p.cardinality();");
                _builder.newLine();
              }
            }
            {
              if (((cond.getSetToValue() != null) && IterableExtensions.isEmpty(IterableExtensions.filter(cond.getCondition(), ((Function1) (SynonymTest it) -> {
                SynonymTest.TestPriority _priority = it.priority();
                return Boolean.valueOf((_priority == SynonymTest.TestPriority.Last));
              }))))) {
                _builder.append("\t");
                CharSequence _generateAnonHandler = this.generateAnonHandler(group, mapping, IterableExtensions.last(group.getAttributePath()), "p", "p");
                _builder.append(_generateAnonHandler, "\t");
                _builder.newLineIfNotEmpty();
                _builder.append("\t");
                _builder.append("builder.");
                CharSequence _setter = this.setter(group.getAttributePath());
                _builder.append(_setter, "\t");
                _builder.append("(");
                CharSequence _evaluate = this.evaluate(cond.getSetToValue());
                _builder.append(_evaluate, "\t");
                _builder.append(");");
                _builder.newLineIfNotEmpty();
              } else {
                RosettaMapTestExpression _setToValue = cond.getSetToValue();
                boolean _tripleNotEquals = (_setToValue != null);
                if (_tripleNotEquals) {
                  _builder.append("\t");
                  CharSequence _setterChain_1 = this.setterChain(group.getAttributePath());
                  _builder.append(_setterChain_1, "\t");
                  _builder.append("(");
                  CharSequence _evaluate_1 = this.evaluate(cond.getSetToValue());
                  _builder.append(_evaluate_1, "\t");
                  _builder.append(");");
                  _builder.newLineIfNotEmpty();
                } else {
                  if ((IterableExtensions.last(group.getAttributePath()).builtInType() || (!this.multipleCardinality(group.getAttributePath())))) {
                    _builder.append("\t");
                    String _attPathName_1 = this.toAttPathName(group.getAttributePath());
                    _builder.append(_attPathName_1, "\t");
                    _builder.append("Values.entrySet()");
                    _builder.newLineIfNotEmpty();
                    _builder.append("\t");
                    _builder.append("\t");
                    _builder.append(".stream()");
                    _builder.newLine();
                    _builder.append("\t");
                    _builder.append("\t");
                    _builder.append(".filter(e -> e.getKey().fullStartMatches(p))");
                    _builder.newLine();
                    _builder.append("\t");
                    _builder.append("\t");
                    _builder.append(".map(e -> e.getValue())");
                    _builder.newLine();
                    _builder.append("\t");
                    _builder.append("\t");
                    _builder.append(".forEach(v -> ");
                    CharSequence _mergeAttribute = this.mergeAttribute(group.getAttributePath());
                    _builder.append(_mergeAttribute, "\t\t");
                    _builder.append(");");
                    _builder.newLineIfNotEmpty();
                  } else {
                    _builder.append("\t");
                    String _attPathName_2 = this.toAttPathName(group.getAttributePath());
                    _builder.append(_attPathName_2, "\t");
                    _builder.append("Handlers.getAllHandlers()");
                    _builder.newLineIfNotEmpty();
                    _builder.append("\t");
                    _builder.append("\t");
                    _builder.append(".stream()");
                    _builder.newLine();
                    _builder.append("\t");
                    _builder.append("\t");
                    _builder.append(".filter(h -> h.getXmlPathsToHere().stream().anyMatch(k -> k.fullStartMatches(p)))");
                    _builder.newLine();
                    _builder.append("\t");
                    _builder.append("\t");
                    _builder.append(".forEach(v -> ");
                    CharSequence _setterChain_2 = this.setterChain(group.getAttributePath());
                    _builder.append(_setterChain_2, "\t\t");
                    _builder.append("(v.getUnderlying()));");
                    _builder.newLineIfNotEmpty();
                  }
                }
              }
            }
            _builder.append("}");
            _builder.newLine();
          }
        }
      } else {
        _builder.append("// (b) ");
        final Function1 _function_3 = (SynonymTest it) -> {
          return it.getClass().getSimpleName();
        };
        String _join_1 = IterableExtensions.join(ListExtensions.map(cond.getCondition(), _function_3), ",");
        _builder.append(_join_1);
        _builder.newLineIfNotEmpty();
        {
          final Function1> _function_4 = (SynonymGroup it) -> {
            return it.getSynonymValues();
          };
          final Function1 _function_5 = (SynonymAbsentTest it) -> {
            return it.getPath();
          };
          boolean _isConditionalMappingPredicatedOnDifferentPath = IngesterGeneratorUtils.isConditionalMappingPredicatedOnDifferentPath(IterableExtensions.toList(IterableExtensions.flatMap(group.getSynonymGroups(), _function_4)), IterableExtensions.toList(IterableExtensions.map(Iterables.filter(cond.getCondition(), SynonymAbsentTest.class), _function_5)));
          if (_isConditionalMappingPredicatedOnDifferentPath) {
            {
              boolean _terMultipleCardinality = this.getterMultipleCardinality(group.getAttributePath());
              if (_terMultipleCardinality) {
                _builder.append("// getOrCreateFoo(MAX_VALUE) creates new list item at next available index");
                _builder.newLine();
                _builder.append("int index = Integer.MAX_VALUE;");
                _builder.newLine();
              }
            }
            _builder.append("if (paths.isEmpty()) {");
            _builder.newLine();
            _builder.append("\t");
            String _attPathName_3 = this.toAttPathName(group.getAttributePath());
            _builder.append(_attPathName_3, "\t");
            _builder.append("Values.values().forEach(v -> ");
            CharSequence _setterChain_3 = this.setterChain(group.getAttributePath());
            _builder.append(_setterChain_3, "\t");
            _builder.append("(v));");
            _builder.newLineIfNotEmpty();
            _builder.append("}");
            _builder.newLine();
          } else {
            {
              boolean _terMultipleCardinality_1 = this.getterMultipleCardinality(group.getAttributePath());
              if (_terMultipleCardinality_1) {
                _builder.append("// getOrCreateFoo(MAX_VALUE) creates new list item at next available index");
                _builder.newLine();
                _builder.append("int index = Integer.MAX_VALUE;");
                _builder.newLine();
              }
            }
            _builder.append("for (Map.Entrylast(group.getAttributePath()).getType());
            _builder.append(_expandedTypeToBuilder);
            _builder.append("> entry : ");
            String _attPathName_4 = this.toAttPathName(group.getAttributePath());
            _builder.append(_attPathName_4);
            _builder.append("Values.entrySet()) {");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("if (!paths.stream().anyMatch(p -> entry.getKey().fullStartMatches(p))) {");
            _builder.newLine();
            _builder.append("\t\t");
            CharSequence _setterChain_4 = this.setterChain(group.getAttributePath());
            _builder.append(_setterChain_4, "\t\t");
            _builder.append("(entry.getValue());");
            _builder.newLineIfNotEmpty();
            _builder.append("\t");
            _builder.append("}");
            _builder.newLine();
            _builder.append("}");
            _builder.newLine();
          }
        }
      }
    }
    return _builder;
  }

  protected CharSequence mergeAttribute(final List attributePath) {
    StringConcatenation _builder = new StringConcatenation();
    {
      boolean _isDataType = IterableExtensions.last(attributePath).isDataType();
      if (_isDataType) {
        String _attributeGetters = this.attributeGetters(attributePath);
        _builder.append(_attributeGetters);
        _builder.append("merge(v, new IngestMerger())");
      } else {
        CharSequence _setterChain = this.setterChain(attributePath);
        _builder.append(_setterChain);
        _builder.append("(v)");
      }
    }
    _builder.newLineIfNotEmpty();
    return _builder;
  }

  protected CharSequence evalSingleCardinality(final SynonymCondition cond, final SynonymMap mapping, final List attributePath, final String pathList, final int attributeConditionIndex) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// evaluate xml path that has single cardinality");
    _builder.newLine();
    _builder.append("if (");
    CharSequence _handleWhen = this.handleWhen(cond, pathList, attributePath);
    _builder.append(_handleWhen);
    _builder.append(") {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    CharSequence _conditionTrue = this.conditionTrue(cond, attributePath, pathList, attributeConditionIndex);
    _builder.append(_conditionTrue, "\t");
    _builder.newLineIfNotEmpty();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  /**
   * Code generate the conditional mapping predicate for xml path that is single cardinality
   */
  private CharSequence handleWhen(final SynonymCondition cond, final String pathList, final List attributePath) {
    CharSequence _xifexpression = null;
    if (((cond.getSetToValue() != null) && cond.getCondition().isEmpty())) {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("!");
      CharSequence _supplier = this.supplier(attributePath);
      _builder.append(_supplier);
      _builder.append(".isPresent()");
      _xifexpression = _builder;
    } else {
      CharSequence _xifexpression_1 = null;
      boolean _isEmpty = cond.getCondition().isEmpty();
      boolean _not = (!_isEmpty);
      if (_not) {
        StringConcatenation _builder_1 = new StringConcatenation();
        {
          List _condition = cond.getCondition();
          boolean _hasElements = false;
          for(final SynonymTest test : _condition) {
            if (!_hasElements) {
              _hasElements = true;
            } else {
              _builder_1.appendImmediate(" && ", "");
            }
            CharSequence _handleTest = this.handleTest(test, pathList, attributePath);
            _builder_1.append(_handleTest);
          }
        }
        _xifexpression_1 = _builder_1;
      } else {
        StringConcatenation _builder_2 = new StringConcatenation();
        _builder_2.append("/* no `set to` and `set when` condition */ true");
        _xifexpression_1 = _builder_2;
      }
      _xifexpression = _xifexpression_1;
    }
    return _xifexpression;
  }

  protected CharSequence evalPathAndTest(final SynonymCondition cond, final List attributePath, final String pathList, final int attributeConditionIndex) {
    StringConcatenation _builder = new StringConcatenation();
    {
      if ((pathList != "")) {
        _builder.append("// evaluate path and test");
        _builder.newLine();
        CharSequence _conditionTrue = this.conditionTrue(cond, attributePath, pathList, attributeConditionIndex);
        _builder.append(_conditionTrue);
        _builder.newLineIfNotEmpty();
      }
    }
    return _builder;
  }

  /**
   * If the conditional mapping predicate resolves to true, this method code generates the logic.
   */
  private CharSequence conditionTrue(final SynonymCondition cond, final List attributePath, final String pathList, final int attributeConditionIndex) {
    StringConcatenation _builder = new StringConcatenation();
    {
      RosettaMapTestExpression _setToValue = cond.getSetToValue();
      boolean _tripleNotEquals = (_setToValue != null);
      if (_tripleNotEquals) {
        _builder.append("// `set to` conditional mapping");
        _builder.newLine();
        {
          boolean _exists = IterableUtil.exists(cond.getCondition(), SynonymPathTest.class);
          if (_exists) {
            _builder.append("// (c) ");
            final Function1 _function = (SynonymTest it) -> {
              return it.getClass().getSimpleName();
            };
            String _join = IterableExtensions.join(ListExtensions.map(cond.getCondition(), _function), ",");
            _builder.append(_join);
            _builder.newLineIfNotEmpty();
            final ArrayList underlying = this.toFirstMultiple(attributePath);
            _builder.newLineIfNotEmpty();
            {
              int _size = underlying.size();
              boolean _greaterThan = (_size > 0);
              if (_greaterThan) {
                _builder.append("// nested set to (synonym path predicate)");
                _builder.newLine();
                {
                  boolean _terMultipleCardinality = this.getterMultipleCardinality(this.postFirstMultiple(attributePath));
                  if (_terMultipleCardinality) {
                    _builder.append("int index=Integer.MAX_VALUE;");
                    _builder.newLine();
                  }
                }
                _builder.append("evaluateConditionalPaths(");
                _builder.newLine();
                _builder.append("\t");
                {
                  boolean _multipleCardinality = this.multipleCardinality(attributePath);
                  if (_multipleCardinality) {
                    final Function1 _function_1 = (ExpandedAttribute it) -> {
                      return it.getName();
                    };
                    String _firstLower = StringExtensions.toFirstLower(IterableExtensions.join(ListExtensions.map(underlying, _function_1), ""));
                    _builder.append(_firstLower, "\t");
                    _builder.append("Underlyers,");
                    _builder.newLineIfNotEmpty();
                    _builder.append("\t");
                  } else {
                    _builder.append("get");
                    final Function1 _function_2 = (ExpandedAttribute it) -> {
                      return it.getName();
                    };
                    String _firstUpper = StringExtensions.toFirstUpper(IterableExtensions.join(ListExtensions.map(underlying, _function_2), ""));
                    _builder.append(_firstUpper, "\t");
                    _builder.append("UnderlyerB(),");
                    _builder.newLineIfNotEmpty();
                    _builder.append("\t");
                    _builder.append("getXmlPathsToHere(),");
                  }
                }
                _builder.newLineIfNotEmpty();
                _builder.append("\t");
                _builder.append("handler -> handler.getUnderlying().");
                String _parentGetters = this.parentGetters(this.postFirstMultiple(attributePath));
                _builder.append(_parentGetters, "\t");
                _builder.append("set");
                String _firstUpper_1 = StringExtensions.toFirstUpper(IterableExtensions.last(attributePath).getName());
                _builder.append(_firstUpper_1, "\t");
                _builder.append("(");
                CharSequence _evaluate = this.evaluate(cond.getSetToValue());
                _builder.append(_evaluate, "\t");
                _builder.append("),");
                _builder.newLineIfNotEmpty();
                _builder.append("\t");
                _builder.append("ImmutableList.of(\"");
                final Function1 _function_3 = (SynonymPathTest it) -> {
                  return it.getPathWithDots();
                };
                String _join_1 = IterableExtensions.join(IterableExtensions.map(Iterables.filter(cond.getCondition(), SynonymPathTest.class), _function_3), "\",\"");
                _builder.append(_join_1, "\t");
                _builder.append("\")");
                {
                  boolean _exists_1 = IterableUtil.exists(cond.getCondition(), SynonymBinaryTest.class);
                  if (_exists_1) {
                    _builder.append(",");
                    _builder.newLineIfNotEmpty();
                    _builder.append("\t");
                    CharSequence _pathMatchBinary = this.toPathMatchBinary(Iterables.filter(cond.getCondition(), SynonymBinaryTest.class));
                    _builder.append(_pathMatchBinary, "\t");
                  }
                }
                _builder.append(");");
                _builder.newLineIfNotEmpty();
              } else {
                _builder.append("// set to (synonym path predicate)");
                _builder.newLine();
                _builder.append("Set paths = getXmlPathsToHere();");
                _builder.newLine();
                _builder.append("if (paths.stream().anyMatch(p -> ");
                {
                  Iterable _filter = Iterables.filter(cond.getCondition(), SynonymPathTest.class);
                  boolean _hasElements = false;
                  for(final SynonymPathTest test : _filter) {
                    if (!_hasElements) {
                      _hasElements = true;
                    } else {
                      _builder.appendImmediate(" || ", "");
                    }
                    _builder.append("p.endsWith(Path.parse(\"");
                    String _pathWithDots = test.getPathWithDots();
                    _builder.append(_pathWithDots);
                    _builder.append("\").getPathNames())");
                  }
                }
                _builder.append(")) {\t");
                _builder.newLineIfNotEmpty();
                _builder.append("\t");
                _builder.append("set");
                String _firstUpper_2 = StringExtensions.toFirstUpper(IterableExtensions.last(attributePath).getName());
                _builder.append(_firstUpper_2, "\t");
                _builder.append("(");
                CharSequence _evaluate_1 = this.evaluate(cond.getSetToValue());
                _builder.append(_evaluate_1, "\t");
                _builder.append(");");
                _builder.newLineIfNotEmpty();
                _builder.append("\t");
                _builder.append("return;");
                _builder.newLine();
                _builder.append("}");
                _builder.newLine();
              }
            }
          } else {
            _builder.append("// (d) ");
            final Function1 _function_4 = (SynonymTest it) -> {
              return it.getClass().getSimpleName();
            };
            String _join_2 = IterableExtensions.join(ListExtensions.map(cond.getCondition(), _function_4), ",");
            _builder.append(_join_2);
            _builder.newLineIfNotEmpty();
            {
              boolean _multipleCardinality_1 = this.multipleCardinality(attributePath);
              if (_multipleCardinality_1) {
                _builder.append("// set to (rosetta path predicate) that has multiple cardinality");
                _builder.newLine();
                {
                  boolean _terMultipleCardinality_1 = this.getterMultipleCardinality(attributePath);
                  if (_terMultipleCardinality_1) {
                    _builder.append("int relativeIndex = ");
                    _builder.append(attributeConditionIndex);
                    _builder.append(";");
                    _builder.newLineIfNotEmpty();
                    _builder.append("// TODO This line needs further explanation");
                    _builder.newLine();
                    _builder.append("int index = (relativeIndex == 0 || relativeIndex == 1) ? 0 : 1;");
                    _builder.newLine();
                  }
                }
                CharSequence _setterChain = this.setterChain(attributePath);
                _builder.append(_setterChain);
                _builder.append("(");
                CharSequence _evaluate_2 = this.evaluate(cond.getSetToValue());
                _builder.append(_evaluate_2);
                _builder.append(");");
                _builder.newLineIfNotEmpty();
              } else {
                _builder.append("// set to (rosetta path predicate) that has single cardinality");
                _builder.newLine();
                CharSequence _setterChain_1 = this.setterChain(attributePath);
                _builder.append(_setterChain_1);
                _builder.append("(");
                CharSequence _evaluate_3 = this.evaluate(cond.getSetToValue());
                _builder.append(_evaluate_3);
                _builder.append(");");
                _builder.newLineIfNotEmpty();
              }
            }
          }
        }
      } else {
        boolean _notEquals = (!Objects.equal(pathList, ""));
        if (_notEquals) {
          _builder.append("// `set when` conditional mapping");
          _builder.newLine();
          {
            boolean _exists_2 = IterableUtil.exists(cond.getCondition(), SynonymPathTest.class);
            if (_exists_2) {
              _builder.append("// (e) ");
              final Function1 _function_5 = (SynonymTest it) -> {
                return it.getClass().getSimpleName();
              };
              String _join_3 = IterableExtensions.join(ListExtensions.map(cond.getCondition(), _function_5), ",");
              _builder.append(_join_3);
              _builder.newLineIfNotEmpty();
              _builder.append("// set rosetta path that has single cardinality");
              _builder.newLine();
              _builder.append("Set paths = getXmlPathsToHere();");
              _builder.newLine();
              _builder.append("if (paths.stream().anyMatch(p -> ");
              {
                Iterable _filter_1 = Iterables.filter(cond.getCondition(), SynonymPathTest.class);
                boolean _hasElements_1 = false;
                for(final SynonymPathTest test_1 : _filter_1) {
                  if (!_hasElements_1) {
                    _hasElements_1 = true;
                  } else {
                    _builder.appendImmediate(" || ", "");
                  }
                  _builder.append("p.endsWith(Path.parse(\"");
                  String _pathWithDots_1 = test_1.getPathWithDots();
                  _builder.append(_pathWithDots_1);
                  _builder.append("\").getPathNames())");
                }
              }
              _builder.append(")) {\t");
              _builder.newLineIfNotEmpty();
              _builder.append("\t");
              CharSequence _conditionSetterSingleCardinality = this.conditionSetterSingleCardinality(attributePath, pathList);
              _builder.append(_conditionSetterSingleCardinality, "\t");
              _builder.newLineIfNotEmpty();
              _builder.append("}");
              _builder.newLine();
            } else {
              _builder.append("// (f) ");
              final Function1 _function_6 = (SynonymTest it) -> {
                return it.getClass().getSimpleName();
              };
              String _join_4 = IterableExtensions.join(ListExtensions.map(cond.getCondition(), _function_6), ",");
              _builder.append(_join_4);
              _builder.newLineIfNotEmpty();
              {
                boolean _multipleCardinality_2 = this.multipleCardinality(attributePath);
                if (_multipleCardinality_2) {
                  _builder.append("// set rosetta path that has multiple cardinality");
                  _builder.newLine();
                  {
                    boolean _terMultipleCardinality_2 = this.getterMultipleCardinality(attributePath);
                    if (_terMultipleCardinality_2) {
                      _builder.append("// getOrCreateFoo(MAX_VALUE) creates new list item at next available index");
                      _builder.newLine();
                      _builder.append("int index = Integer.MAX_VALUE;");
                      _builder.newLine();
                    }
                  }
                  _builder.append("for (");
                  CharSequence _expandedTypeToBuilder = this.expandedTypeToBuilder(IterableExtensions.last(attributePath).getType());
                  _builder.append(_expandedTypeToBuilder);
                  _builder.append(" b : GeneratorPathUtil.getValuesForPathEnding(");
                  String _attPathName = this.toAttPathName(attributePath);
                  _builder.append(_attPathName);
                  _builder.append("Values, ImmutableList.of(\"");
                  _builder.append(pathList);
                  _builder.append("\"))) {");
                  _builder.newLineIfNotEmpty();
                  _builder.append("\t");
                  CharSequence _setterChain_2 = this.setterChain(attributePath);
                  _builder.append(_setterChain_2, "\t");
                  _builder.append("(b);");
                  _builder.newLineIfNotEmpty();
                  _builder.append("}");
                  _builder.newLine();
                } else {
                  CharSequence _conditionSetterSingleCardinality_1 = this.conditionSetterSingleCardinality(attributePath, pathList);
                  _builder.append(_conditionSetterSingleCardinality_1);
                  _builder.newLineIfNotEmpty();
                }
              }
            }
          }
        }
      }
    }
    _builder.newLine();
    return _builder;
  }

  public CharSequence conditionSetterSingleCardinality(final List attributePath, final String pathList) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("// set rosetta path that has single cardinality");
    _builder.newLine();
    _builder.append("Optional<");
    CharSequence _expandedTypeToBuilder = this.expandedTypeToBuilder(IterableExtensions.last(attributePath).getType());
    _builder.append(_expandedTypeToBuilder);
    _builder.append("> val = GeneratorPathUtil.getValueForPath(");
    String _attPathName = this.toAttPathName(attributePath);
    _builder.append(_attPathName);
    _builder.append("Values, ImmutableList.of(\"");
    _builder.append(pathList);
    _builder.append("\"));");
    _builder.newLineIfNotEmpty();
    _builder.append("if (val.isPresent()) {");
    _builder.newLine();
    {
      boolean _isType = IterableExtensions.last(attributePath).getType().isType();
      if (_isType) {
        _builder.append("\t");
        CharSequence _expandedTypeToBuilder_1 = this.expandedTypeToBuilder(IterableExtensions.last(attributePath).getType());
        _builder.append(_expandedTypeToBuilder_1, "\t");
        _builder.append(" builder = val.get();");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        _builder.append("new IngestMerger().run(builder, ");
        CharSequence _terChain = this.getterChain(attributePath);
        _builder.append(_terChain, "\t");
        _builder.append(");");
        _builder.newLineIfNotEmpty();
        _builder.append("\t");
        CharSequence _setterChain = this.setterChain(attributePath);
        _builder.append(_setterChain, "\t");
        _builder.append("(builder);");
        _builder.newLineIfNotEmpty();
      } else {
        _builder.append("\t");
        CharSequence _setterChain_1 = this.setterChain(attributePath);
        _builder.append(_setterChain_1, "\t");
        _builder.append("(val.get());");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t");
    _builder.append("return;");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  public CharSequence toPathMatchBinary(final Iterable tests) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("ps -> ");
    {
      boolean _hasElements = false;
      for(final SynonymBinaryTest test : tests) {
        if (!_hasElements) {
          _hasElements = true;
        } else {
          _builder.appendImmediate(" && ", "");
        }
        _builder.newLineIfNotEmpty();
        _builder.append("GeneratorPathUtil.getPathMatchingValues(ps, ");
        String _pathName = this.toPathName(IterableExtensions.last(test.getPaths()));
        _builder.append(_pathName);
        _builder.append("Values).stream().anyMatch(s -> ");
        String _java = this.toJava(test.getOperator());
        _builder.append(_java);
        _builder.append("(s,");
        CharSequence _java_1 = this.toJava(test.getRightPath(), test.getRightLiteral());
        _builder.append(_java_1);
        _builder.append("))");
        _builder.newLineIfNotEmpty();
      }
    }
    return _builder;
  }

  private String toPathList(final SynonymGroup group) {
    final Function1 _function = (SynonymValue it) -> {
      final Function1 _function_1 = (Element it_1) -> {
        return it_1.getName();
      };
      return IterableExtensions.join(ListExtensions.map(it.getSynonymPath(), _function_1), ".");
    };
    List _map = ListExtensions.map(group.getSynonymValues(), _function);
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("\", \"");
    return IterableExtensions.join(_map, _builder);
  }

  private CharSequence setterChain(final List path) {
    StringConcatenation _builder = new StringConcatenation();
    String _parentGetters = this.parentGetters(path);
    _builder.append(_parentGetters);
    CharSequence _setter = this.setter(path);
    _builder.append(_setter);
    return _builder;
  }

  private CharSequence getterChain(final List path) {
    StringConcatenation _builder = new StringConcatenation();
    String _parentGetters = this.parentGetters(path);
    _builder.append(_parentGetters);
    String _ter = this.getter(IterableExtensions.last(path));
    _builder.append(_ter);
    return _builder;
  }

  private String parentGetters(final List path) {
    final Function1 _function = (ExpandedAttribute a) -> {
      return this.getter(a);
    };
    return IterableExtensions.join(this.removeLast(path), "", ".", ".", _function);
  }

  private String attributeGetters(final List path) {
    final Function1 _function = (ExpandedAttribute a) -> {
      return this.getter(a);
    };
    return IterableExtensions.join(path, "", ".", ".", _function);
  }

  private String getter(final ExpandedAttribute att) {
    String _xifexpression = null;
    boolean _isMultiple = att.isMultiple();
    if (_isMultiple) {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("getOrCreate");
      String _firstUpper = StringExtensions.toFirstUpper(att.getName());
      _builder.append(_firstUpper);
      _builder.append("(index)");
      _xifexpression = _builder.toString();
    } else {
      StringConcatenation _builder_1 = new StringConcatenation();
      _builder_1.append("getOrCreate");
      String _firstUpper_1 = StringExtensions.toFirstUpper(att.getName());
      _builder_1.append(_firstUpper_1);
      _builder_1.append("()");
      _xifexpression = _builder_1.toString();
    }
    return _xifexpression;
  }

  private CharSequence setter(final List path) {
    StringConcatenation _builder = new StringConcatenation();
    {
      boolean _cardinalityIsSingleValue = RosettaAttributeExtensions.cardinalityIsSingleValue(IterableExtensions.last(path));
      if (_cardinalityIsSingleValue) {
        _builder.append("set");
      } else {
        _builder.append("add");
      }
    }
    String _firstUpper = StringExtensions.toFirstUpper(IterableExtensions.last(path).getName());
    _builder.append(_firstUpper);
    return _builder;
  }

  private CharSequence _evaluate(final RosettaMapTestExpression expression) {
    Class _class = expression.getClass();
    String _plus = ("Don\'t know how to evaluate expression " + _class);
    throw new UnsupportedOperationException(_plus);
  }

  private CharSequence _evaluate(final RosettaLiteral expression) {
    return expression.stringValue();
  }

  private CharSequence _evaluate(final RosettaEnumValueReference ref) {
    StringConcatenation _builder = new StringConcatenation();
    String _trim = IterableUtil.fullname(ref.getEnumeration()).trim();
    _builder.append(_trim);
    _builder.append(".");
    String _formatEnumName = EnumHelper.formatEnumName(ref.getValue().getName());
    _builder.append(_formatEnumName);
    return _builder;
  }

  private CharSequence _handleTest(final SynonymTest test, final String pathList, final List attributePath) {
    Class _class = test.getClass();
    String _plus = ("Don\'t know how to generate test for " + _class);
    throw new UnsupportedOperationException(_plus);
  }

  private CharSequence _handleTest(final SynonymExistsTest test, final String pathList, final List attributePath) {
    StringConcatenation _builder = new StringConcatenation();
    String _pathName = this.toPathName(test.getPath());
    _builder.append(_pathName);
    _builder.append("Value != null");
    return _builder;
  }

  private CharSequence _handleTest(final SynonymAbsentTest test, final String pathList, final List attributePath) {
    StringConcatenation _builder = new StringConcatenation();
    String _pathName = this.toPathName(test.getPath());
    _builder.append(_pathName);
    _builder.append("Value == null");
    return _builder;
  }

  private CharSequence _handleTest(@Extension final SynonymBinaryTest test, final String pathList, final List attributePath) {
    StringConcatenation _builder = new StringConcatenation();
    String _java = this.toJava(test.getOperator());
    _builder.append(_java);
    _builder.append("(");
    CharSequence _java_1 = this.toJava(test.getLeftPath(), test.getLeftLiteral());
    _builder.append(_java_1);
    _builder.append(",");
    CharSequence _java_2 = this.toJava(test.getRightPath(), test.getRightLiteral());
    _builder.append(_java_2);
    _builder.append(")");
    return _builder;
  }

  private CharSequence _handleTest(final SynonymPathTest test, final String pathList, final List attributePath) {
    return "true";
  }

  private CharSequence _handleTest(final SynonymRosettaPathTest test, final String pathList, final List attributePath) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("GeneratorPathUtil.endsWith(getRosettaPath().");
    final Function1 _function = (ExpandedAttribute it) -> {
      return it.getName();
    };
    final Function1 _function_1 = (String it) -> {
      return (("addElement(\"" + it) + "\")");
    };
    String _join = IterableExtensions.join(ListExtensions.map(ListExtensions.map(attributePath, _function), _function_1), ".");
    _builder.append(_join);
    _builder.append(".getParent(), \"");
    CharSequence _dotSepDropFirst = this.toDotSepDropFirst(test.getPath());
    _builder.append(_dotSepDropFirst);
    _builder.append("\")");
    return _builder;
  }

  private CharSequence _handleTest(final SynonymConditionFuncTest test, final String pathList, final List attributePath) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("injector.getInstance(");
    String _funcClassName = test.getFuncClassName();
    _builder.append(_funcClassName);
    _builder.append(".class)");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append(".evaluate(getSynonymPathForConditionFunc(getXmlPathsToHere(), \"");
    _builder.append(pathList, "\t\t");
    _builder.append("\"), ");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t\t\t");
    _builder.append("formatPathWithNoIndexesAndSeparators(getRosettaPath()), ");
    _builder.newLine();
    _builder.append("\t\t\t\t");
    {
      List _predicatePathEndsWith = test.getPredicatePathEndsWith();
      boolean _tripleNotEquals = (_predicatePathEndsWith != null);
      if (_tripleNotEquals) {
        _builder.append("getValuesFromConditionPath(");
        final Function1 _function = (String it) -> {
          return (("\"" + it) + "\"");
        };
        String _join = IterableExtensions.join(ListExtensions.map(test.getPredicatePathEndsWith(), _function), ", ");
        _builder.append(_join, "\t\t\t\t");
        _builder.append(")");
      } else {
        _builder.append("null");
      }
    }
    _builder.append(")");
    return _builder;
  }

  private CharSequence toJava(final SynonymValue path, final RosettaMapTestExpression literal) {
    CharSequence _xifexpression = null;
    if ((path != null)) {
      String _pathName = this.toPathName(path);
      _xifexpression = (_pathName + "Value");
    } else {
      _xifexpression = this.handleWhenRight(literal);
    }
    return _xifexpression;
  }

  private String toJava(final String op) {
    String _switchResult = null;
    if (op != null) {
      switch (op) {
        case "=":
          _switchResult = "areEqual";
          break;
        case "<>":
          _switchResult = "!areEqual";
          break;
        default:
          throw new UnsupportedOperationException((("test operator " + op) + " not currently supported"));
      }
    } else {
      throw new UnsupportedOperationException((("test operator " + op) + " not currently supported"));
    }
    return _switchResult;
  }

  private CharSequence _toDotSep(final RosettaAttributeReference call) {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _dotSep = this.toDotSep(call.getReceiver());
    _builder.append(_dotSep);
    _builder.append(".");
    String _name = call.getAttribute().getName();
    _builder.append(_name);
    return _builder;
  }

  private CharSequence _toDotSep(final RosettaDataReference call) {
    StringConcatenation _builder = new StringConcatenation();
    String _name = call.getData().getName();
    _builder.append(_name);
    return _builder;
  }

  private CharSequence _toDotSepDropFirst(final RosettaAttributeReference call) {
    StringConcatenation _builder = new StringConcatenation();
    CharSequence _dotSepDropFirst = this.toDotSepDropFirst(call.getReceiver());
    _builder.append(_dotSepDropFirst);
    String _name = call.getAttribute().getName();
    _builder.append(_name);
    _builder.append(".");
    return _builder;
  }

  private CharSequence _toDotSepDropFirst(final RosettaDataReference call) {
    StringConcatenation _builder = new StringConcatenation();
    return _builder;
  }

  private CharSequence _handleWhenRight(final RosettaMapTestExpression right) {
    String _simpleName = right.getClass().getSimpleName();
    String _plus = ("Unsupported expression type " + _simpleName);
    throw new UnsupportedOperationException(_plus);
  }

  private CharSequence _handleWhenRight(final RosettaStringLiteral right) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("\"");
    String _value = right.getValue();
    _builder.append(_value);
    _builder.append("\"");
    return _builder;
  }

  private CharSequence _handleWhenRight(final RosettaBooleanLiteral right) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("Boolean.valueOf(");
    boolean _isValue = right.isValue();
    _builder.append(_isValue);
    _builder.append(")");
    return _builder;
  }

  private CharSequence _handleWhenRight(final RosettaIntLiteral right) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("Integer.valueOf(");
    BigInteger _value = right.getValue();
    _builder.append(_value);
    _builder.append(")");
    return _builder;
  }

  private CharSequence _handleWhenRight(final RosettaNumberLiteral right) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("BigDecimal.valueOf(");
    BigDecimal _value = right.getValue();
    _builder.append(_value);
    _builder.append(")");
    return _builder;
  }

  private void generateEnumParsers(final SynonymMap mapping, final Map generated, final String childName, final Map synHashCache) {
    boolean _containsKey = generated.containsKey(IterableUtil.fullname(mapping.getRosetta()));
    if (_containsKey) {
      return;
    }
    final Long prevHash = synHashCache.get(IterableUtil.fullname(mapping.getRosetta()));
    final long newHash = mapping.hashForGeneration();
    if (((prevHash == null) || (newHash != (prevHash).longValue()))) {
      StringConcatenation _builder = new StringConcatenation();
      _builder.append("package ");
      _builder.append(childName);
      _builder.append(".");
      String _packageName = IterableUtil.packageName(mapping.getRosetta());
      _builder.append(_packageName);
      _builder.append(";");
      _builder.newLineIfNotEmpty();
      _builder.newLine();
      _builder.append("import java.util.Map;");
      _builder.newLine();
      _builder.newLine();
      String _basicEnumParserImports = this.basicEnumParserImports(mapping);
      _builder.append(_basicEnumParserImports);
      _builder.newLineIfNotEmpty();
      _builder.newLine();
      _builder.append("public class ");
      CharSequence _pNameW = this.pNameW(mapping);
      _builder.append(_pNameW);
      _builder.append(" extends EnumParseHandler<");
      String _rosettaName = mapping.rosettaName();
      _builder.append(_rosettaName);
      _builder.append("> {");
      _builder.newLineIfNotEmpty();
      _builder.append("\t");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("private final Map lookup;");
      _builder.newLineIfNotEmpty();
      _builder.append("\t");
      _builder.newLine();
      _builder.append("\t");
      CharSequence _enumConstructor = this.enumConstructor(mapping);
      _builder.append(_enumConstructor, "\t");
      _builder.newLineIfNotEmpty();
      _builder.append("\t");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("@Override");
      _builder.newLine();
      _builder.append("\t");
      _builder.append("protected ");
      String _rosettaName_2 = mapping.rosettaName();
      _builder.append(_rosettaName_2, "\t");
      _builder.append(" convert(String value) {");
      _builder.newLineIfNotEmpty();
      _builder.append("\t\t");
      String _rosettaName_3 = mapping.rosettaName();
      _builder.append(_rosettaName_3, "\t\t");
      _builder.append(" enumValue = lookup.get(value);");
      _builder.newLineIfNotEmpty();
      _builder.append("\t\t");
      _builder.append("if (enumValue!=null) return enumValue;");
      _builder.newLine();
      _builder.append("\t\t");
      _builder.append("throw new RuntimeException(\"Could not find matching ");
      String _name = mapping.getRosetta().getName();
      _builder.append(_name, "\t\t");
      _builder.append(" for [\" + value + \"]\");");
      _builder.newLineIfNotEmpty();
      _builder.append("\t");
      _builder.append("}");
      _builder.newLine();
      _builder.append("}");
      _builder.newLine();
      String parser = _builder.toString();
      String _fullname = IterableUtil.fullname(mapping.getRosetta());
      GenerationResult _generationResult = new GenerationResult(false, parser);
      generated.put(_fullname, _generationResult);
      synHashCache.put(IterableUtil.fullname(mapping.getRosetta()), Long.valueOf(newHash));
    } else {
      String _fullname_1 = IterableUtil.fullname(mapping.getRosetta());
      GenerationResult _generationResult_1 = new GenerationResult(true, null);
      generated.put(_fullname_1, _generationResult_1);
    }
  }

  private CharSequence enumConstructor(final SynonymMap mapping) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("public ");
    String _name = mapping.getRosetta().getName();
    _builder.append(_name);
    _builder.append("ParseHandler(boolean allowsMultiple, boolean condition, boolean removeHtml) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("this(allowsMultiple, condition, removeHtml, null, null);");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    _builder.newLine();
    _builder.append("public ");
    String _name_1 = mapping.getRosetta().getName();
    _builder.append(_name_1);
    _builder.append("ParseHandler(boolean allowsMultiple, boolean condition, boolean removeHtml, String patternMatch, String patternReplace) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.append("super(allowsMultiple, condition, removeHtml, patternMatch, patternReplace);");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("ImmutableMap.Builder builder = ImmutableMap.builder();");
    _builder.newLineIfNotEmpty();
    {
      List _sort = IterableExtensions.sort(mapping.attributeGroups());
      for(final AttributeGroup attrPathSynGroup : _sort) {
        {
          final Function1> _function = (SynonymGroup sp) -> {
            return sp.getSynonymValues();
          };
          final Function1 _function_1 = (SynonymValue it) -> {
            final Function1 _function_2 = (Element it_1) -> {
              return it_1.getName();
            };
            return IterableExtensions.join(ListExtensions.map(it.getSynonymPath(), _function_2));
          };
          List _sortBy = IterableExtensions.sortBy(IterableExtensions.flatMap(attrPathSynGroup.getSynonymGroups(), _function), _function_1);
          for(final SynonymValue synonymValue : _sortBy) {
            _builder.append("\t\t\t");
            _builder.append("builder.put(\"");
            final Function1 _function_2 = (Element it) -> {
              return it.getName();
            };
            String _join = IterableExtensions.join(ListExtensions.map(synonymValue.getSynonymPath(), _function_2));
            _builder.append(_join, "\t\t\t");
            _builder.append("\", ");
            String _rosettaName_1 = mapping.rosettaName();
            _builder.append(_rosettaName_1, "\t\t\t");
            _builder.append(".");
            String _formatEnumName = EnumHelper.formatEnumName(IterableExtensions.last(attrPathSynGroup.getAttributePath()).getName());
            _builder.append(_formatEnumName, "\t\t\t");
            _builder.append(");");
            _builder.newLineIfNotEmpty();
          }
        }
      }
    }
    _builder.append("\t");
    _builder.append("lookup = builder.build();");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder;
  }

  private  String basicEnumParserImports(final SynonymMap mapping) {
    EObject _eContainer = mapping.getRosetta().eContainer();
    final RosettaModel rosettaModel = ((RosettaModel) _eContainer);
    final ArrayList imports = CollectionLiterals.newArrayList();
    CollectionExtensions.addAll(imports, "import com.google.common.collect.ImmutableMap", 
      "import com.regnosys.rosetta.translate.basic.EnumParseHandler", 
      "import com.regnosys.rosetta.common.translation.Path");
    String _name = rosettaModel.getName();
    String _plus = ("import " + _name);
    String _plus_1 = (_plus + ".");
    String _name_1 = mapping.getRosetta().getName();
    String _plus_2 = (_plus_1 + _name_1);
    imports.add(_plus_2);
    return imports.stream().sorted().distinct().collect(Collectors.joining(";\n", "", ";"));
  }

  public String generateXmlFactory(final String packageName, final String factoryName, final List generatorParamsList) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("package ");
    _builder.append(packageName);
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    _builder.append("import java.net.MalformedURLException;");
    _builder.newLine();
    _builder.append("import java.net.URL;");
    _builder.newLine();
    _builder.append("import java.nio.file.Files;");
    _builder.newLine();
    _builder.append("import java.nio.file.Path;");
    _builder.newLine();
    _builder.append("import java.nio.file.Paths;");
    _builder.newLine();
    _builder.append("import java.util.Map;");
    _builder.newLine();
    _builder.append("import java.util.HashMap;");
    _builder.newLine();
    _builder.newLine();
    _builder.append("import javax.xml.validation.Schema;");
    _builder.newLine();
    _builder.append("import javax.xml.validation.SchemaFactory;");
    _builder.newLine();
    _builder.newLine();
    _builder.append("import com.regnosys.rosetta.common.translation.MappingContext;");
    _builder.newLine();
    _builder.append("import com.regnosys.rosetta.common.util.UrlUtils;");
    _builder.newLine();
    _builder.append("import org.xml.sax.SAXException;");
    _builder.newLine();
    _builder.append("import com.google.inject.Injector;");
    _builder.newLine();
    _builder.newLine();
    _builder.append("import com.rosetta.model.lib.RosettaModelObject;");
    _builder.newLine();
    _builder.append("import com.regnosys.rosetta.translate.*;");
    _builder.newLine();
    {
      final Function1> _function = (GeneratorParams it) -> {
        return it.getTopLevelTags();
      };
      boolean _isEmpty = IterableExtensions.isEmpty(Iterables.concat(ListExtensions.>map(generatorParamsList, _function)));
      boolean _not = (!_isEmpty);
      if (_not) {
        _builder.append("import java.util.Arrays;");
        _builder.newLine();
      }
    }
    _builder.append("import java.util.function.Function;");
    _builder.newLine();
    _builder.newLine();
    _builder.append("public class ");
    _builder.append(factoryName);
    _builder.append(" implements XmlHandlerFactory {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private final Function, HandlerSupplier>> factory;");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private final Map, Schema> schemas = new HashMap<>();");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private static final SchemaFactory SCHEMA_FACTORY = SchemaFactory.newInstance(\"http://www.w3.org/2001/XMLSchema\");");
    _builder.newLine();
    {
      final Function1 _function_1 = (GeneratorParams it) -> {
        return it.getSchema();
      };
      List _map = ListExtensions.map(generatorParamsList, _function_1);
      for(final URL xsdUrl : _map) {
        _builder.append("\t");
        _builder.append("private static Schema ");
        String _urlToStaticVar = this.urlToStaticVar(xsdUrl);
        _builder.append(_urlToStaticVar, "\t");
        _builder.append(" = newSchema(\"");
        {
          String _protocol = xsdUrl.getProtocol();
          boolean _equals = Objects.equal(_protocol, "jar");
          if (_equals) {
            String _last = IterableExtensions.last(Splitter.on("!/").split(xsdUrl.getPath()));
            _builder.append(_last, "\t");
          } else {
            String _escapeJava = StringEscapeUtils.escapeJava(UrlUtils.toPath(xsdUrl).toString());
            _builder.append(_escapeJava, "\t");
          }
        }
        _builder.append("\");");
        _builder.newLineIfNotEmpty();
      }
    }
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private final Injector injector;");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@javax.inject.Inject");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    _builder.append(factoryName, "\t");
    _builder.append("(Injector injector) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("this.injector = injector;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.factory = (mappingContext) -> {");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("Map, HandlerSupplier> handlerMap = new HashMap<>();");
    _builder.newLine();
    {
      for(final GeneratorParams params : generatorParamsList) {
        {
          Collection _rosettaEntities = params.getRosettaEntities();
          for(final RosettaType rmo : _rosettaEntities) {
            {
              boolean _isEmpty_1 = params.getTopLevelTags().isEmpty();
              if (_isEmpty_1) {
                _builder.append("\t\t\t\t");
                _builder.append("handlerMap.put(");
                String _fullname = IterableUtil.fullname(rmo);
                _builder.append(_fullname, "\t\t\t\t");
                _builder.append(".class, (a, b) -> new ");
                CharSequence _pFullNameT = this.pFullNameT(rmo, params.getChildPackageName());
                _builder.append(_pFullNameT, "\t\t\t\t");
                _builder.append("(injector, mappingContext));");
                _builder.newLineIfNotEmpty();
              } else {
                _builder.append("\t\t\t\t");
                _builder.append("handlerMap.put(");
                String _fullname_1 = IterableUtil.fullname(rmo);
                _builder.append(_fullname_1, "\t\t\t\t");
                _builder.append(".class, (a, b) -> new RootHandler<>(\"");
                String _name = rmo.getName();
                _builder.append(_name, "\t\t\t\t");
                _builder.append("\", new ");
                CharSequence _pFullNameT_1 = this.pFullNameT(rmo, params.getChildPackageName());
                _builder.append(_pFullNameT_1, "\t\t\t\t");
                _builder.append("(injector, mappingContext), Arrays.asList(");
                final Function1 _function_2 = (String it) -> {
                  return (("\"" + it) + "\"");
                };
                String _join = IterableExtensions.join(IterableExtensions.map(params.getTopLevelTags(), _function_2), ", ");
                _builder.append(_join, "\t\t\t\t");
                _builder.append(")));");
                _builder.newLineIfNotEmpty();
              }
            }
          }
        }
      }
    }
    _builder.append("\t\t\t");
    _builder.append("return handlerMap;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("};");
    _builder.newLine();
    {
      for(final GeneratorParams params_1 : generatorParamsList) {
        {
          Collection _rosettaEntities_1 = params_1.getRosettaEntities();
          for(final RosettaType rmo_1 : _rosettaEntities_1) {
            _builder.append("\t\t");
            _builder.append("schemas.put(");
            String _fullname_2 = IterableUtil.fullname(rmo_1);
            _builder.append(_fullname_2, "\t\t");
            _builder.append(".class, ");
            String _urlToStaticVar_1 = this.urlToStaticVar(params_1.getSchema());
            _builder.append(_urlToStaticVar_1, "\t\t");
            _builder.append(");");
            _builder.newLineIfNotEmpty();
          }
        }
      }
    }
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@Override");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Map, HandlerSupplier> getHandlerSuppliers(MappingContext mappingContext) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("return factory.apply(mappingContext);");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@Override ");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Map, Schema> getSchemas() {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("return schemas;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private static Path getXsdPath(String xsdFilePath) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("Path path = Paths.get(xsdFilePath);");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("if (Files.exists(path)) {");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("return path;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("}");
    _builder.newLine();
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("URL resource = ");
    _builder.append(factoryName, "\t\t");
    _builder.append(".class.getClassLoader().getResource(xsdFilePath);");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("if (resource != null) {");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("return UrlUtils.toPath(resource);");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("}");
    _builder.newLine();
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("throw new IngestException(\"Error reading xsd file - \" + xsdFilePath + \" could not be found\");");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private static Schema newSchema(String schemaUrl) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("try {");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("return SCHEMA_FACTORY.newSchema(getXsdPath(schemaUrl).toUri().toURL());");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("} catch (SAXException | MalformedURLException e) {");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("throw new IngestException(\"Failed to create Schema URL for \" + schemaUrl, e);");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@Override");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Injector getInjector() {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("return injector;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder.toString();
  }

  public String generateJsonFactory(final String packageName, final String factoryName, final List generatorParamsList) {
    StringConcatenation _builder = new StringConcatenation();
    _builder.append("package ");
    _builder.append(packageName);
    _builder.append(";");
    _builder.newLineIfNotEmpty();
    _builder.newLine();
    _builder.append("import java.net.MalformedURLException;");
    _builder.newLine();
    _builder.append("import java.net.URL;");
    _builder.newLine();
    _builder.append("import java.util.Map;");
    _builder.newLine();
    _builder.append("import java.util.HashMap;");
    _builder.newLine();
    _builder.newLine();
    _builder.append("import com.google.inject.Injector;");
    _builder.newLine();
    _builder.newLine();
    _builder.append("import com.regnosys.rosetta.common.translation.MappingContext;");
    _builder.newLine();
    _builder.append("import com.rosetta.model.lib.RosettaModelObject;");
    _builder.newLine();
    _builder.append("import com.regnosys.rosetta.translate.*;");
    _builder.newLine();
    _builder.append("import com.regnosys.rosetta.translate.basic.*;");
    _builder.newLine();
    {
      final Function1> _function = (GeneratorParams it) -> {
        return it.getTopLevelTags();
      };
      boolean _isEmpty = IterableExtensions.isEmpty(Iterables.concat(ListExtensions.>map(generatorParamsList, _function)));
      boolean _not = (!_isEmpty);
      if (_not) {
        _builder.append("import java.util.Arrays;");
        _builder.newLine();
      }
    }
    _builder.append("import java.util.function.Function;");
    _builder.newLine();
    _builder.newLine();
    _builder.append("public class ");
    _builder.append(factoryName);
    _builder.append(" implements JsonHandlerFactory {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private final Function, HandlerSupplier>> factory;");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("private final Injector injector;");
    _builder.newLine();
    _builder.append("\t");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@javax.inject.Inject");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public ");
    _builder.append(factoryName, "\t");
    _builder.append("(Injector injector) {");
    _builder.newLineIfNotEmpty();
    _builder.append("\t\t");
    _builder.append("this.injector = injector;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("this.factory = (mappingContext) -> {");
    _builder.newLine();
    _builder.append("\t\t\t");
    _builder.append("Map, HandlerSupplier> handlerMap = new HashMap<>();");
    _builder.newLine();
    {
      for(final GeneratorParams params : generatorParamsList) {
        {
          Collection _rosettaEntities = params.getRosettaEntities();
          for(final RosettaType rmo : _rosettaEntities) {
            {
              boolean _isEmpty_1 = params.getTopLevelTags().isEmpty();
              if (_isEmpty_1) {
                _builder.append("\t\t\t\t");
                _builder.append("handlerMap.put(");
                String _fullname = IterableUtil.fullname(rmo);
                _builder.append(_fullname, "\t\t\t\t");
                _builder.append(".class, (a, b) -> new ");
                CharSequence _pFullNameT = this.pFullNameT(rmo, params.getChildPackageName());
                _builder.append(_pFullNameT, "\t\t\t\t");
                _builder.append("(injector, mappingContext));");
                _builder.newLineIfNotEmpty();
              } else {
                _builder.append("\t\t\t\t");
                _builder.append("handlerMap.put(");
                String _fullname_1 = IterableUtil.fullname(rmo);
                _builder.append(_fullname_1, "\t\t\t\t");
                _builder.append(".class, (a, b) -> new RootHandler<>(\"");
                String _name = rmo.getName();
                _builder.append(_name, "\t\t\t\t");
                _builder.append("\", new ");
                CharSequence _pFullNameT_1 = this.pFullNameT(rmo, params.getChildPackageName());
                _builder.append(_pFullNameT_1, "\t\t\t\t");
                _builder.append("(injector, mappingContext), Arrays.asList(");
                final Function1 _function_1 = (String it) -> {
                  return (("\"" + it) + "\"");
                };
                String _join = IterableExtensions.join(IterableExtensions.map(params.getTopLevelTags(), _function_1), ", ");
                _builder.append(_join, "\t\t\t\t");
                _builder.append(")));");
                _builder.newLineIfNotEmpty();
              }
            }
          }
        }
      }
    }
    _builder.append("\t\t\t");
    _builder.append("return handlerMap;");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("};");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@Override");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Map, HandlerSupplier> getHandlerSuppliers(MappingContext mappingContext) {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("return factory.apply(mappingContext);");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.newLine();
    _builder.append("\t");
    _builder.append("@Override");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("public Injector getInjector() {");
    _builder.newLine();
    _builder.append("\t\t");
    _builder.append("return injector;");
    _builder.newLine();
    _builder.append("\t");
    _builder.append("}");
    _builder.newLine();
    _builder.append("}");
    _builder.newLine();
    return _builder.toString();
  }

  private String urlToStaticVar(final URL u) {
    return UrlUtils.getFileName(u).replaceAll("[-,.]", "_").toUpperCase();
  }

  private SynonymValue removeLast(final SynonymValue synonymValue) {
    List _removeLast = this.removeLast(synonymValue.getSynonymPath());
    int _mapsTo = synonymValue.getMapsTo();
    boolean _isMeta = synonymValue.isMeta();
    return new SynonymValue(_removeLast, _mapsTo, _isMeta);
  }

  private AttributeGroup removeLast(final AttributeGroup group) {
    final Function1 _function = (SynonymGroup it) -> {
      return this.removeLast(it);
    };
    List _map = ListExtensions.map(group.getSynonymGroups(), _function);
    List _removeLast = this.removeLast(group.getAttributePath());
    return new AttributeGroup(_map, _removeLast);
  }

  private SynonymGroup removeLast(final SynonymGroup group) {
    final Function1 _function = (SynonymValue it) -> {
      return this.removeLast(it);
    };
    List _map = ListExtensions.map(group.getSynonymValues(), _function);
    List _conditions = group.getConditions();
    String _mapperName = group.getMapperName();
    String _formatString = group.getFormatString();
    String _patternMatcher = group.getPatternMatcher();
    String _patternReplace = group.getPatternReplace();
    boolean _isRemoveHtml = group.isRemoveHtml();
    return new SynonymGroup(_map, _conditions, _mapperName, _formatString, _patternMatcher, _patternReplace, _isRemoveHtml);
  }

  private  List removeLast(final List list) {
    int _size = list.size();
    int _minus = (_size - 1);
    return list.subList(0, _minus);
  }

  private Object penultimateBuilder(final List attributes, final SynonymMap mapping) {
    int _size = attributes.size();
    boolean _greaterEqualsThan = (_size >= 2);
    if (_greaterEqualsThan) {
      int _size_1 = attributes.size();
      int _minus = (_size_1 - 2);
      return this.expandedTypeToBuilder(attributes.get(_minus).getType());
    } else {
      return this.toBuilder(mapping.getRosetta());
    }
  }

  /**
   * @param atts - list of attributes represents a path (with attribute name/type for each path element).
   * @returns the first attribute that has multiple cardinality
   */
  private Object firstMultipleBuilder(final List attributes, final SynonymMap mapping) {
    ArrayList resAt = this.toFirstMultiple(attributes);
    int _size = resAt.size();
    boolean _greaterEqualsThan = (_size >= 1);
    if (_greaterEqualsThan) {
      return this.expandedTypeToBuilder(IterableExtensions.last(resAt).getType());
    } else {
      return this.toBuilder(mapping.getRosetta());
    }
  }

  public boolean isAbstract(final RosettaType type) {
    if (type instanceof com.regnosys.rosetta.rosetta.simple.Data) {
      return _isAbstract((com.regnosys.rosetta.rosetta.simple.Data)type);
    } else if (type != null) {
      return _isAbstract(type);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.asList(type).toString());
    }
  }

  private StringConcatenationClient toBuilder(final EObject type) {
    if (type instanceof RosettaBuiltinType) {
      return _toBuilder((RosettaBuiltinType)type);
    } else if (type instanceof RosettaEnumeration) {
      return _toBuilder((RosettaEnumeration)type);
    } else if (type instanceof RosettaTypeAlias) {
      return _toBuilder((RosettaTypeAlias)type);
    } else if (type instanceof com.regnosys.rosetta.rosetta.simple.Data) {
      return _toBuilder((com.regnosys.rosetta.rosetta.simple.Data)type);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.asList(type).toString());
    }
  }

  private CharSequence evaluate(final RosettaMapTestExpression ref) {
    if (ref instanceof RosettaEnumValueReference) {
      return _evaluate((RosettaEnumValueReference)ref);
    } else if (ref instanceof RosettaLiteral) {
      return _evaluate((RosettaLiteral)ref);
    } else if (ref != null) {
      return _evaluate(ref);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.asList(ref).toString());
    }
  }

  private CharSequence handleTest(final SynonymTest test, final String pathList, final List attributePath) {
    if (test instanceof SynonymAbsentTest) {
      return _handleTest((SynonymAbsentTest)test, pathList, attributePath);
    } else if (test instanceof SynonymBinaryTest) {
      return _handleTest((SynonymBinaryTest)test, pathList, attributePath);
    } else if (test instanceof SynonymConditionFuncTest) {
      return _handleTest((SynonymConditionFuncTest)test, pathList, attributePath);
    } else if (test instanceof SynonymExistsTest) {
      return _handleTest((SynonymExistsTest)test, pathList, attributePath);
    } else if (test instanceof SynonymPathTest) {
      return _handleTest((SynonymPathTest)test, pathList, attributePath);
    } else if (test instanceof SynonymRosettaPathTest) {
      return _handleTest((SynonymRosettaPathTest)test, pathList, attributePath);
    } else if (test != null) {
      return _handleTest(test, pathList, attributePath);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.asList(test, pathList, attributePath).toString());
    }
  }

  private CharSequence toDotSep(final RosettaAttributeReferenceSegment call) {
    if (call instanceof RosettaAttributeReference) {
      return _toDotSep((RosettaAttributeReference)call);
    } else if (call instanceof RosettaDataReference) {
      return _toDotSep((RosettaDataReference)call);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.asList(call).toString());
    }
  }

  private CharSequence toDotSepDropFirst(final RosettaAttributeReferenceSegment call) {
    if (call instanceof RosettaAttributeReference) {
      return _toDotSepDropFirst((RosettaAttributeReference)call);
    } else if (call instanceof RosettaDataReference) {
      return _toDotSepDropFirst((RosettaDataReference)call);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.asList(call).toString());
    }
  }

  private CharSequence handleWhenRight(final RosettaMapTestExpression right) {
    if (right instanceof RosettaBooleanLiteral) {
      return _handleWhenRight((RosettaBooleanLiteral)right);
    } else if (right instanceof RosettaIntLiteral) {
      return _handleWhenRight((RosettaIntLiteral)right);
    } else if (right instanceof RosettaNumberLiteral) {
      return _handleWhenRight((RosettaNumberLiteral)right);
    } else if (right instanceof RosettaStringLiteral) {
      return _handleWhenRight((RosettaStringLiteral)right);
    } else if (right != null) {
      return _handleWhenRight(right);
    } else {
      throw new IllegalArgumentException("Unhandled parameter types: " +
        Arrays.asList(right).toString());
    }
  }
}