@Override
        public List<Constituent> transform(Constituent input) {

          List<Constituent> c = new ArrayList<>();
          for (Relation r : input.getOutgoingRelations()) {
            c.add(addPointerToSource(input, r.getTarget()));
          }
          return c;
        }
  private static void writeView(View view, JsonObject json) {
    writeString("viewType", view.getClass().getCanonicalName(), json);

    writeString("viewName", view.getViewName(), json);

    writeString("generator", view.getViewGenerator(), json);

    if (view.getScore() != 0) writeDouble("score", view.getScore(), json);

    List<Constituent> constituents = view.getConstituents();

    if (constituents.size() > 0) {
      JsonArray cJson = new JsonArray();
      for (int i = 0; i < view.getNumberOfConstituents(); i++) {

        Constituent constituent = constituents.get(i);
        JsonObject c = new JsonObject();
        writeConstituent(constituent, c);

        cJson.add(c);
      }

      json.add("constituents", cJson);
    }

    List<Relation> relations = view.getRelations();

    if (relations.size() > 0) {

      JsonArray rJson = new JsonArray();

      for (Relation r : relations) {
        Constituent src = r.getSource();
        Constituent tgt = r.getTarget();

        int srcId = constituents.indexOf(src);
        int tgtId = constituents.indexOf(tgt);

        JsonObject rJ = new JsonObject();

        writeString("relationName", r.getRelationName(), rJ);

        if (r.getScore() != 0) writeDouble("score", r.getScore(), rJ);
        writeInt("srcConstituent", srcId, rJ);
        writeInt("targetConstituent", tgtId, rJ);
        writeAttributes(r, rJ);

        Map<String, Double> labelsToScores = r.getLabelsToScores();

        if (null != labelsToScores) writeLabelsToScores(labelsToScores, rJ);

        rJson.add(rJ);
      }

      json.add("relations", rJson);
    }
  }
  private static List<Constituent> getModifiers(Constituent input, TreeView dependency) {
    List<Constituent> constituentsCovering = dependency.getConstituentsCovering(input);

    if (constituentsCovering.size() == 0) return new ArrayList<>();

    Constituent c = constituentsCovering.get(0);

    List<Relation> outgoingRelations = c.getOutgoingRelations();

    if (outgoingRelations == null || outgoingRelations.size() == 0) return new ArrayList<>();
    else {

      for (Relation r : outgoingRelations) {
        if (r.getRelationName().contains("mod"))
          return Collections.singletonList(addPointerToSource(input, r.getTarget()));
      }

      return Collections.singletonList(
          addPointerToSource(input, outgoingRelations.get(0).getTarget()));
    }
  }
        @Override
        public List<Constituent> transform(Constituent c) {
          TextAnnotation ta = c.getTextAnnotation();
          int tokenPosition = c.getStartSpan();
          TreeView dependency = (TreeView) ta.getView(ViewNames.DEPENDENCY);

          Constituent prepositionDepConstituent =
              dependency.getConstituentsCoveringToken(tokenPosition).get(0);

          List<Relation> incomingRelations = prepositionDepConstituent.getIncomingRelations();

          List<Constituent> list = new ArrayList<>();
          if (incomingRelations != null && incomingRelations.size() > 0) {

            Constituent parent = incomingRelations.get(0).getSource();

            for (Relation out : parent.getOutgoingRelations()) {
              if (out == incomingRelations.get(0)) continue;

              String label = out.getRelationName();

              if (label.contains("prep")) {
                Constituent ppNode = out.getTarget();

                list.add(addPointerToSource(c, ppNode));

                // get the first child of the pp and add this
                List<Relation> ppOut = ppNode.getOutgoingRelations();

                if (ppOut != null && ppOut.size() != 0) {

                  Constituent child = ppOut.get(0).getTarget();
                  list.add(addPointerToSource(c, child));
                }
              }
            }
          }

          return list;
        }
 public List<Constituent> getConnectedNPs(Problem prob) {
   List<Constituent> npList = new ArrayList<>();
   List<Constituent> npListQuantRemoved = new ArrayList<>();
   boolean onlyQuantityInSentence = true;
   int sentId = prob.ta.getSentenceFromToken(quantPhrase.getStartSpan()).getSentenceId();
   for (QuantSpan qs : prob.quantities) {
     int tokenId = prob.ta.getTokenIdFromCharacterOffset(qs.start);
     if (prob.ta.getSentenceFromToken(tokenId).getSentenceId() == sentId
         && !(quantPhrase.getStartSpan() <= tokenId && quantPhrase.getEndSpan() > tokenId)) {
       onlyQuantityInSentence = false;
       break;
     }
   }
   // Find NPs from children of verb
   if (verbPhrase != null) {
     List<Relation> relations = verbPhrase.getOutgoingRelations();
     for (Relation relation : relations) {
       if (!relation.getRelationName().equals("nsubj")) continue;
       Constituent dst = relation.getTarget();
       for (Constituent cons : prob.chunks) {
         if (cons.getStartSpan() <= dst.getStartSpan()
             && cons.getEndSpan() > dst.getStartSpan()
             && cons.getLabel().equals("NP")
             && !npList.contains(cons)) {
           npList.add(cons);
           subject = cons;
           break;
         }
       }
     }
   }
   // Find NPs from PP NP connection
   int quantPhraseId = getChunkIndex(prob, quantPhrase.getStartSpan());
   if (quantPhraseId + 2 < prob.chunks.size()
       && !prob.chunks.get(quantPhraseId + 1).getSurfaceForm().trim().equals("of")
       && prob.chunks.get(quantPhraseId + 1).getLabel().equals("PP")
       && prob.chunks.get(quantPhraseId + 2).getLabel().equals("NP")
       && !npList.contains(prob.chunks.get(quantPhraseId + 2))) {
     npList.add(prob.chunks.get(quantPhraseId + 2));
   }
   if (quantPhraseId - 2 >= 0
       && prob.chunks.get(quantPhraseId - 1).getLabel().equals("PP")
       && prob.chunks.get(quantPhraseId - 2).getLabel().equals("NP")
       && !npList.contains(prob.chunks.get(quantPhraseId - 2))) {
     npList.add(prob.chunks.get(quantPhraseId - 2));
   }
   // Get preceding NP
   if (quantPhraseId - 1 >= 0
       && prob.chunks.get(quantPhraseId - 1).getLabel().equals("NP")
       && !prob.posTags
           .get(prob.chunks.get(quantPhraseId - 1).getEndSpan())
           .getLabel()
           .equals("CC")
       && !npList.contains(prob.chunks.get(quantPhraseId - 1))) {
     npList.add(prob.chunks.get(quantPhraseId - 1));
   }
   // Get succeeding NP
   if (quantPhraseId + 1 < prob.chunks.size()
       && prob.chunks.get(quantPhraseId + 1).getLabel().equals("NP")
       && !prob.posTags.get(prob.chunks.get(quantPhraseId).getEndSpan()).getLabel().equals("CC")
       && !npList.contains(prob.chunks.get(quantPhraseId + 1))) {
     npList.add(prob.chunks.get(quantPhraseId + 1));
   }
   //		 If only quantity in sentence, all NPs are connected
   if (onlyQuantityInSentence) {
     for (int i = 0; i < prob.chunks.size(); ++i) {
       Constituent cons = prob.chunks.get(i);
       if (cons.getSentenceId() == sentId
           && (i > quantPhraseId + 2 || i < quantPhraseId - 2)
           && !npList.contains(cons)
           && cons.getLabel().equals("NP")) {
         npList.add(cons);
       }
     }
   }
   // Remove quantity phrases from npList
   for (Constituent cons : npList) {
     boolean allow = true;
     for (QuantSpan qs : prob.quantities) {
       int index = prob.ta.getTokenIdFromCharacterOffset(qs.start);
       if (index >= cons.getStartSpan() && index < cons.getEndSpan()) {
         allow = false;
         break;
       }
     }
     if (allow) {
       npListQuantRemoved.add(cons);
     }
   }
   return npListQuantRemoved;
 }