MtasTokenCollection.java

  1. package mtas.analysis.token;

  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.Collections;
  5. import java.util.Comparator;
  6. import java.util.HashMap;
  7. import java.util.Iterator;
  8. import java.util.Map;
  9. import java.util.Map.Entry;

  10. import org.apache.lucene.analysis.payloads.PayloadHelper;
  11. import org.apache.lucene.util.BytesRef;

  12. import mtas.analysis.util.MtasParserException;

  13. /**
  14.  * The Class MtasTokenCollection.
  15.  */
  16. public class MtasTokenCollection {

  17.   /** The token collection. */
  18.   private HashMap<Integer, MtasToken> tokenCollection = new HashMap<>();

  19.   /** The token collection index. */
  20.   private ArrayList<Integer> tokenCollectionIndex = new ArrayList<>();

  21.   /**
  22.    * Instantiates a new mtas token collection.
  23.    */
  24.   public MtasTokenCollection() {
  25.     clear();
  26.   }

  27.   /**
  28.    * Adds the.
  29.    *
  30.    * @param token the token
  31.    * @return the integer
  32.    */
  33.   public Integer add(MtasToken token) {
  34.     Integer id = token.getId();
  35.     tokenCollection.put(id, token);
  36.     return id;
  37.   }

  38.   /**
  39.    * Gets the.
  40.    *
  41.    * @param id the id
  42.    * @return the mtas token
  43.    */
  44.   public MtasToken get(Integer id) {
  45.     return tokenCollection.get(id);
  46.   }

  47.   /**
  48.    * Iterator.
  49.    *
  50.    * @return the iterator
  51.    * @throws MtasParserException the mtas parser exception
  52.    */
  53.   public Iterator<MtasToken> iterator() throws MtasParserException {
  54.     checkTokenCollectionIndex();
  55.     return new Iterator<MtasToken>() {

  56.       private Iterator<Integer> indexIterator = tokenCollectionIndex.iterator();

  57.       @Override
  58.       public boolean hasNext() {
  59.         return indexIterator.hasNext();
  60.       }

  61.       @Override
  62.       public MtasToken next() {
  63.         return tokenCollection.get(indexIterator.next());
  64.       }

  65.       @Override
  66.       public void remove() {
  67.         throw new UnsupportedOperationException();
  68.       }
  69.     };
  70.   }

  71.   /**
  72.    * Prints the.
  73.    *
  74.    * @throws MtasParserException the mtas parser exception
  75.    */
  76.   public void print() throws MtasParserException {
  77.     Iterator<MtasToken> it = this.iterator();
  78.     while (it.hasNext()) {
  79.       MtasToken token = it.next();
  80.       System.out.println(token);
  81.     }
  82.   }

  83.   /**
  84.    * Gets the list.
  85.    *
  86.    * @return the list
  87.    * @throws MtasParserException the mtas parser exception
  88.    */
  89.   public String[][] getList() throws MtasParserException {
  90.     String[][] result = new String[(tokenCollection.size() + 1)][];
  91.     result[0] = new String[] { "id", "start real offset", "end real offset",
  92.         "provide real offset", "start offset", "end offset", "provide offset",
  93.         "start position", "end position", "multiple positions", "parent",
  94.         "provide parent", "payload", "prefix", "postfix" };
  95.     int number = 1;
  96.     Iterator<MtasToken> it = this.iterator();
  97.     while (it.hasNext()) {
  98.       MtasToken token = it.next();
  99.       String[] row = new String[15];
  100.       row[0] = token.getId().toString();
  101.       if (token.getRealOffsetStart() != null) {
  102.         row[1] = token.getRealOffsetStart().toString();
  103.         row[2] = token.getRealOffsetEnd().toString();
  104.         row[3] = token.getProvideRealOffset() ? "1" : null;
  105.       }
  106.       if (token.getOffsetStart() != null) {
  107.         row[4] = token.getOffsetStart().toString();
  108.         row[5] = token.getOffsetEnd().toString();
  109.         row[6] = token.getProvideOffset() ? "1" : null;
  110.       }
  111.       if (token.getPositionLength() != null) {
  112.         if (token.getPositionStart().equals(token.getPositionEnd())) {
  113.           row[7] = token.getPositionStart().toString();
  114.           row[8] = token.getPositionEnd().toString();
  115.           row[9] = null;
  116.         } else if ((token.getPositions() == null)
  117.             || (token.getPositions().length == (1 + token.getPositionEnd()
  118.                 - token.getPositionStart()))) {
  119.           row[7] = token.getPositionStart().toString();
  120.           row[8] = token.getPositionEnd().toString();
  121.           row[9] = null;
  122.         } else {
  123.           row[7] = null;
  124.           row[8] = null;
  125.           row[9] = Arrays.toString(token.getPositions());
  126.         }
  127.       }
  128.       if (token.getParentId() != null) {
  129.         row[10] = token.getParentId().toString();
  130.         row[11] = token.getProvideParentId() ? "1" : null;
  131.       }
  132.       if (token.getPayload() != null) {
  133.         BytesRef payload = token.getPayload();
  134.         row[12] = Float.toString(PayloadHelper.decodeFloat(Arrays.copyOfRange(
  135.             payload.bytes, payload.offset, (payload.offset + payload.length))));
  136.       }
  137.       row[13] = token.getPrefix();
  138.       row[14] = token.getPostfix();
  139.       result[number] = row;
  140.       number++;
  141.     }
  142.     return result;
  143.   }

  144.   /**
  145.    * Check.
  146.    *
  147.    * @param autoRepair the auto repair
  148.    * @param makeUnique the make unique
  149.    * @throws MtasParserException the mtas parser exception
  150.    */
  151.   public void check(Boolean autoRepair, Boolean makeUnique)
  152.       throws MtasParserException {
  153.     if (autoRepair) {
  154.       autoRepair();
  155.     }
  156.     if (makeUnique) {
  157.       makeUnique();
  158.     }
  159.     checkTokenCollectionIndex();
  160.     for (Integer i : tokenCollectionIndex) {
  161.       // minimal properties
  162.       if (tokenCollection.get(i).getId() == null
  163.           || tokenCollection.get(i).getPositionStart() == null
  164.           || tokenCollection.get(i).getPositionEnd() == null
  165.           || tokenCollection.get(i).getValue() == null) {
  166.         clear();
  167.         break;
  168.       }
  169.     }
  170.   }

  171.   /**
  172.    * Make unique.
  173.    */
  174.   private void makeUnique() {
  175.     HashMap<String, ArrayList<MtasToken>> currentPositionTokens = new HashMap<>();
  176.     ArrayList<MtasToken> currentValueTokens;
  177.     int currentStartPosition = -1;
  178.     MtasToken currentToken = null;
  179.     for (Entry<Integer, MtasToken> entry : tokenCollection.entrySet()) {
  180.       currentToken = entry.getValue();
  181.       if (currentToken.getPositionStart() > currentStartPosition) {
  182.         currentPositionTokens.clear();
  183.         currentStartPosition = currentToken.getPositionStart();
  184.       } else {
  185.         if (currentPositionTokens.containsKey(currentToken.getValue())) {
  186.           currentValueTokens = currentPositionTokens
  187.               .get(currentToken.getValue());

  188.         } else {
  189.           currentValueTokens = new ArrayList<>();
  190.           currentPositionTokens.put(currentToken.getValue(),
  191.               currentValueTokens);
  192.         }
  193.         currentValueTokens.add(currentToken);
  194.       }
  195.     }
  196.   }

  197.   /**
  198.    * Auto repair.
  199.    */
  200.   private void autoRepair() {
  201.     ArrayList<Integer> trash = new ArrayList<>();
  202.     HashMap<Integer, Integer> translation = new HashMap<>();
  203.     HashMap<Integer, MtasToken> newTokenCollection = new HashMap<>();
  204.     Integer parentId;
  205.     Integer maxId = null;
  206.     Integer minId = null;
  207.     MtasToken token;
  208.     // check id, position and value
  209.     for (Entry<Integer, MtasToken> entry : tokenCollection.entrySet()) {
  210.       token = entry.getValue();
  211.       boolean putInTrash;
  212.       putInTrash = token.getId() == null;
  213.       putInTrash |= (token.getPositionStart() == null)
  214.           || (token.getPositionEnd() == null);
  215.       putInTrash |= token.getValue() == null || (token.getValue().isEmpty());
  216.       putInTrash |= token.getPrefix() == null || (token.getPrefix().isEmpty());
  217.       if (putInTrash) {
  218.         trash.add(entry.getKey());
  219.       }
  220.     }
  221.     // check parentId
  222.     for (Entry<Integer, MtasToken> entry : tokenCollection.entrySet()) {
  223.       token = entry.getValue();
  224.       parentId = token.getParentId();
  225.       if (parentId != null && (!tokenCollection.containsKey(parentId)
  226.           || trash.contains(parentId))) {
  227.         token.setParentId(null);
  228.       }
  229.     }
  230.     // empty bin
  231.     if (!trash.isEmpty()) {
  232.       for (Integer i : trash) {
  233.         tokenCollection.remove(i);
  234.       }
  235.     }
  236.     // always check ids
  237.     if (tokenCollection.size() > 0) {
  238.       for (Integer i : tokenCollection.keySet()) {
  239.         maxId = ((maxId == null) ? i : Math.max(maxId, i));
  240.         minId = ((minId == null) ? i : Math.min(minId, i));
  241.       }
  242.       // check
  243.       if ((minId > 0) || ((1 + maxId - minId) != tokenCollection.size())) {
  244.         int newId = 0;
  245.         // create translation
  246.         for (Integer i : tokenCollection.keySet()) {
  247.           translation.put(i, newId);
  248.           newId++;
  249.         }
  250.         // translate objects
  251.         for (Entry<Integer, MtasToken> entry : tokenCollection.entrySet()) {
  252.           token = entry.getValue();
  253.           parentId = token.getParentId();
  254.           token.setId(translation.get(entry.getKey()));
  255.           if (parentId != null) {
  256.             token.setParentId(translation.get(parentId));
  257.           }
  258.         }
  259.         // new tokenCollection
  260.         Iterator<Map.Entry<Integer, MtasToken>> iter = tokenCollection
  261.             .entrySet().iterator();
  262.         while (iter.hasNext()) {
  263.           Map.Entry<Integer, MtasToken> entry = iter.next();
  264.           newTokenCollection.put(translation.get(entry.getKey()),
  265.               entry.getValue());
  266.           iter.remove();
  267.         }
  268.         tokenCollection = newTokenCollection;
  269.       }
  270.     }
  271.   }

  272.   /**
  273.    * Check token collection index.
  274.    *
  275.    * @throws MtasParserException the mtas parser exception
  276.    */
  277.   private void checkTokenCollectionIndex() throws MtasParserException {
  278.     if (tokenCollectionIndex.size() != tokenCollection.size()) {
  279.       MtasToken token;
  280.       Integer maxId = null;
  281.       Integer minId = null;
  282.       tokenCollectionIndex.clear();
  283.       for (Entry<Integer, MtasToken> entry : tokenCollection.entrySet()) {
  284.         token = entry.getValue();
  285.         maxId = ((maxId == null) ? entry.getKey()
  286.             : Math.max(maxId, entry.getKey()));
  287.         minId = ((minId == null) ? entry.getKey()
  288.             : Math.min(minId, entry.getKey()));
  289.         if (token.getId() == null) {
  290.           throw new MtasParserException(
  291.               "no id for token (" + token.getValue() + ")");
  292.         } else if ((token.getPositionStart() == null)
  293.             || (token.getPositionEnd() == null)) {
  294.           throw new MtasParserException("no position for token with id "
  295.               + token.getId() + " (" + token.getValue() + ")");
  296.         } else if (token.getValue() == null || (token.getValue().equals(""))) {
  297.           throw new MtasParserException(
  298.               "no value for token with id " + token.getId());
  299.         } else if (token.getPrefix() == null
  300.             || (token.getPrefix().equals(""))) {
  301.           throw new MtasParserException(
  302.               "no prefix for token with id " + token.getId());
  303.         } else if ((token.getParentId() != null)
  304.             && !tokenCollection.containsKey(token.getParentId())) {
  305.           throw new MtasParserException(
  306.               "missing parentId for token with id " + token.getId());
  307.         } else if ((token.getOffsetStart() == null)
  308.             || (token.getOffsetEnd() == null)) {
  309.           throw new MtasParserException("missing offset for token with id "
  310.               + token.getId() + " (" + token.getValue() + ")");
  311.         }
  312.         tokenCollectionIndex.add(entry.getKey());
  313.       }
  314.       if ((tokenCollection.size() > 0)
  315.           && ((minId > 0) || ((1 + maxId - minId) != tokenCollection.size()))) {
  316.         throw new MtasParserException("missing ids");
  317.       }
  318.       Collections.sort(tokenCollectionIndex, getCompByName());
  319.     }
  320.   }

  321.   /**
  322.    * Gets the comp by name.
  323.    *
  324.    * @return the comp by name
  325.    */
  326.   public Comparator<Integer> getCompByName() {
  327.     return new Comparator<Integer>() {
  328.       @Override
  329.       public int compare(Integer t1, Integer t2) {
  330.         Integer p1 = tokenCollection.get(t1).getPositionStart();
  331.         Integer p2 = tokenCollection.get(t2).getPositionStart();
  332.         assert p1 != null : "no position for " + tokenCollection.get(t1);
  333.         assert p2 != null : "no position for " + tokenCollection.get(t2);
  334.         if (p1.equals(p2)) {
  335.           Integer o1 = tokenCollection.get(t1).getOffsetStart();
  336.           Integer o2 = tokenCollection.get(t2).getOffsetStart();
  337.           if (o1 != null && o2 != null) {
  338.             if (o1.equals(o2)) {
  339.               return tokenCollection.get(t1).getValue()
  340.                   .compareTo(tokenCollection.get(t2).getValue());
  341.             } else {
  342.               return o1.compareTo(o2);
  343.             }
  344.           } else {
  345.             return tokenCollection.get(t1).getValue()
  346.                 .compareTo(tokenCollection.get(t2).getValue());
  347.           }
  348.         }
  349.         return p1.compareTo(p2);
  350.       }
  351.     };
  352.   }

  353.   /**
  354.    * Clear.
  355.    */
  356.   private void clear() {
  357.     tokenCollectionIndex.clear();
  358.     tokenCollection.clear();
  359.   }

  360. }