private void buildToJsonForOption(
      PropertyWrapper pWrap, OJAnnotatedClass annotatedClass, OJBlock block) {

    SortedSet<Classifier> concreteImplementations =
        new TreeSet<Classifier>(
            new Comparator<Classifier>() {
              @Override
              public int compare(Classifier o1, Classifier o2) {
                return o1.getName().compareTo(o2.getName());
              }
            });

    // For derived unions only show tabs for each property that makes up the union.
    if (pWrap.isDerivedUnion()) {
      List<Property> subsettingProperties =
          ModelLoader.INSTANCE.findSubsettingProperties(pWrap.getProperty());
      for (Property subsettingProperty : subsettingProperties) {
        concreteImplementations.addAll(
            UmlgClassOperations.getConcreteImplementations(
                (Classifier) subsettingProperty.getType()));
      }
    } else {
      // For non derived union show all concrete implementations
      concreteImplementations =
          UmlgClassOperations.getConcreteImplementations((Classifier) pWrap.getType());
    }

    Set<Classifier> concreteImplementationsFrom =
        UmlgClassOperations.getConcreteImplementations((Classifier) pWrap.getOwningType());
    if (!concreteImplementationsFrom.isEmpty()) {
      annotatedClass.addToImports(UmlgGenerationUtil.ToJsonUtil);
      // blok get reassigned for the meta data if statement
      OJBlock returnBlock = block;
      block.addToStatements("StringBuilder json = new StringBuilder()");
      block.addToStatements("json.append(\"[\")");

      int count = 1;
      // For meta data, put where one is navigating to first, then where on is
      // navigating from
      // This is consistent with navigating to a entity with a vertex where
      // there is no navigating from.
      // i.e. the first meta data in the array is the entity navigating to.
      for (Classifier concreteClassifierTo : concreteImplementations) {
        annotatedClass.addToImports(UmlgClassOperations.getPathName(concreteClassifierTo));

        for (Classifier concreteClassifierFrom : concreteImplementationsFrom) {

          block.addToStatements("json.append(\"{\")");

          block.addToStatements("json.append(\" \\\"meta\\\" : {\")");
          block.addToStatements(
              "json.append(\"\\\"qualifiedName\\\": \\\"" + pWrap.getQualifiedName() + "\\\"\")");

          // The execute ocl query resource is only required if the below
          // visitor is available
          if (RestletVisitors.containsVisitorForClass(QueryExecuteResourceBuilder.class)
              && (pWrap
                      .getType()
                      .getQualifiedName()
                      .equals(UmlgRestletGenerationUtil.instanceQueryQualifiedName)
                  || pWrap
                      .getType()
                      .getQualifiedName()
                      .equals(UmlgRestletGenerationUtil.classQueryQualifiedName))) {
            block.addToStatements(
                "json.append(\", \\\"oclExecuteUri\\\": \\\"/"
                    + pWrap.getModel().getName()
                    + "/{contextId}/oclExecuteQuery\\\"\")");
          }
          block.addToStatements("json.append(\", \\\"to\\\": \")");
          OJBlock conditionBlockFrom = new OJBlock();
          annotatedClass.addToImports(UmlgClassOperations.getPathName(concreteClassifierFrom));

          conditionBlockFrom.addToStatements(
              "json.append("
                  + UmlgClassOperations.propertyEnumName(concreteClassifierTo)
                  + ".asJson())");
          conditionBlockFrom.addToStatements("json.append(\", \\\"from\\\": \")");
          conditionBlockFrom.addToStatements(
              "json.append("
                  + UmlgClassOperations.propertyEnumName(concreteClassifierFrom)
                  + ".asJson())");
          annotatedClass.addToImports(
              UmlgClassOperations.getPathName(concreteClassifierFrom)
                  .append(UmlgClassOperations.propertyEnumName(concreteClassifierFrom)));

          block.addToStatements(conditionBlockFrom);

          annotatedClass.addToImports(
              UmlgClassOperations.getPathName(pWrap.getOwningType())
                  .append(UmlgClassOperations.propertyEnumName(pWrap.getOwningType())));
          annotatedClass.addToImports(
              UmlgClassOperations.getPathName(concreteClassifierTo)
                  .append(UmlgClassOperations.propertyEnumName(concreteClassifierTo)));

          if (count++ < (concreteImplementations.size() * concreteImplementationsFrom.size())) {
            block.addToStatements("json.append(\"}},\")");
          } else {
            block.addToStatements("json.append(\"}}\")");
          }
        }
        block = returnBlock;
      }
      returnBlock.addToStatements("json.append(\"]\")");
      returnBlock.addToStatements(
          "return new "
              + UmlgRestletGenerationUtil.JsonRepresentation.getLast()
              + "(json.toString())");
    } else {
      // TODO not thought through
      block.addToStatements("return null");
    }
  }
  private void buildToJson(PropertyWrapper pWrap, OJAnnotatedClass annotatedClass, OJBlock block) {

    // This is very important to be a sorted set. The get and options method need to return the meta
    // data in the same order.
    // This allows the client to merge them easily

    SortedSet<Classifier> sortedConcreteImplementations =
        new TreeSet<Classifier>(
            new Comparator<Classifier>() {
              @Override
              public int compare(Classifier o1, Classifier o2) {
                return o1.getName().compareTo(o2.getName());
              }
            });

    // For derived unions only show tabs for each property that makes up the union.
    if (pWrap.isDerivedUnion()) {
      List<Property> subsettingProperties =
          ModelLoader.INSTANCE.findSubsettingProperties(pWrap.getProperty());
      for (Property subsettingProperty : subsettingProperties) {
        sortedConcreteImplementations.addAll(
            UmlgClassOperations.getConcreteImplementations(
                (Classifier) subsettingProperty.getType()));
      }
    } else {
      // For non derived union show all concrete implementations
      sortedConcreteImplementations =
          UmlgClassOperations.getConcreteImplementations((Classifier) pWrap.getType());
    }

    Set<Classifier> concreteImplementationsFrom =
        UmlgClassOperations.getConcreteImplementations((Classifier) pWrap.getOwningType());
    if (!concreteImplementationsFrom.isEmpty()) {
      annotatedClass.addToImports(UmlgGenerationUtil.ToJsonUtil);
      // block get reassigned for the meta data if statement
      OJBlock returnBlock = block;
      block.addToStatements("StringBuilder json = new StringBuilder()");
      block.addToStatements("json.append(\"[\")");

      int count = 1;
      // For meta data, put where one is navigating to first, then where on is
      // navigating from
      // This is consistent with navigating to a entity with a vertex where
      // there is no navigating from.
      // i.e. the first meta data in the array is the entity navigating to.
      for (Classifier concreteClassifierTo : sortedConcreteImplementations) {
        annotatedClass.addToImports(UmlgClassOperations.getPathName(concreteClassifierTo));
        if (pWrap.isOne()) {
          block.addToStatements("json.append(\"{\\\"data\\\": \")");
        } else {
          block.addToStatements("json.append(\"{\\\"data\\\": [\")");
        }
        if (pWrap.isOne()) {
          OJIfStatement ifOneInstanceOf =
              new OJIfStatement(
                  "parentResource."
                      + pWrap.getter()
                      + "() != null && parentResource."
                      + pWrap.getter()
                      + "().getClass() == "
                      + UmlgClassOperations.getPathName(concreteClassifierTo).getLast()
                      + ".class");
          ifOneInstanceOf.addToThenPart(
              "json.append("
                  + UmlgGenerationUtil.ToJsonUtil.getLast()
                  + ".toJsonWithoutCompositeParent(parentResource."
                  + pWrap.getter()
                  + "()))");
          ifOneInstanceOf.addToElsePart("json.append(\"null\")");
          block.addToStatements(ifOneInstanceOf);
        } else {
          block.addToStatements(
              "json.append("
                  + UmlgGenerationUtil.ToJsonUtil.getLast()
                  + ".toJsonWithoutCompositeParent(parentResource."
                  + pWrap.getter()
                  + "().select(new "
                  + UmlgGenerationUtil.BooleanExpressionEvaluator.getCopy()
                      .addToGenerics(UmlgClassOperations.getPathName(pWrap.getType()))
                      .getLast()
                  + "() {\n			@Override\n			public Boolean evaluate("
                  + UmlgClassOperations.getPathName(pWrap.getType()).getLast()
                  + " e) {\n				return e.getClass() == "
                  + UmlgClassOperations.getPathName(concreteClassifierTo).getLast()
                  + ".class;\n			}\n		})))");
          annotatedClass.addToImports(UmlgGenerationUtil.BooleanExpressionEvaluator);
        }
        annotatedClass.addToImports(UmlgClassOperations.getPathName(pWrap.getType()));
        if (pWrap.isOne()) {
          block.addToStatements("json.append(\",\")");
        } else {
          block.addToStatements("json.append(\"],\")");
        }

        block.addToStatements("json.append(\" \\\"meta\\\" : {\")");
        block.addToStatements(
            "json.append(\"\\\"qualifiedName\\\": \\\"" + pWrap.getQualifiedName() + "\\\"\")");

        block.addToStatements(
            "json.append(\",\\\"qualifiedNameFrom\\\": \\\"\" + parentResource.getQualifiedName() + \"\\\"\")");
        block.addToStatements(
            "json.append(\",\\\"qualifiedNameTo\\\": \\\""
                + concreteClassifierTo.getQualifiedName()
                + "\\\"\")");

        block.addToStatements("json.append(\"}\")");
        if (sortedConcreteImplementations.size() != 1
            && count != sortedConcreteImplementations.size()) {
          block.addToStatements("json.append(\"}, \")");
        }
        block = returnBlock;
        count++;
      }
      returnBlock.addToStatements("json.append(\"}]\")");
      returnBlock.addToStatements(
          "return new "
              + UmlgRestletGenerationUtil.JsonRepresentation.getLast()
              + "(json.toString())");
    } else {
      // TODO not thought through
      block.addToStatements("return null");
    }
  }