public static OJAnnotatedOperation buildSetter(OJAnnotatedClass owner, PropertyWrapper pWrap) {
   OJAnnotatedOperation setter = new OJAnnotatedOperation(pWrap.setter());
   if (pWrap.isReadOnly()) {
     setter.setVisibility(OJVisibilityKind.PROTECTED);
   }
   if (!pWrap.isMemberOfAssociationClass()) {
     setter.addParam(pWrap.fieldname(), pWrap.javaTypePath());
   } else {
     setter.addParam(
         pWrap.getAssociationClassFakePropertyName(), pWrap.javaTypePathWithAssociationClass());
   }
   setter.getBody().addToStatements(pWrap.clearer() + "()");
   OJIfStatement ifNotNull;
   if (!pWrap.isMemberOfAssociationClass()) {
     ifNotNull = new OJIfStatement(pWrap.fieldname() + " != null");
     ifNotNull.addToThenPart(pWrap.adder() + "(" + pWrap.fieldname() + ")");
   } else {
     ifNotNull = new OJIfStatement(pWrap.getAssociationClassFakePropertyName() + " != null");
     ifNotNull.addToThenPart(
         pWrap.adder() + "(" + pWrap.getAssociationClassFakePropertyName() + ")");
   }
   setter.getBody().addToStatements(ifNotNull);
   owner.addToOperations(setter);
   return setter;
 }
  public static void buildGetter(OJAnnotatedClass owner, PropertyWrapper propertyWrapper) {
    OJAnnotatedOperation getter =
        new OJAnnotatedOperation(propertyWrapper.getter(), propertyWrapper.javaTumlTypePath());
    getter.getBody().addToStatements("return this." + propertyWrapper.fieldname());
    owner.addToOperations(getter);

    if (propertyWrapper.isMemberOfAssociationClass()) {
      getter =
          new OJAnnotatedOperation(
              propertyWrapper.associationClassGetter(),
              propertyWrapper.getAssociationClassJavaTumlTypePath());
      getter
          .getBody()
          .addToStatements("return this." + propertyWrapper.getAssociationClassFakePropertyName());
      owner.addToOperations(getter);

      // Build getter that returns the AssociationClass for an instance of the other end
      buildGetAssociationClassForPropertyInstance(owner, propertyWrapper);
    }

    // If the property is subsetting another property then add @Override to the getter.
    // The subsetted property's implementation will add an protected getter with the subsetting
    // property's name
    if (!propertyWrapper.getSubsettedProperties().isEmpty()) {
      // if subsetted property is on an interface then there is no fake implementation, so no
      // override
      Property subsettedProperty = propertyWrapper.getSubsettedProperties().get(0);
      PropertyWrapper subsettedPropertyWrapper = new PropertyWrapper(subsettedProperty);
      if (!(subsettedProperty.getType() instanceof Interface)
          && subsettedPropertyWrapper.getOtherEnd().getType()
              != propertyWrapper.getOtherEnd().getType()) {
        UmlgGenerationUtil.addOverrideAnnotation(getter);
      }
    }
  }
 private static void buildGetAssociationClassForPropertyInstance(
     OJAnnotatedClass owner, PropertyWrapper propertyWrapper) {
   OJAnnotatedOperation getAC =
       new OJAnnotatedOperation(
           propertyWrapper.associationClassGetterForProperty(),
           propertyWrapper.getAssociationClassPathName());
   getAC.addParam(propertyWrapper.fieldname(), propertyWrapper.javaBaseTypePath());
   OJForStatement forAC =
       new OJForStatement(
           "ac",
           propertyWrapper.getAssociationClassPathName(),
           "this." + propertyWrapper.getAssociationClassFakePropertyName());
   OJIfStatement ifStatement =
       new OJIfStatement(
           "ac." + propertyWrapper.getter() + "().equals(" + propertyWrapper.fieldname() + ")",
           "return ac");
   forAC.getBody().addToStatements(ifStatement);
   getAC.getBody().addToStatements(forAC);
   getAC.getBody().addToStatements("return null");
   owner.addToOperations(getAC);
 }
 private static String constructNotifierForOtherEndMany(
     PropertyWrapper propertyWrapper, PropertyWrapper otherEnd) {
   return UmlgGenerationUtil.UmlgNotificationManager.getLast()
       + ".INSTANCE.notify(\n\t"
       + propertyWrapper.getTumlRuntimePropertyEnum()
       + ",\n\tChangeHolder.of(\n\t\t"
       + otherEnd.fieldname()
       + ",\n\t\t"
       + propertyWrapper.getTumlRuntimePropertyEnum()
       + ",\n\t\t"
       + "ChangeHolder.ChangeType.DELETE,\n\t\t"
       + "this.toJson()"
       + "\n\t)\n)";
 }
 public static void buildGetterForAssociationClass(
     OJAnnotatedClass ac, PropertyWrapper propertyWrapper) {
   PropertyWrapper otherEnd = new PropertyWrapper(propertyWrapper.getOtherEnd());
   OJAnnotatedOperation getter =
       new OJAnnotatedOperation(otherEnd.getter(), otherEnd.javaBaseTypePath());
   OJAnnotatedField tmpField = new OJAnnotatedField("tmp", otherEnd.javaTumlTypePath(true));
   getter.getBody().addToLocals(tmpField);
   tmpField.setInitExp("this." + otherEnd.fieldname());
   OJIfStatement ifFieldNotEmpty = new OJIfStatement("!" + tmpField.getName() + ".isEmpty()");
   if (otherEnd.isOrdered()) {
     ifFieldNotEmpty.addToThenPart("return " + tmpField.getName() + ".get(0)");
   } else {
     ifFieldNotEmpty.addToThenPart("return " + tmpField.getName() + ".iterator().next()");
   }
   ifFieldNotEmpty.addToElsePart("return null");
   getter.getBody().addToStatements(ifFieldNotEmpty);
   ac.addToOperations(getter);
 }
  private void addPostResource(
      PropertyWrapper pWrap, OJAnnotatedClass annotatedClass, OJPathName parentPathName) {
    OJAnnotatedOperation add = new OJAnnotatedOperation("add");
    add.setVisibility(OJVisibilityKind.PRIVATE);

    add.addToParameters(
        new OJParameter(
            "resultMap",
            new OJPathName("java.util.Map")
                .addToGenerics(
                    new OJPathName("Class")
                        .addToGenerics("? extends " + pWrap.javaBaseTypePath().getLast()))
                .addToGenerics(
                    "List<" + UmlgRestletGenerationUtil.UmlgNodeJsonHolder.getLast() + ">")));
    add.addToParameters(new OJParameter("parentResource", parentPathName));
    add.addToParameters(
        new OJParameter(
            "propertyMap",
            new OJPathName("java.util.Map").addToGenerics("String").addToGenerics("Object")));
    annotatedClass.addToOperations(add);

    OJField qualifiedName = new OJField("qualifiedName", "String");
    qualifiedName.setInitExp("(String)propertyMap.get(\"qualifiedName\")");
    add.getBody().addToLocals(qualifiedName);

    OJField baseTumlClass =
        new OJField(
            "baseTumlClass", new OJPathName("Class").addToGenerics(pWrap.javaBaseTypePath()));
    baseTumlClass.setInitExp(
        UmlgGenerationUtil.UmlgSchemaFactory.getLast() + ".getUmlgSchemaMap().get(qualifiedName)");
    annotatedClass.addToImports(UmlgGenerationUtil.UmlgSchemaFactory);
    add.getBody().addToLocals(baseTumlClass);

    OJField sb =
        new OJField(
            "objectList", "List<" + UmlgRestletGenerationUtil.UmlgNodeJsonHolder.getLast() + ">");
    add.getBody().addToLocals(sb);

    OJIfStatement ifSbExist = new OJIfStatement("!resultMap.containsKey(baseTumlClass)");
    ifSbExist.addToThenPart(
        "objectList = new ArrayList<"
            + UmlgRestletGenerationUtil.UmlgNodeJsonHolder.getLast()
            + ">()");
    ifSbExist.addToThenPart("resultMap.put(baseTumlClass, objectList)");
    ifSbExist.addToElsePart("objectList = resultMap.get(baseTumlClass)");
    add.getBody().addToStatements(ifSbExist);

    OJTryStatement tryInstantiate = new OJTryStatement();
    add.getBody().addToStatements(tryInstantiate);

    if (pWrap.isComposite()) {
      PropertyWrapper otherEndPWrap = new PropertyWrapper(pWrap.getOtherEnd());
      if (!pWrap.isMemberOfAssociationClass()) {
        OJField constructor =
            new OJField(
                "constructor",
                new OJPathName("java.lang.reflect.Constructor")
                    .addToGenerics(pWrap.javaBaseTypePath()));
        constructor.setInitExp(
            "baseTumlClass.getConstructor("
                + otherEndPWrap.javaBaseTypePath().getLast()
                + ".class)");
        tryInstantiate.getTryPart().addToLocals(constructor);
        tryInstantiate
            .getTryPart()
            .addToStatements(
                pWrap.javaBaseTypePath().getLast()
                    + " childResource = constructor.newInstance(parentResource)");
        tryInstantiate.getTryPart().addToStatements("childResource.fromJson(propertyMap)");
        tryInstantiate
            .getTryPart()
            .addToStatements(
                "objectList.add(new "
                    + UmlgRestletGenerationUtil.UmlgNodeJsonHolder.getLast()
                    + "(childResource))");
      } else {
        PropertyWrapper otherEnd = new PropertyWrapper(pWrap.getOtherEnd());
        OJField constructor =
            new OJField(
                "constructor",
                new OJPathName("java.lang.reflect.Constructor")
                    .addToGenerics(pWrap.javaBaseTypePath()));
        constructor.setInitExp(
            "baseTumlClass.getConstructor("
                + otherEndPWrap.javaBaseTypePath().getLast()
                + ".class, "
                + otherEnd.getAssociationClassPathName().getLast()
                + ".class)");
        tryInstantiate.getTryPart().addToLocals(constructor);

        // TODO check this out, it creates a duplicate as the fromJson creates the association class
        tryInstantiate
            .getTryPart()
            .addToStatements(
                otherEnd.getAssociationClassPathName().getLast()
                    + " "
                    + otherEnd.getAssociationClassFakePropertyName()
                    + " = new "
                    + otherEnd.getAssociationClassPathName().getLast()
                    + "(true)");
        tryInstantiate
            .getTryPart()
            .addToStatements(
                otherEnd.getAssociationClassFakePropertyName()
                    + ".fromJson((Map<String, Object>) propertyMap.get(\""
                    + otherEnd.getAssociationClassFakePropertyName()
                    + "\"))");
        tryInstantiate
            .getTryPart()
            .addToStatements(
                pWrap.javaBaseTypePath().getLast()
                    + " childResource = constructor.newInstance(parentResource, "
                    + otherEnd.getAssociationClassFakePropertyName()
                    + ")");
        tryInstantiate.getTryPart().addToStatements("childResource.fromJson(propertyMap)");
        tryInstantiate
            .getTryPart()
            .addToStatements(
                "objectList.add(new "
                    + UmlgRestletGenerationUtil.UmlgNodeJsonHolder.getLast()
                    + "(childResource, \""
                    + otherEnd.getAssociationClassFakePropertyName()
                    + "\", "
                    + otherEnd.getAssociationClassFakePropertyName()
                    + "))");
        annotatedClass.addToImports(otherEnd.getAssociationClassPathName());
      }
    } else {
      tryInstantiate.getTryPart().addToStatements("Object id = propertyMap.get(\"id\")");
      // Need to remove the one from the map, otherwise the from will also add the one and create
      // another association class
      PropertyWrapper otherEndPWrap = new PropertyWrapper(pWrap.getOtherEnd());
      tryInstantiate
          .getTryPart()
          .addToStatements("propertyMap.remove(\"" + otherEndPWrap.fieldname() + "\")");
      tryInstantiate
          .getTryPart()
          .addToStatements(
              pWrap.javaBaseTypePath().getLast()
                  + " childResource = "
                  + UmlgGenerationUtil.UMLGAccess
                  + "."
                  + UmlgGenerationUtil.getEntity
                  + "(id)");
      if (!pWrap.isMemberOfAssociationClass()) {
        //
        // tryInstantiate.getTryPart().addToStatements("childResource.fromJson(propertyMap)");
        tryInstantiate
            .getTryPart()
            .addToStatements("parentResource." + pWrap.adder() + "(childResource)");
        tryInstantiate
            .getTryPart()
            .addToStatements(
                "objectList.add(new "
                    + UmlgRestletGenerationUtil.UmlgNodeJsonHolder.getLast()
                    + "(childResource))");
      } else {
        //
        // tryInstantiate.getTryPart().addToStatements("childResource.fromJson(propertyMap)");
        PropertyWrapper otherEnd = new PropertyWrapper(pWrap.getOtherEnd());

        // TODO check this out, it creates a duplicate as the fromJson creates the association class
        tryInstantiate
            .getTryPart()
            .addToStatements(
                otherEnd.getAssociationClassPathName().getLast()
                    + " "
                    + otherEnd.getAssociationClassFakePropertyName()
                    + " = new "
                    + otherEnd.getAssociationClassPathName().getLast()
                    + "(true)");
        tryInstantiate
            .getTryPart()
            .addToStatements(
                otherEnd.getAssociationClassFakePropertyName()
                    + ".fromJson((Map<String, Object>) propertyMap.get(\""
                    + otherEnd.getAssociationClassFakePropertyName()
                    + "\"))");
        tryInstantiate
            .getTryPart()
            .addToStatements(
                "parentResource."
                    + pWrap.adder()
                    + "(childResource, "
                    + otherEnd.getAssociationClassFakePropertyName()
                    + ")");
        tryInstantiate
            .getTryPart()
            .addToStatements(
                "objectList.add(new "
                    + UmlgRestletGenerationUtil.UmlgNodeJsonHolder.getLast()
                    + "(childResource, \""
                    + otherEnd.getAssociationClassFakePropertyName()
                    + "\", "
                    + otherEnd.getAssociationClassFakePropertyName()
                    + "))");
        annotatedClass.addToImports(otherEnd.getAssociationClassPathName());
      }
    }

    annotatedClass.addToImports(pWrap.javaBaseTypePath());
    if (pWrap.isOrdered()) {
      // TODO
    } else {
      // TODO
    }
    tryInstantiate.setCatchParam(new OJParameter("e", "Exception"));
    tryInstantiate.getCatchPart().addToStatements("throw new RuntimeException(e)");
  }
  private void addServerResourceToRouterEnum(
      PropertyWrapper pWrap, OJAnnotatedClass annotatedClass) {
    OJEnum routerEnum =
        (OJEnum)
            this.workspace.findOJClass(UmlgRestletGenerationUtil.RestletRouterEnum.toJavaString());

    OJEnumLiteral ojLiteral =
        new OJEnumLiteral(
            UmlgClassOperations.getPathName(pWrap.getOwningType()).getLast()
                + "_"
                + pWrap.fieldname());

    OJField uri = new OJField();
    uri.setType(new OJPathName("String"));
    uri.setInitExp(
        "\"/"
            + UmlgClassOperations.getPathName(pWrap.getOwningType()).getLast().toLowerCase()
            + "s/{"
            + UmlgClassOperations.getPathName(pWrap.getOwningType()).getLast().toLowerCase()
            + "Id}/"
            + pWrap.fieldname()
            + "\"");
    ojLiteral.addToAttributeValues(uri);

    OJField serverResourceClassField = new OJField();
    serverResourceClassField.setType(new OJPathName("java.lang.Class"));
    serverResourceClassField.setInitExp(annotatedClass.getName() + ".class");
    ojLiteral.addToAttributeValues(serverResourceClassField);
    routerEnum.addToImports(annotatedClass.getPathName());
    routerEnum.addToImports(UmlgRestletGenerationUtil.ServerResource);

    routerEnum.addToLiterals(ojLiteral);

    OJAnnotatedOperation attachAll =
        routerEnum.findOperation("attachAll", UmlgRestletGenerationUtil.Router);
    attachAll
        .getBody()
        .addToStatements(routerEnum.getName() + "." + ojLiteral.getName() + ".attach(router)");

    //        //Add the url for post/put to the resource
    //        ojLiteral = new
    // OJEnumLiteral(UmlgClassOperations.getPathName(pWrap.getOwningType()).getLast() + "_" +
    // pWrap.fieldname());
    //
    //        uri = new OJField();
    //        uri.setType(new OJPathName("String"));
    //        uri.setInitExp("\"" +
    // UmlgClassOperations.getPathName(pWrap.getOwningType()).getLast().toLowerCase() + "s/{"
    //                +
    // UmlgClassOperations.getPathName(pWrap.getOwningType()).getLast().toLowerCase() + "Id}/" +
    // pWrap.fieldname() + "\"");
    //        ojLiteral.addToAttributeValues(uri);
    //
    //        serverResourceClassField = new OJField();
    //        serverResourceClassField.setType(new OJPathName("java.lang.Class"));
    //        serverResourceClassField.setInitExp(annotatedClass.getName() + ".class");
    //        ojLiteral.addToAttributeValues(serverResourceClassField);
    //        routerEnum.addToImports(annotatedClass.getPathName());
    //        routerEnum.addToImports(UmlgRestletGenerationUtil.ServerResource);
    //
    //        routerEnum.addToLiterals(ojLiteral);
    //
    //        attachAll.getBody().addToStatements(routerEnum.getName() + "." + ojLiteral.getName() +
    // ".attach(router)");

  }
  public static void buildManyAdder(
      OJAnnotatedClass owner,
      PropertyWrapper propertyWrapper,
      boolean indexed,
      boolean ignoreInverse) {
    OJAnnotatedOperation adder = new OJAnnotatedOperation(propertyWrapper.adder());
    if (!propertyWrapper.isMemberOfAssociationClass()) {
      if (indexed) {
        adder.addParam("index", "int");
      }
      adder.addParam(propertyWrapper.fieldname(), propertyWrapper.javaTypePath());
    } else {
      if (indexed) {
        adder.addParam("index", "int");
      }
      adder.addParam(
          propertyWrapper.getAssociationClassFakePropertyName(),
          propertyWrapper.javaTypePathWithAssociationClass());
    }

    if (!(owner instanceof OJAnnotatedInterface)) {
      if (!propertyWrapper.hasQualifiers()) {
        if (!propertyWrapper.isMemberOfAssociationClass()) {
          OJIfStatement ifNotNull =
              new OJIfStatement("!" + propertyWrapper.fieldname() + ".isEmpty()");
          ifNotNull.addToThenPart(
              "this."
                  + propertyWrapper.fieldname()
                  + ".addAll("
                  + propertyWrapper.fieldname()
                  + ")");
          adder.getBody().addToStatements(ifNotNull);
        } else {
          // iterate the association class set as it contains a Pair
          OJForStatement associationClassPairs =
              new OJForStatement(
                  "pair",
                  propertyWrapper.getAssociationClassPair(),
                  propertyWrapper.getAssociationClassFakePropertyName());
          associationClassPairs
              .getBody()
              .addToStatements(propertyWrapper.adder() + "(pair.getFirst(), pair.getSecond())");
          adder.getBody().addToStatements(associationClassPairs);
        }
      } else {
        String elementName = "_" + propertyWrapper.fieldname().substring(0, 1);
        OJForStatement forAll =
            new OJForStatement(
                elementName, propertyWrapper.javaBaseTypePath(), propertyWrapper.fieldname());
        forAll
            .getBody()
            .addToStatements("this." + propertyWrapper.adder() + "(" + elementName + ")");
        adder.getBody().addToStatements(forAll);
      }
    }
    owner.addToOperations(adder);

    OJAnnotatedOperation singleAdder =
        new OJAnnotatedOperation(
            !ignoreInverse ? propertyWrapper.adder() : propertyWrapper.adderIgnoreInverse());
    if (indexed) {
      singleAdder.addParam("index", "int");
    }
    singleAdder.addParam(propertyWrapper.fieldname(), propertyWrapper.javaBaseTypePath());
    if (propertyWrapper.isMemberOfAssociationClass()) {
      singleAdder.addParam(
          StringUtils.uncapitalize(propertyWrapper.getAssociationClass().getName()),
          UmlgClassOperations.getPathName(propertyWrapper.getAssociationClass()));
    }
    if (!(owner instanceof OJAnnotatedInterface)) {

      PropertyWrapper otherEnd = new PropertyWrapper(propertyWrapper.getOtherEnd());
      if (
      /*For bags the one side can have many edges to the same element*/ propertyWrapper.isUnique()
          && propertyWrapper.hasOtherEnd()
          && !propertyWrapper.isEnumeration()
          && otherEnd.isOne()) {
        OJIfStatement ifNotNull2 = new OJIfStatement(propertyWrapper.fieldname() + " != null");
        ifNotNull2.addToThenPart(propertyWrapper.fieldname() + "." + otherEnd.clearer() + "()");
        ifNotNull2.addToThenPart(
            propertyWrapper.fieldname()
                + ".initialiseProperty("
                + UmlgClassOperations.propertyEnumName(otherEnd.getOwningType())
                + "."
                + otherEnd.fieldname()
                + ", false)");
        ifNotNull2.addToThenPart(
            propertyWrapper.remover() + "(" + propertyWrapper.fieldname() + ")");
        owner.addToImports(
            UmlgClassOperations.getPathName(otherEnd.getOwningType())
                .append(UmlgClassOperations.propertyEnumName(otherEnd.getOwningType())));
        singleAdder.getBody().addToStatements(ifNotNull2);
      }
      OJIfStatement ifNotNull = new OJIfStatement(propertyWrapper.fieldname() + " != null");

      // Add in validations

      OJBlock block;
      if (propertyWrapper.isDataType()) {
        OJField failedConstraints =
            new OJField(
                "violations",
                new OJPathName("java.util.List")
                    .addToGenerics(UmlgGenerationUtil.UmlgConstraintViolation));
        failedConstraints.setInitExp(
            propertyWrapper.validator() + "(" + propertyWrapper.fieldname() + ")");
        ifNotNull.getThenPart().addToLocals(failedConstraints);
        OJIfStatement ifValidated = new OJIfStatement("violations.isEmpty()");
        ifValidated.addToElsePart(
            "throw new "
                + UmlgGenerationUtil.UmlgConstraintViolationException.getLast()
                + "(violations)");
        owner.addToImports(UmlgGenerationUtil.UmlgConstraintViolationException);
        ifNotNull.addToThenPart(ifValidated);
        block = ifValidated.getThenPart();
      } else {
        block = ifNotNull.getThenPart();
      }

      if (!propertyWrapper.isMemberOfAssociationClass()) {
        if (!indexed) {
          if (!ignoreInverse) {
            block.addToStatements(
                "this."
                    + propertyWrapper.fieldname()
                    + ".add("
                    + propertyWrapper.fieldname()
                    + ")");
          } else {
            block.addToStatements(
                "this."
                    + propertyWrapper.fieldname()
                    + ".addIgnoreInverse("
                    + propertyWrapper.fieldname()
                    + ")");
          }
        } else {
          block.addToStatements(
              "this."
                  + propertyWrapper.fieldname()
                  + ".add(index, "
                  + propertyWrapper.fieldname()
                  + ")");
        }
      } else {
        if (!indexed) {
          block.addToStatements(
              "this."
                  + propertyWrapper.fieldname()
                  + ".add("
                  + propertyWrapper.fieldname()
                  + ", "
                  + StringUtils.uncapitalize(propertyWrapper.getAssociationClass().getName())
                  + ")");
        } else {
          block.addToStatements(
              "this."
                  + propertyWrapper.fieldname()
                  + ".add(index, "
                  + propertyWrapper.fieldname()
                  + ", "
                  + StringUtils.uncapitalize(propertyWrapper.getAssociationClass().getName())
                  + ")");
        }
      }
      singleAdder.getBody().addToStatements(ifNotNull);
    }
    owner.addToOperations(singleAdder);

    //        //Add change listener
    //        if (propertyWrapper.isChangedListener()) {
    //            PropertyChangeNotificationBuilder.buildChangeNotification(owner, singleAdder,
    // propertyWrapper, PropertyChangeNotificationBuilder.CHANGE_TYPE.ADD);
    //        }

  }