MtasXMLParser.java

  1. package mtas.analysis.parser;

  2. import java.io.Reader;
  3. import java.util.Collection;
  4. import java.util.HashMap;
  5. import java.util.HashSet;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Map.Entry;
  9. import java.util.Set;
  10. import java.util.SortedSet;
  11. import java.util.TreeSet;
  12. import java.util.concurrent.atomic.AtomicInteger;

  13. import javax.xml.namespace.QName;
  14. import javax.xml.stream.XMLInputFactory;
  15. import javax.xml.stream.XMLStreamConstants;
  16. import javax.xml.stream.XMLStreamException;
  17. import javax.xml.stream.XMLStreamReader;

  18. import org.apache.commons.logging.Log;
  19. import org.apache.commons.logging.LogFactory;

  20. import mtas.analysis.token.MtasToken;
  21. import mtas.analysis.token.MtasTokenCollection;
  22. import mtas.analysis.token.MtasTokenIdFactory;
  23. import mtas.analysis.util.MtasConfigException;
  24. import mtas.analysis.util.MtasParserException;
  25. import mtas.analysis.util.MtasConfiguration;

  26. /**
  27.  * The Class MtasXMLParser.
  28.  */
  29. abstract class MtasXMLParser extends MtasBasicParser {

  30.   /** The Constant log. */
  31.   private static final Log log = LogFactory.getLog(MtasXMLParser.class);

  32.   /** The namespace URI. */
  33.   protected String namespaceURI = null;

  34.   /** The namespace URI  id. */
  35.   protected String namespaceURI_id = null;

  36.   /** The root tag. */
  37.   protected String rootTag = null;

  38.   /** The content tag. */
  39.   protected String contentTag = null;

  40.   /** The allow non content. */
  41.   protected boolean allowNonContent = false;

  42.   /** The relation key map. */
  43.   private Map<String, SortedSet<String>> relationKeyMap = new HashMap<>();

  44.   /** The q names. */
  45.   private Map<String, QName> qNames = new HashMap<>();

  46.   /** The relation types. */
  47.   private Map<QName, MtasParserType<MtasParserMapping<?>>> relationTypes = new HashMap<>();

  48.   /** The relation annotation types. */
  49.   private Map<QName, MtasParserType<MtasParserMapping<?>>> relationAnnotationTypes = new HashMap<>();

  50.   /** The ref types. */
  51.   private Map<QName, MtasParserType<MtasParserMapping<?>>> refTypes = new HashMap<>();

  52.   /** The group types. */
  53.   private Map<QName, MtasParserType<MtasParserMapping<?>>> groupTypes = new HashMap<>();

  54.   /** The group annotation types. */
  55.   private Map<QName, MtasParserType<MtasParserMapping<?>>> groupAnnotationTypes = new HashMap<>();

  56.   /** The word types. */
  57.   private Map<QName, MtasParserType<MtasParserMapping<?>>> wordTypes = new HashMap<>();

  58.   /** The word annotation types. */
  59.   private Map<QName, MtasParserType<MtasParserMapping<?>>> wordAnnotationTypes = new HashMap<>();

  60.   /** The variable types. */
  61.   private Map<QName, MtasParserType<MtasParserVariable>> variableTypes = new HashMap<>();

  62.   /** The Constant XML_VARIABLES. */
  63.   private static final String XML_VARIABLES = "variables";

  64.   /** The Constant XML_VARIABLE. */
  65.   private static final String XML_VARIABLE = "variable";

  66.   /** The Constant XML_VARIABLE_NAME. */
  67.   private static final String XML_VARIABLE_NAME = "name";

  68.   /** The Constant XML_VARIABLE_VALUE. */
  69.   private static final String XML_VARIABLE_VALUE = "value";

  70.   /** The Constant XML_REFERENCES. */
  71.   private static final String XML_REFERENCES = "references";

  72.   /** The Constant XML_REFERENCE. */
  73.   private static final String XML_REFERENCE = "reference";

  74.   /** The Constant XML_REFERENCE_NAME. */
  75.   private static final String XML_REFERENCE_NAME = "name";

  76.   /** The Constant XML_REFERENCE_REF. */
  77.   private static final String XML_REFERENCE_REF = "ref";

  78.   /** The Constant XML_MAPPINGS. */
  79.   private static final String XML_MAPPINGS = "mappings";

  80.   /** The Constant XML_MAPPING. */
  81.   private static final String XML_MAPPING = "mapping";

  82.   /** The Constant XML_MAPPING_TYPE. */
  83.   private static final String XML_MAPPING_TYPE = "type";

  84.   /** The Constant XML_MAPPING_NAME. */
  85.   private static final String XML_MAPPING_NAME = "name";

  86.   /**
  87.    * Instantiates a new mtas XML parser.
  88.    *
  89.    * @param config the config
  90.    */
  91.   public MtasXMLParser(MtasConfiguration config) {
  92.     super(config);
  93.     try {
  94.       initParser();
  95.       // System.out.print(printConfig());
  96.     } catch (MtasConfigException e) {
  97.       log.error(e);
  98.     }
  99.   }

  100.   /*
  101.    * (non-Javadoc)
  102.    *
  103.    * @see mtas.analysis.parser.MtasParser#printConfig()
  104.    */
  105.   @Override
  106.   public String printConfig() {
  107.     StringBuilder text = new StringBuilder();
  108.     text.append("=== CONFIGURATION ===\n");
  109.     text.append("type: " + variableTypes.size() + " x variable\n");
  110.     text.append(printConfigVariableTypes(variableTypes));
  111.     text.append("type: " + groupTypes.size() + " x group\n");
  112.     text.append(printConfigMappingTypes(groupTypes));
  113.     text.append("type: " + groupAnnotationTypes.size() + " x groupAnnotation");
  114.     text.append(printConfigMappingTypes(groupAnnotationTypes));
  115.     text.append("type: " + wordTypes.size() + " x word\n");
  116.     text.append(printConfigMappingTypes(wordTypes));
  117.     text.append("type: " + wordAnnotationTypes.size() + " x wordAnnotation");
  118.     text.append(printConfigMappingTypes(wordAnnotationTypes));
  119.     text.append("type: " + relationTypes.size() + " x relation\n");
  120.     text.append(printConfigMappingTypes(relationTypes));
  121.     text.append(
  122.         "type: " + relationAnnotationTypes.size() + " x relationAnnotation\n");
  123.     text.append(printConfigMappingTypes(relationAnnotationTypes));
  124.     text.append("type: " + refTypes.size() + " x references\n");
  125.     text.append(printConfigMappingTypes(refTypes));
  126.     text.append("=== CONFIGURATION ===\n");
  127.     return text.toString();
  128.   }

  129.   /**
  130.    * Prints the config mapping types.
  131.    *
  132.    * @param types the types
  133.    * @return the string
  134.    */
  135.   private String printConfigMappingTypes(
  136.       Map<QName, MtasParserType<MtasParserMapping<?>>> types) {
  137.     StringBuilder text = new StringBuilder();
  138.     for (Entry<QName, MtasParserType<MtasParserMapping<?>>> entry : types
  139.         .entrySet()) {
  140.       text.append("- " + entry.getKey().getLocalPart() + ": "
  141.           + entry.getValue().items.size() + " mapping(s)\n");
  142.       for (int i = 0; i < entry.getValue().items.size(); i++) {
  143.         text.append("\t" + entry.getValue().items.get(i) + "\n");
  144.       }
  145.     }
  146.     return text.toString();
  147.   }

  148.   /**
  149.    * Prints the config variable types.
  150.    *
  151.    * @param types the types
  152.    * @return the string
  153.    */
  154.   private String printConfigVariableTypes(
  155.       Map<QName, MtasParserType<MtasParserVariable>> types) {
  156.     StringBuilder text = new StringBuilder();
  157.     for (Entry<QName, MtasParserType<MtasParserVariable>> entry : types
  158.         .entrySet()) {
  159.       text.append("- " + entry.getKey().getLocalPart() + ": "
  160.           + entry.getValue().items.size() + " variables(s)\n");
  161.       for (int i = 0; i < entry.getValue().items.size(); i++) {
  162.         text.append("\t" + entry.getValue().items.get(i) + "\n");
  163.       }
  164.     }
  165.     return text.toString();
  166.   }

  167.   /*
  168.    * (non-Javadoc)
  169.    *
  170.    * @see mtas.analysis.parser.MtasParser#initParser()
  171.    */
  172.   @Override
  173.   protected void initParser() throws MtasConfigException {
  174.     super.initParser();
  175.     if (config != null) {
  176.       // find namespaceURI
  177.       for (int i = 0; i < config.children.size(); i++) {
  178.         MtasConfiguration current = config.children.get(i);
  179.         if (current.name.equals("namespaceURI")) {
  180.           namespaceURI = current.attributes.get("value");
  181.         }
  182.       }
  183.       // loop again
  184.       for (int i = 0; i < config.children.size(); i++) {
  185.         MtasConfiguration current = config.children.get(i);
  186.         if (current.name.equals(XML_VARIABLES)) {
  187.           for (int j = 0; j < current.children.size(); j++) {
  188.             if (current.children.get(j).name.equals(XML_VARIABLE)) {
  189.               MtasConfiguration variable = current.children.get(j);
  190.               String nameVariable = variable.attributes.get(XML_VARIABLE_NAME);
  191.               String valueVariable = variable.attributes
  192.                   .get(XML_VARIABLE_VALUE);
  193.               if ((nameVariable != null) && (valueVariable != null)) {
  194.                 MtasParserVariable v = new MtasParserVariable(nameVariable,
  195.                     valueVariable);
  196.                 v.processConfig(variable);
  197.                 QName qn = getQName(nameVariable);
  198.                 if (variableTypes.containsKey(qn)) {
  199.                   variableTypes.get(qn).addItem(v);
  200.                 } else {
  201.                   MtasParserType<MtasParserVariable> t = new MtasParserType<>(
  202.                       nameVariable, valueVariable, false);
  203.                   t.addItem(v);
  204.                   variableTypes.put(qn, t);
  205.                 }
  206.               }
  207.             }
  208.           }
  209.         } else if (current.name.equals(XML_REFERENCES)) {
  210.           for (int j = 0; j < current.children.size(); j++) {
  211.             if (current.children.get(j).name.equals(XML_REFERENCE)) {
  212.               MtasConfiguration reference = current.children.get(j);
  213.               String name = reference.attributes.get(XML_REFERENCE_NAME);
  214.               String ref = reference.attributes.get(XML_REFERENCE_REF);
  215.               if ((name != null) && (ref != null)) {
  216.                 MtasParserType<MtasParserMapping<?>> t = new MtasParserType<>(
  217.                     MAPPING_TYPE_REF, name, false, ref);
  218.                 refTypes.put(getQName(t.getName()), t);
  219.               }
  220.             }
  221.           }
  222.         } else if (current.name.equals(XML_MAPPINGS)) {
  223.           for (int j = 0; j < current.children.size(); j++) {
  224.             if (current.children.get(j).name.equals(XML_MAPPING)) {
  225.               MtasConfiguration mapping = current.children.get(j);
  226.               String typeMapping = mapping.attributes.get(XML_MAPPING_TYPE);
  227.               String nameMapping = mapping.attributes.get(XML_MAPPING_NAME);
  228.               if ((typeMapping != null) && (nameMapping != null)) {
  229.                 if (typeMapping.equals(MAPPING_TYPE_RELATION)) {
  230.                   MtasXMLParserMappingRelation m = new MtasXMLParserMappingRelation();
  231.                   m.processConfig(mapping);
  232.                   QName qn = getQName(nameMapping);
  233.                   if (relationTypes.containsKey(qn)) {
  234.                     relationTypes.get(qn).addItem(m);
  235.                   } else {
  236.                     MtasParserType<MtasParserMapping<?>> t = new MtasParserType<>(
  237.                         typeMapping, nameMapping, false);
  238.                     t.addItem(m);
  239.                     relationTypes.put(qn, t);
  240.                   }
  241.                 } else if (typeMapping
  242.                     .equals(MAPPING_TYPE_RELATION_ANNOTATION)) {
  243.                   MtasXMLParserMappingRelationAnnotation m = new MtasXMLParserMappingRelationAnnotation();
  244.                   m.processConfig(mapping);
  245.                   QName qn = getQName(nameMapping);
  246.                   if (relationAnnotationTypes.containsKey(qn)) {
  247.                     relationAnnotationTypes.get(qn).addItem(m);
  248.                   } else {
  249.                     MtasParserType<MtasParserMapping<?>> t = new MtasParserType<>(
  250.                         typeMapping, nameMapping, false);
  251.                     t.addItem(m);
  252.                     relationAnnotationTypes.put(qn, t);
  253.                   }
  254.                 } else if (typeMapping.equals(MAPPING_TYPE_WORD)) {
  255.                   MtasXMLParserMappingWord m = new MtasXMLParserMappingWord();
  256.                   m.processConfig(mapping);
  257.                   QName qn = getQName(nameMapping);
  258.                   if (wordTypes.containsKey(qn)) {
  259.                     wordTypes.get(qn).addItem(m);
  260.                   } else {
  261.                     MtasParserType<MtasParserMapping<?>> t = new MtasParserType<>(
  262.                         typeMapping, nameMapping, false);
  263.                     t.addItem(m);
  264.                     wordTypes.put(qn, t);
  265.                   }
  266.                 } else if (typeMapping.equals(MAPPING_TYPE_WORD_ANNOTATION)) {
  267.                   MtasXMLParserMappingWordAnnotation m = new MtasXMLParserMappingWordAnnotation();
  268.                   m.processConfig(mapping);
  269.                   QName qn = getQName(nameMapping);
  270.                   if (wordAnnotationTypes.containsKey(qn)) {
  271.                     wordAnnotationTypes.get(qn).addItem(m);
  272.                   } else {
  273.                     MtasParserType<MtasParserMapping<?>> t = new MtasParserType<>(
  274.                         typeMapping, nameMapping, false);
  275.                     t.addItem(m);
  276.                     wordAnnotationTypes.put(qn, t);
  277.                   }
  278.                 } else if (typeMapping.equals(MAPPING_TYPE_GROUP)) {
  279.                   MtasXMLParserMappingGroup m = new MtasXMLParserMappingGroup();
  280.                   m.processConfig(mapping);
  281.                   QName qn = getQName(nameMapping);
  282.                   if (groupTypes.containsKey(qn)) {
  283.                     groupTypes.get(qn).addItem(m);
  284.                   } else {
  285.                     MtasParserType<MtasParserMapping<?>> t = new MtasParserType<>(
  286.                         typeMapping, nameMapping, false);
  287.                     t.addItem(m);
  288.                     groupTypes.put(qn, t);
  289.                   }
  290.                 } else if (typeMapping.equals(MAPPING_TYPE_GROUP_ANNOTATION)) {
  291.                   MtasXMLParserMappingGroupAnnotation m = new MtasXMLParserMappingGroupAnnotation();
  292.                   m.processConfig(mapping);
  293.                   QName qn = getQName(nameMapping);
  294.                   if (groupAnnotationTypes.containsKey(qn)) {
  295.                     groupAnnotationTypes.get(qn).addItem(m);
  296.                   } else {
  297.                     MtasParserType<MtasParserMapping<?>> t = new MtasParserType<>(
  298.                         typeMapping, nameMapping, false);
  299.                     t.addItem(m);
  300.                     groupAnnotationTypes.put(qn, t);
  301.                   }
  302.                 } else {
  303.                   throw new MtasConfigException(
  304.                       "unknown mapping type " + typeMapping);
  305.                 }
  306.               }
  307.             }
  308.           }
  309.         }
  310.       }
  311.     }
  312.   }

  313.   /*
  314.    * (non-Javadoc)
  315.    *
  316.    * @see mtas.analysis.parser.MtasParser#createTokenCollection(java.io.Reader)
  317.    */
  318.   @Override
  319.   public MtasTokenCollection createTokenCollection(Reader reader)
  320.       throws MtasParserException, MtasConfigException {
  321.     Boolean hasRoot = rootTag == null ? true : false;
  322.     Boolean parsingContent = contentTag == null ? true : false;
  323.     String textContent = null;
  324.     Integer unknownAncestors = 0;
  325.     Integer lastOffset = 0;

  326.     AtomicInteger position = new AtomicInteger(0);
  327.     Map<String, Set<Integer>> idPositions = new HashMap<>();
  328.     Map<String, Integer[]> idOffsets = new HashMap<>();

  329.     Map<String, Map<Integer, Set<String>>> updateList = createUpdateList();
  330.     Map<String, List<MtasParserObject>> currentList = createCurrentList();
  331.     Map<String, Map<String, String>> variables = createVariables();

  332.     tokenCollection = new MtasTokenCollection();
  333.     MtasTokenIdFactory mtasTokenIdFactory = new MtasTokenIdFactory();
  334.     XMLInputFactory factory = XMLInputFactory.newInstance();
  335.     try {      
  336.       XMLStreamReader streamReader = factory.createXMLStreamReader(reader);
  337.       QName qname;
  338.       try {
  339.         int event = streamReader.getEventType();
  340.         MtasParserType<?> currentType;
  341.         MtasParserType<?> tmpCurrentType;
  342.         MtasParserType<?> tmpVariableType;
  343.         MtasParserObject currentObject = null;
  344.         MtasParserObject variableObject = null;
  345.         while (true) {
  346.           switch (event) {
  347.           case XMLStreamConstants.START_DOCUMENT:
  348.             log.debug("start of document");
  349.             String encodingScheme = streamReader.getCharacterEncodingScheme();
  350.             if (encodingScheme == null) {
  351.               //ignore for now
  352.               log.info("No encodingScheme found, assume utf-8");
  353.               //throw new MtasParserException("No encodingScheme found");              
  354.             } else if (!encodingScheme.equalsIgnoreCase("utf-8")) {
  355.               throw new MtasParserException(
  356.                   "XML not UTF-8 encoded but '" + encodingScheme + "'");
  357.             }
  358.             break;
  359.           case XMLStreamConstants.END_DOCUMENT:
  360.             log.debug("end of document");
  361.             break;
  362.           case XMLStreamConstants.SPACE:
  363.             // set offset (end of start-element)
  364.             lastOffset = streamReader.getLocation().getCharacterOffset();
  365.             break;
  366.           case XMLStreamConstants.START_ELEMENT:
  367.             // get data
  368.             qname = streamReader.getName();
  369.             // check for rootTag
  370.             if (!hasRoot) {
  371.               if (qname.equals(getQName(rootTag))) {
  372.                 hasRoot = true;
  373.               } else {
  374.                 throw new MtasParserException("No " + rootTag);
  375.               }
  376.               // parse content
  377.             } else {
  378.               if ((tmpVariableType = variableTypes.get(qname)) != null) {
  379.                 variableObject = new MtasParserObject(tmpVariableType);
  380.                 collectAttributes(variableObject, streamReader);
  381.                 computeVariablesFromObject(variableObject, currentList,
  382.                     variables);
  383.               }
  384.               if (parsingContent) {
  385.                 // check for relation : not within word, not within
  386.                 // groupAnnotation
  387.                 if ((currentList.get(MAPPING_TYPE_WORD).isEmpty())
  388.                     && (currentList.get(MAPPING_TYPE_GROUP_ANNOTATION)
  389.                         .isEmpty())
  390.                     && (tmpCurrentType = relationTypes.get(qname)) != null) {
  391.                   currentObject = new MtasParserObject(tmpCurrentType);
  392.                   collectAttributes(currentObject, streamReader);
  393.                   currentObject.setUnknownAncestorNumber(unknownAncestors);
  394.                   currentObject.setRealOffsetStart(lastOffset);
  395.                   if (!prevalidateObject(currentObject, currentList)) {
  396.                     unknownAncestors++;
  397.                   } else {
  398.                     currentType = tmpCurrentType;
  399.                     currentList.get(MAPPING_TYPE_RELATION).add(currentObject);
  400.                     unknownAncestors = 0;
  401.                   }
  402.                   // check for relation annotation: not within word, but within
  403.                   // relation
  404.                 } else if ((currentList.get(MAPPING_TYPE_WORD).isEmpty())
  405.                     && (!currentList.get(MAPPING_TYPE_RELATION).isEmpty())
  406.                     && (tmpCurrentType = relationAnnotationTypes
  407.                         .get(qname)) != null) {
  408.                   currentObject = new MtasParserObject(tmpCurrentType);
  409.                   collectAttributes(currentObject, streamReader);
  410.                   currentObject.setUnknownAncestorNumber(unknownAncestors);
  411.                   currentObject.setRealOffsetStart(lastOffset);
  412.                   if (!prevalidateObject(currentObject, currentList)) {
  413.                     unknownAncestors++;
  414.                   } else {
  415.                     currentType = tmpCurrentType;
  416.                     currentList.get(MAPPING_TYPE_RELATION_ANNOTATION)
  417.                         .add(currentObject);
  418.                     unknownAncestors = 0;
  419.                   }
  420.                   // check for group: not within word, not within relation, not
  421.                   // within groupAnnotation
  422.                 } else if ((currentList.get(MAPPING_TYPE_WORD).isEmpty())
  423.                     && (currentList.get(MAPPING_TYPE_RELATION).isEmpty())
  424.                     && (currentList.get(MAPPING_TYPE_GROUP_ANNOTATION)
  425.                         .isEmpty())
  426.                     && (tmpCurrentType = groupTypes.get(qname)) != null) {
  427.                   currentObject = new MtasParserObject(tmpCurrentType);
  428.                   collectAttributes(currentObject, streamReader);
  429.                   currentObject.setUnknownAncestorNumber(unknownAncestors);
  430.                   currentObject.setRealOffsetStart(lastOffset);
  431.                   if (!prevalidateObject(currentObject, currentList)) {
  432.                     unknownAncestors++;
  433.                   } else {
  434.                     currentType = tmpCurrentType;
  435.                     currentList.get(MAPPING_TYPE_GROUP).add(currentObject);
  436.                     unknownAncestors = 0;
  437.                   }
  438.                   // check for group annotation: not within word, not within
  439.                   // relation, but within group
  440.                 } else if ((currentList.get(MAPPING_TYPE_WORD).isEmpty())
  441.                     && (currentList.get(MAPPING_TYPE_RELATION).isEmpty())
  442.                     && (!currentList.get(MAPPING_TYPE_GROUP).isEmpty())
  443.                     && (tmpCurrentType = groupAnnotationTypes
  444.                         .get(qname)) != null) {
  445.                   currentObject = new MtasParserObject(tmpCurrentType);
  446.                   collectAttributes(currentObject, streamReader);
  447.                   currentObject.setUnknownAncestorNumber(unknownAncestors);
  448.                   currentObject.setRealOffsetStart(lastOffset);
  449.                   if (!prevalidateObject(currentObject, currentList)) {
  450.                     unknownAncestors++;
  451.                   } else {
  452.                     currentType = tmpCurrentType;
  453.                     currentList.get(MAPPING_TYPE_GROUP_ANNOTATION)
  454.                         .add(currentObject);
  455.                     unknownAncestors = 0;
  456.                   }
  457.                   // check for word: not within relation, not within
  458.                   // groupAnnotation, not within word, not within wordAnnotation
  459.                 } else if ((currentList.get(MAPPING_TYPE_RELATION).isEmpty())
  460.                     && (currentList.get(MAPPING_TYPE_GROUP_ANNOTATION)
  461.                         .isEmpty())
  462.                     && (currentList.get(MAPPING_TYPE_WORD).isEmpty())
  463.                     && (currentList.get(MAPPING_TYPE_WORD_ANNOTATION).isEmpty())
  464.                     && (tmpCurrentType = wordTypes.get(qname)) != null) {
  465.                   currentObject = new MtasParserObject(tmpCurrentType);
  466.                   collectAttributes(currentObject, streamReader);
  467.                   currentObject.setUnknownAncestorNumber(unknownAncestors);
  468.                   currentObject.setOffsetStart(lastOffset);
  469.                   currentObject.setRealOffsetStart(lastOffset);
  470.                   if (!prevalidateObject(currentObject, currentList)) {
  471.                     unknownAncestors++;
  472.                   } else {
  473.                     currentType = tmpCurrentType;
  474.                     currentObject.addPosition(position.getAndIncrement());
  475.                     currentList.get(MAPPING_TYPE_WORD).add(currentObject);
  476.                     unknownAncestors = 0;
  477.                   }
  478.                   // check for word annotation: not within relation, not within
  479.                   // groupAnnotation, but within word
  480.                 } else if ((currentList.get(MAPPING_TYPE_RELATION).isEmpty())
  481.                     && (currentList.get(MAPPING_TYPE_GROUP_ANNOTATION)
  482.                         .isEmpty())
  483.                     && (!currentList.get(MAPPING_TYPE_WORD).isEmpty())
  484.                     && (tmpCurrentType = wordAnnotationTypes
  485.                         .get(qname)) != null) {
  486.                   currentObject = new MtasParserObject(tmpCurrentType);
  487.                   collectAttributes(currentObject, streamReader);
  488.                   currentObject.addPositions(currentList.get(MAPPING_TYPE_WORD)
  489.                       .get((currentList.get(MAPPING_TYPE_WORD).size() - 1))
  490.                       .getPositions());
  491.                   currentObject.setUnknownAncestorNumber(unknownAncestors);
  492.                   currentObject.setRealOffsetStart(lastOffset);
  493.                   if (!prevalidateObject(currentObject, currentList)) {
  494.                     unknownAncestors++;
  495.                   } else {
  496.                     currentType = tmpCurrentType;
  497.                     currentList.get(MAPPING_TYPE_WORD_ANNOTATION)
  498.                         .add(currentObject);
  499.                     unknownAncestors = 0;
  500.                   }
  501.                   // check for references: within relation
  502.                 } else if (!currentList.get(MAPPING_TYPE_RELATION).isEmpty()
  503.                     && (tmpCurrentType = refTypes.get(qname)) != null) {
  504.                   currentObject = new MtasParserObject(tmpCurrentType);
  505.                   collectAttributes(currentObject, streamReader);
  506.                   currentObject.setUnknownAncestorNumber(unknownAncestors);
  507.                   currentObject.setRealOffsetStart(lastOffset);
  508.                   if (!prevalidateObject(currentObject, currentList)) {
  509.                     unknownAncestors++;
  510.                   } else {
  511.                     currentType = tmpCurrentType;
  512.                     currentList.get(MAPPING_TYPE_REF).add(currentObject);
  513.                     unknownAncestors = 0;
  514.                     // add reference to ancestor relations
  515.                     for (MtasParserObject currentRelation : currentList
  516.                         .get(MAPPING_TYPE_RELATION)) {
  517.                       currentRelation.addRefId(currentObject
  518.                           .getAttribute(currentType.getRefAttributeName()));
  519.                       // register mapping for relation (for recursive relations)
  520.                       SortedSet<String> keyMapList;
  521.                       if (currentRelation.getId() != null) {
  522.                         if (relationKeyMap
  523.                             .containsKey(currentRelation.getId())) {
  524.                           keyMapList = relationKeyMap
  525.                               .get(currentRelation.getId());
  526.                         } else {
  527.                           keyMapList = new TreeSet<>();
  528.                           relationKeyMap.put(currentRelation.getId(),
  529.                               keyMapList);
  530.                         }
  531.                         keyMapList.add(currentObject
  532.                             .getAttribute(currentType.getRefAttributeName()));
  533.                       }
  534.                     }
  535.                   }
  536.                 } else {
  537.                   unknownAncestors++;
  538.                 }
  539.                 // check for start content
  540.               } else if (qname.equals(getQName(contentTag))) {
  541.                 parsingContent = true;
  542.                 // unexpected
  543.               } else if (!allowNonContent) {
  544.                 throw new MtasParserException(
  545.                     "Unexpected " + qname.getLocalPart() + " in document");
  546.               }
  547.             }
  548.             // set offset (end of start-element)
  549.             lastOffset = streamReader.getLocation().getCharacterOffset();
  550.             break;
  551.           case XMLStreamConstants.END_ELEMENT:
  552.             // set offset (end of end-element)
  553.             lastOffset = streamReader.getLocation().getCharacterOffset();
  554.             // get data
  555.             qname = streamReader.getName();
  556.             // parse content
  557.             if (parsingContent) {
  558.               if (unknownAncestors > 0) {
  559.                 unknownAncestors--;
  560.                 // check for reference: because otherwise currentList should
  561.                 // contain no references
  562.               } else if (!currentList.get(MAPPING_TYPE_REF).isEmpty()) {
  563.                 if ((currentType = refTypes.get(qname)) != null) {
  564.                   currentObject = currentList.get(MAPPING_TYPE_REF)
  565.                       .remove(currentList.get(MAPPING_TYPE_REF).size() - 1);
  566.                   assert currentObject.getType()
  567.                       .equals(currentType) : "object expected to be "
  568.                           + currentObject.getType().getName() + ", not "
  569.                           + currentType.getName();
  570.                   assert unknownAncestors == 0 : "error in administration "
  571.                       + currentObject.getType().getName();
  572.                   // ignore text and realOffset: not relevant
  573.                   idPositions.put(currentObject.getId(),
  574.                       currentObject.getPositions());
  575.                   idOffsets.put(currentObject.getId(),
  576.                       currentObject.getOffset());
  577.                   currentObject.updateMappings(idPositions, idOffsets);
  578.                   unknownAncestors = currentObject.getUnknownAncestorNumber();
  579.                   computeMappingsFromObject(mtasTokenIdFactory, currentObject,
  580.                       currentList, updateList);
  581.                 } else {
  582.                   // this shouldn't happen
  583.                 }
  584.                 // check for wordAnnotation: because otherwise currentList
  585.                 // should contain no wordAnnotations
  586.               } else if (!currentList.get(MAPPING_TYPE_WORD_ANNOTATION)
  587.                   .isEmpty()) {
  588.                 if ((currentType = wordAnnotationTypes.get(qname)) != null) {
  589.                   currentObject = currentList.get(MAPPING_TYPE_WORD_ANNOTATION)
  590.                       .remove(
  591.                           currentList.get(MAPPING_TYPE_WORD_ANNOTATION).size()
  592.                               - 1);
  593.                   assert currentObject.getType()
  594.                       .equals(currentType) : "object expected to be "
  595.                           + currentObject.getType().getName() + ", not "
  596.                           + currentType.getName();
  597.                   assert unknownAncestors == 0 : "error in administration "
  598.                       + currentObject.getType().getName();
  599.                   currentObject.setRealOffsetEnd(lastOffset);
  600.                   idPositions.put(currentObject.getId(),
  601.                       currentObject.getPositions());
  602.                   idOffsets.put(currentObject.getId(),
  603.                       currentObject.getOffset());
  604.                   // offset always null, so update later with word (should be
  605.                   // possible)
  606.                   if ((currentObject.getId() != null)
  607.                       && (!currentList.get(MAPPING_TYPE_WORD).isEmpty())) {
  608.                     currentList.get(MAPPING_TYPE_WORD)
  609.                         .get((currentList.get(MAPPING_TYPE_WORD).size() - 1))
  610.                         .addUpdateableIdWithOffset(currentObject.getId());
  611.                   }
  612.                   currentObject.updateMappings(idPositions, idOffsets);
  613.                   unknownAncestors = currentObject.getUnknownAncestorNumber();
  614.                   computeMappingsFromObject(mtasTokenIdFactory, currentObject,
  615.                       currentList, updateList);
  616.                 } else {
  617.                   // this shouldn't happen
  618.                 }
  619.                 // check for word: because otherwise currentList should contain
  620.                 // no words
  621.               } else if (!currentList.get(MAPPING_TYPE_WORD).isEmpty()) {
  622.                 if ((currentType = wordTypes.get(qname)) != null) {
  623.                   currentObject = currentList.get(MAPPING_TYPE_WORD)
  624.                       .remove(currentList.get(MAPPING_TYPE_WORD).size() - 1);
  625.                   assert currentObject.getType()
  626.                       .equals(currentType) : "object expected to be "
  627.                           + currentObject.getType().getName() + ", not "
  628.                           + currentType.getName();
  629.                   assert unknownAncestors == 0 : "error in administration "
  630.                       + currentObject.getType().getName();
  631.                   currentObject.setOffsetEnd(lastOffset);
  632.                   currentObject.setRealOffsetEnd(lastOffset);
  633.                   // update ancestor groups with position and offset
  634.                   for (MtasParserObject currentGroup : currentList
  635.                       .get(MAPPING_TYPE_GROUP)) {
  636.                     currentGroup.addPositions(currentObject.getPositions());
  637.                     currentGroup.addOffsetStart(currentObject.getOffsetStart());
  638.                     currentGroup.addOffsetEnd(currentObject.getOffsetEnd());
  639.                   }
  640.                   idPositions.put(currentObject.getId(),
  641.                       currentObject.getPositions());
  642.                   idOffsets.put(currentObject.getId(),
  643.                       currentObject.getOffset());
  644.                   currentObject.updateMappings(idPositions, idOffsets);
  645.                   unknownAncestors = currentObject.getUnknownAncestorNumber();
  646.                   computeMappingsFromObject(mtasTokenIdFactory, currentObject,
  647.                       currentList, updateList);
  648.                 } else {
  649.                   // this shouldn't happen
  650.                 }
  651.                 // check for group annotation: because otherwise currentList
  652.                 // should contain no groupAnnotations
  653.               } else if (!currentList.get(MAPPING_TYPE_GROUP_ANNOTATION)
  654.                   .isEmpty()) {
  655.                 if ((currentType = groupAnnotationTypes.get(qname)) != null) {
  656.                   currentObject = currentList.get(MAPPING_TYPE_GROUP_ANNOTATION)
  657.                       .remove(
  658.                           currentList.get(MAPPING_TYPE_GROUP_ANNOTATION).size()
  659.                               - 1);
  660.                   assert currentObject.getType()
  661.                       .equals(currentType) : "object expected to be "
  662.                           + currentObject.getType().getName() + ", not "
  663.                           + currentType.getName();
  664.                   assert unknownAncestors == 0 : "error in administration "
  665.                       + currentObject.getType().getName();
  666.                   currentObject.setRealOffsetEnd(lastOffset);
  667.                   idPositions.put(currentObject.getId(),
  668.                       currentObject.getPositions());
  669.                   idOffsets.put(currentObject.getId(),
  670.                       currentObject.getOffset());
  671.                   currentObject.updateMappings(idPositions, idOffsets);
  672.                   unknownAncestors = currentObject.getUnknownAncestorNumber();
  673.                   computeMappingsFromObject(mtasTokenIdFactory, currentObject,
  674.                       currentList, updateList);
  675.                 } else {
  676.                   // this shouldn't happen
  677.                 }
  678.                 // check for relation annotation
  679.               } else if (!currentList.get(MAPPING_TYPE_RELATION_ANNOTATION)
  680.                   .isEmpty()) {
  681.                 if ((currentType = relationAnnotationTypes
  682.                     .get(qname)) != null) {
  683.                   currentObject = currentList
  684.                       .get(MAPPING_TYPE_RELATION_ANNOTATION).remove(currentList
  685.                           .get(MAPPING_TYPE_RELATION_ANNOTATION).size() - 1);
  686.                   assert currentObject.getType()
  687.                       .equals(currentType) : "object expected to be "
  688.                           + currentObject.getType().getName() + ", not "
  689.                           + currentType.getName();
  690.                   assert unknownAncestors == 0 : "error in administration "
  691.                       + currentObject.getType().getName();
  692.                   currentObject.setRealOffsetEnd(lastOffset);
  693.                   idPositions.put(currentObject.getId(),
  694.                       currentObject.getPositions());
  695.                   idOffsets.put(currentObject.getId(),
  696.                       currentObject.getOffset());
  697.                   currentObject.updateMappings(idPositions, idOffsets);
  698.                   unknownAncestors = currentObject.getUnknownAncestorNumber();
  699.                   computeMappingsFromObject(mtasTokenIdFactory, currentObject,
  700.                       currentList, updateList);
  701.                 } else {
  702.                   // this shouldn't happen
  703.                 }
  704.                 // check for relation
  705.               } else if (!currentList.get(MAPPING_TYPE_RELATION).isEmpty()) {
  706.                 if ((currentType = relationTypes.get(qname)) != null) {
  707.                   currentObject = currentList.get(MAPPING_TYPE_RELATION).remove(
  708.                       currentList.get(MAPPING_TYPE_RELATION).size() - 1);
  709.                   assert currentObject.getType()
  710.                       .equals(currentType) : "object expected to be "
  711.                           + currentObject.getType().getName() + ", not "
  712.                           + currentType.getName();
  713.                   assert unknownAncestors == 0 : "error in administration "
  714.                       + currentObject.getType().getName();
  715.                   // ignore text: should not occur
  716.                   currentObject.setRealOffsetEnd(lastOffset);
  717.                   idPositions.put(currentObject.getId(),
  718.                       currentObject.getPositions());
  719.                   idOffsets.put(currentObject.getId(),
  720.                       currentObject.getOffset());
  721.                   currentObject.updateMappings(idPositions, idOffsets);
  722.                   unknownAncestors = currentObject.getUnknownAncestorNumber();
  723.                   computeMappingsFromObject(mtasTokenIdFactory, currentObject,
  724.                       currentList, updateList);
  725.                 } else {
  726.                   // this shouldn't happen
  727.                 }
  728.                 // check for group
  729.               } else if (!currentList.get(MAPPING_TYPE_GROUP).isEmpty()) {
  730.                 if ((currentType = groupTypes.get(qname)) != null) {
  731.                   currentObject = currentList.get(MAPPING_TYPE_GROUP)
  732.                       .remove(currentList.get(MAPPING_TYPE_GROUP).size() - 1);
  733.                   assert currentObject.getType()
  734.                       .equals(currentType) : "object expected to be "
  735.                           + currentObject.getType().getName() + ", not "
  736.                           + currentType.getName();
  737.                   assert unknownAncestors == 0 : "error in administration "
  738.                       + currentObject.getType().getName();
  739.                   // ignore text: should not occur
  740.                   currentObject.setRealOffsetEnd(lastOffset);
  741.                   idPositions.put(currentObject.getId(),
  742.                       currentObject.getPositions());
  743.                   idOffsets.put(currentObject.getId(),
  744.                       currentObject.getOffset());
  745.                   currentObject.updateMappings(idPositions, idOffsets);
  746.                   unknownAncestors = currentObject.getUnknownAncestorNumber();
  747.                   computeMappingsFromObject(mtasTokenIdFactory, currentObject,
  748.                       currentList, updateList);
  749.                 } else {
  750.                   unknownAncestors--;
  751.                 }
  752.               } else if (qname.equals(getQName("text"))) {
  753.                 parsingContent = false;
  754.                 assert unknownAncestors == 0 : "error in administration unknownAncestors";
  755.                 assert currentList.get(MAPPING_TYPE_REF)
  756.                     .isEmpty() : "error in administration references";
  757.                 assert currentList.get(MAPPING_TYPE_GROUP)
  758.                     .isEmpty() : "error in administration groups";
  759.                 assert currentList.get(MAPPING_TYPE_GROUP_ANNOTATION)
  760.                     .isEmpty() : "error in administration groupAnnotations";
  761.                 assert currentList.get(MAPPING_TYPE_WORD)
  762.                     .isEmpty() : "error in administration words";
  763.                 assert currentList.get(MAPPING_TYPE_WORD_ANNOTATION)
  764.                     .isEmpty() : "error in administration wordAnnotations";
  765.                 assert currentList.get(MAPPING_TYPE_RELATION)
  766.                     .isEmpty() : "error in administration relations";
  767.                 assert currentList.get(MAPPING_TYPE_RELATION_ANNOTATION)
  768.                     .isEmpty() : "error in administration relationAnnotations";
  769.               }
  770.             }
  771.             // forget text
  772.             textContent = null;
  773.             break;
  774.           case XMLStreamConstants.CHARACTERS:
  775.             // set offset (end of start-element)
  776.             lastOffset = streamReader.getLocation().getCharacterOffset();
  777.             // check for text
  778.             if (streamReader.hasText()) {
  779.               textContent = streamReader.getText();
  780.             }
  781.             if (currentObject != null && unknownAncestors.equals(0)) {
  782.               currentObject.addText(textContent);
  783.             }
  784.             break;
  785.           default:
  786.             break;
  787.           }
  788.           if (!streamReader.hasNext()) {
  789.             break;
  790.           }
  791.           event = streamReader.next();
  792.         }
  793.       } finally {
  794.         streamReader.close();
  795.       }
  796.       // final checks
  797.       assert unknownAncestors == 0 : "error in administration unknownAncestors";
  798.       assert hasRoot : "no " + rootTag;
  799.     } catch (XMLStreamException e) {
  800.       log.debug(e);      
  801.       throw new MtasParserException("No valid XML: " + e.getMessage());
  802.     }

  803.     // update tokens with variable
  804.     for (Entry<Integer, Set<String>> updateItem : updateList
  805.         .get(UPDATE_TYPE_VARIABLE).entrySet()) {
  806.       MtasToken token = tokenCollection.get(updateItem.getKey());
  807.       String encodedPrefix = token.getPrefix();
  808.       String encodedPostfix = token.getPostfix();
  809.       token.setValue(decodeAndUpdateWithVariables(encodedPrefix, encodedPostfix,
  810.           variables));
  811.     }
  812.     // update tokens with offset
  813.     for (Entry<Integer, Set<String>> updateItem : updateList
  814.         .get(UPDATE_TYPE_OFFSET).entrySet()) {
  815.       Set<String> refIdList = new HashSet<>();
  816.       for (String refId : updateItem.getValue()) {
  817.         if (idPositions.containsKey(refId)) {
  818.           refIdList.add(refId);
  819.         }
  820.         if (relationKeyMap.containsKey(refId)) {
  821.           refIdList.addAll(recursiveCollect(refId, relationKeyMap, 10));
  822.         }
  823.       }
  824.       for (String refId : refIdList) {
  825.         Integer[] refOffset = idOffsets.get(refId);
  826.         Integer tokenId = updateItem.getKey();
  827.         if (tokenId != null && refOffset != null) {
  828.           MtasToken token = tokenCollection.get(tokenId);
  829.           token.addOffset(refOffset[0], refOffset[1]);
  830.         }
  831.       }
  832.     }
  833.     // update tokens with position
  834.     for (Entry<Integer, Set<String>> updateItem : updateList
  835.         .get(UPDATE_TYPE_POSITION).entrySet()) {
  836.       HashSet<String> refIdList = new HashSet<>();
  837.       for (String refId : updateItem.getValue()) {
  838.         if (idPositions.containsKey(refId)) {
  839.           refIdList.add(refId);
  840.         }
  841.         if (relationKeyMap.containsKey(refId)) {
  842.           refIdList.addAll(recursiveCollect(refId, relationKeyMap, 10));
  843.         }
  844.       }
  845.       for (String refId : refIdList) {
  846.         Set<Integer> refPositions = idPositions.get(refId);
  847.         Integer tokenId = updateItem.getKey();
  848.         if (tokenId != null && refPositions != null) {
  849.           MtasToken token = tokenCollection.get(tokenId);
  850.           token.addPositions(refPositions);
  851.         }
  852.       }
  853.     }
  854.     // final check
  855.     tokenCollection.check(autorepair, makeunique);
  856.     return tokenCollection;
  857.   }

  858.   /**
  859.    * Recursive collect.
  860.    *
  861.    * @param refId the ref id
  862.    * @param relationKeyMap the relation key map
  863.    * @param maxRecursion the max recursion
  864.    * @return the collection<? extends string>
  865.    */
  866.   private Collection<? extends String> recursiveCollect(String refId,
  867.       Map<String, SortedSet<String>> relationKeyMap, int maxRecursion) {
  868.     Set<String> list = new HashSet<>();
  869.     if (maxRecursion > 0 && relationKeyMap.containsKey(refId)) {
  870.       SortedSet<String> subList = relationKeyMap.get(refId);
  871.       for (String subRefId : subList) {
  872.         list.add(subRefId);
  873.         list.addAll(
  874.             recursiveCollect(subRefId, relationKeyMap, maxRecursion - 1));
  875.       }
  876.     }
  877.     return list;
  878.   }

  879.   /**
  880.    * Gets the q name.
  881.    *
  882.    * @param key the key
  883.    * @return the q name
  884.    */
  885.   private QName getQName(String key) {
  886.     QName qname;
  887.     if ((qname = qNames.get(key)) == null) {
  888.       qname = new QName(namespaceURI, key);
  889.       qNames.put(key, qname);
  890.     }
  891.     return qname;
  892.   }

  893.   /**
  894.    * Collect attributes.
  895.    *
  896.    * @param currentObject the current object
  897.    * @param streamReader the stream reader
  898.    */
  899.   public void collectAttributes(MtasParserObject currentObject,
  900.       XMLStreamReader streamReader) {
  901.     String attributeNamespaceURI;
  902.     currentObject.objectAttributes.clear();
  903.     currentObject.objectId = streamReader.getAttributeValue(namespaceURI_id,
  904.         "id");
  905.     for (int i = 0; i < streamReader.getAttributeCount(); i++) {
  906.       attributeNamespaceURI = streamReader.getAttributeNamespace(i);
  907.       if (attributeNamespaceURI == null || attributeNamespaceURI.equals("")) {
  908.         attributeNamespaceURI = streamReader.getNamespaceURI();
  909.       }
  910.       if (namespaceURI == null || attributeNamespaceURI.equals(namespaceURI)) {
  911.         currentObject.objectAttributes.put(
  912.             streamReader.getAttributeLocalName(i),
  913.             streamReader.getAttributeValue(i));
  914.       } else {
  915.         HashMap<String, String> otherMap;
  916.         if(!currentObject.objectOtherAttributes.containsKey(attributeNamespaceURI)) {
  917.            otherMap = new HashMap<>();          
  918.           currentObject.objectOtherAttributes.put(attributeNamespaceURI, otherMap);
  919.         } else {
  920.           otherMap = currentObject.objectOtherAttributes.get(attributeNamespaceURI);
  921.         }
  922.         otherMap.put(
  923.             streamReader.getAttributeLocalName(i),
  924.             streamReader.getAttributeValue(i));
  925.       }
  926.     }
  927.   }

  928.   /**
  929.    * The Class MtasXMLParserMappingRelation.
  930.    */
  931.   private class MtasXMLParserMappingRelation
  932.       extends MtasParserMapping<MtasXMLParserMappingRelation> {

  933.     /**
  934.      * Instantiates a new mtas XML parser mapping relation.
  935.      */
  936.     public MtasXMLParserMappingRelation() {
  937.       super();
  938.       this.position = SOURCE_REFS;
  939.       this.realOffset = SOURCE_OWN;
  940.       this.offset = SOURCE_REFS;
  941.       this.type = MAPPING_TYPE_RELATION;
  942.     }

  943.     /*
  944.      * (non-Javadoc)
  945.      *
  946.      * @see mtas.analysis.parser.MtasBasicParser.MtasParserMapping#self()
  947.      */
  948.     @Override
  949.     protected MtasXMLParserMappingRelation self() {
  950.       return this;
  951.     }
  952.   }

  953.   /**
  954.    * The Class MtasXMLParserMappingRelationAnnotation.
  955.    */
  956.   private class MtasXMLParserMappingRelationAnnotation
  957.       extends MtasParserMapping<MtasXMLParserMappingRelationAnnotation> {

  958.     /**
  959.      * Instantiates a new mtas XML parser mapping relation annotation.
  960.      */
  961.     public MtasXMLParserMappingRelationAnnotation() {
  962.       super();
  963.       this.position = SOURCE_ANCESTOR_RELATION;
  964.       this.realOffset = SOURCE_OWN;
  965.       this.offset = SOURCE_ANCESTOR_RELATION;
  966.       this.type = MAPPING_TYPE_RELATION_ANNOTATION;
  967.     }

  968.     /*
  969.      * (non-Javadoc)
  970.      *
  971.      * @see mtas.analysis.parser.MtasBasicParser.MtasParserMapping#self()
  972.      */
  973.     @Override
  974.     protected MtasXMLParserMappingRelationAnnotation self() {
  975.       return this;
  976.     }

  977.   }

  978.   /**
  979.    * The Class MtasXMLParserMappingGroup.
  980.    */
  981.   private class MtasXMLParserMappingGroup
  982.       extends MtasParserMapping<MtasXMLParserMappingGroup> {

  983.     /**
  984.      * Instantiates a new mtas XML parser mapping group.
  985.      */
  986.     public MtasXMLParserMappingGroup() {
  987.       super();
  988.       this.position = SOURCE_OWN;
  989.       this.realOffset = SOURCE_OWN;
  990.       this.offset = SOURCE_OWN;
  991.       this.type = MAPPING_TYPE_GROUP;
  992.     }

  993.     /*
  994.      * (non-Javadoc)
  995.      *
  996.      * @see mtas.analysis.parser.MtasBasicParser.MtasParserMapping#self()
  997.      */
  998.     @Override
  999.     protected MtasXMLParserMappingGroup self() {
  1000.       return this;
  1001.     }
  1002.   }

  1003.   /**
  1004.    * The Class MtasXMLParserMappingGroupAnnotation.
  1005.    */
  1006.   private class MtasXMLParserMappingGroupAnnotation
  1007.       extends MtasParserMapping<MtasXMLParserMappingGroupAnnotation> {

  1008.     /**
  1009.      * Instantiates a new mtas XML parser mapping group annotation.
  1010.      */
  1011.     public MtasXMLParserMappingGroupAnnotation() {
  1012.       super();
  1013.       this.position = SOURCE_ANCESTOR_GROUP;
  1014.       this.realOffset = SOURCE_OWN;
  1015.       this.offset = SOURCE_ANCESTOR_GROUP;
  1016.       this.type = MAPPING_TYPE_GROUP_ANNOTATION;
  1017.     }

  1018.     /*
  1019.      * (non-Javadoc)
  1020.      *
  1021.      * @see mtas.analysis.parser.MtasBasicParser.MtasParserMapping#self()
  1022.      */
  1023.     @Override
  1024.     protected MtasXMLParserMappingGroupAnnotation self() {
  1025.       return this;
  1026.     }

  1027.     /*
  1028.      * (non-Javadoc)
  1029.      *
  1030.      * @see
  1031.      * mtas.analysis.parser.MtasBasicParser.MtasParserMapping#setStartEnd(java.
  1032.      * lang.String, java.lang.String)
  1033.      */
  1034.     @Override
  1035.     protected void setStartEnd(String start, String end) {
  1036.       super.setStartEnd(start, end);
  1037.       if (start != null && end != null) {
  1038.         position = SOURCE_REFS;
  1039.         offset = SOURCE_REFS;
  1040.       }
  1041.     }

  1042.   }

  1043.   /**
  1044.    * The Class MtasXMLParserMappingWord.
  1045.    */
  1046.   private class MtasXMLParserMappingWord
  1047.       extends MtasParserMapping<MtasXMLParserMappingWord> {

  1048.     /**
  1049.      * Instantiates a new mtas XML parser mapping word.
  1050.      */
  1051.     public MtasXMLParserMappingWord() {
  1052.       super();
  1053.       this.position = SOURCE_OWN;
  1054.       this.realOffset = SOURCE_OWN;
  1055.       this.offset = SOURCE_OWN;
  1056.       this.type = MAPPING_TYPE_WORD;
  1057.     }

  1058.     /*
  1059.      * (non-Javadoc)
  1060.      *
  1061.      * @see mtas.analysis.parser.MtasBasicParser.MtasParserMapping#self()
  1062.      */
  1063.     @Override
  1064.     protected MtasXMLParserMappingWord self() {
  1065.       return this;
  1066.     }
  1067.   }

  1068.   /**
  1069.    * The Class MtasXMLParserMappingWordAnnotation.
  1070.    */
  1071.   private class MtasXMLParserMappingWordAnnotation
  1072.       extends MtasParserMapping<MtasXMLParserMappingWordAnnotation> {

  1073.     /**
  1074.      * Instantiates a new mtas XML parser mapping word annotation.
  1075.      */
  1076.     public MtasXMLParserMappingWordAnnotation() {
  1077.       super();
  1078.       this.position = SOURCE_OWN;
  1079.       this.realOffset = SOURCE_OWN;
  1080.       this.offset = SOURCE_ANCESTOR_WORD;
  1081.       this.type = MAPPING_TYPE_WORD_ANNOTATION;
  1082.     }

  1083.     /*
  1084.      * (non-Javadoc)
  1085.      *
  1086.      * @see mtas.analysis.parser.MtasBasicParser.MtasParserMapping#self()
  1087.      */
  1088.     @Override
  1089.     protected MtasXMLParserMappingWordAnnotation self() {
  1090.       return this;
  1091.     }
  1092.   }

  1093. }