public WDBObject getParentObject(String superClassName, ParserAdapter scda) throws Exception {
   ClassDef myClass = this.getClassDef(scda);
   // See if its parent of this class
   if (myClass.getClass() == SubclassDef.class) {
     // See if its one of my immediate superclasses.
     if (parents.containsKey(superClassName)) {
       return scda.getObject(superClassName, ((Integer) parents.get(superClassName)));
     }
     // Not immediate superclass of me. Check my parents.
     Enumeration e = parents.keys();
     while (e.hasMoreElements()) {
       String parentClass = (String) e.nextElement();
       Integer parentUid = (Integer) parents.get(parentClass);
       WDBObject parent = scda.getObject(parentClass, parentUid);
       WDBObject grandparent = parent.getParentObject(superClassName, scda);
       if (grandparent != null) {
         return grandparent;
       }
     }
     // Not any superClass of mine!
     return null;
   } else {
     return null;
   }
 }
 public void removeEvaObjects(
     String evaName, String targetClass, SimpleNode expression, ParserAdapter scda)
     throws Exception {
   ClassDef targetClassDef = scda.getClass(targetClass);
   WDBObject[] matchingObjs = targetClassDef.search(expression, scda);
   removeEvaObjects(evaName, targetClass, matchingObjs, scda);
 }
 public WDBObject getChildObject(String subClassName, ParserAdapter scda) throws Exception {
   // See if its one of my immediate subclasses.
   if (children.containsKey(subClassName)) {
     return scda.getObject(subClassName, ((Integer) children.get(subClassName)));
   } else {
     return null;
   }
 }
  public void PrintAttribute(PrintNode row, AttributePath attributePath, ParserAdapter scda)
      throws Exception {
    ClassDef myClass = this.getClassDef(scda);
    if (attributePath.levelsOfIndirection() <= 0) {
      if (attributePath.attribute.equals("*")) {
        for (int j = 0; j < myClass.attributes.size(); j++) {
          Attribute currentAttribute = (Attribute) myClass.getAttribute(j);
          if (currentAttribute.getClass() == DVA.class) {
            Object dvaValue = dvaValues.get(currentAttribute.name);
            PrintCell cell = new PrintCell();
            cell.setOutput(String.format("%s", dvaValue));
            row.addCell(cell);
          }
        }
        if (myClass.getClass() == SubclassDef.class) {
          for (int i = 0; i < ((SubclassDef) myClass).numberOfSuperClasses(); i++) {
            String parentClass = (String) ((SubclassDef) myClass).getSuperClass(i);
            Integer parentUid = (Integer) this.parents.get(parentClass);
            WDBObject parent = scda.getObject(parentClass, parentUid);
            parent.PrintAttribute(row, attributePath, scda);
          }
        }
      } else {
        Attribute currentAttribute = (Attribute) myClass.getAttribute(attributePath.attribute);
        Object dvaValue = getDvaValue(attributePath.attribute, scda);
        PrintCell cell = new PrintCell();
        cell.setOutput(String.format("%s", dvaValue));
        row.addCell(cell);
      }
    } else {
      String evaName = attributePath.getIndirection(attributePath.levelsOfIndirection() - 1);
      WDBObject[] objects = this.getEvaObjects(evaName, scda);
      ArrayList<PrintNode> branch = row.getBranch(evaName);

      if (objects != null && objects.length > 0) {
        if (branch == null) {
          branch = row.newBranch(evaName, objects.length);
        }
        attributePath.removeIndirection(attributePath.levelsOfIndirection() - 1);
        for (int i = 0; i < objects.length; i++) {
          objects[i].PrintAttribute(branch.get(i), attributePath, scda);
        }
        attributePath.addIndirection(evaName);
      } else {
        if (branch == null) {
          branch = row.newBranch(evaName, 1);
          myClass.padAttribute(branch.get(0), attributePath, scda);
        }
      }

      row.updateBranchCols(evaName);
    }
  }
  public void setDvaValue(String dvaName, Object value, ParserAdapter scda) throws Exception {
    // See if its immediate in this class
    ClassDef myClass = this.getClassDef(scda);
    Attribute myAttribute = myClass.getAttribute(dvaName);
    if (myAttribute != null && myAttribute.getClass() == DVA.class) {
      if (value instanceof String) {
        this.dvaValues.put(dvaName, value);
      } else if (value instanceof Integer) {
        this.dvaValues.put(dvaName, value);
      } else if (value instanceof Boolean) {
        this.dvaValues.put(dvaName, value);
      } else {
        throw new ClassCastException(
            "Type verification failed: Attribute \""
                + dvaName
                + "\" type: "
                + ((DVA) myAttribute).type.toString()
                + ", Value type: "
                + value.getClass().toString());
      }
    }
    // Not immediate, go check parents if I'm an object of a subclass
    else if (myClass.getClass() == SubclassDef.class) {
      Enumeration e = parents.keys();
      while (true) {
        if (parents.keySet().isEmpty()) {
          break;
        }
        try {
          String parentClass = (String) e.nextElement();
          Integer parentUid = (Integer) parents.get(parentClass);
          WDBObject parent = scda.getObject(parentClass, parentUid);
          parent.setDvaValue(dvaName, value, scda);
          // If we reached here, we set our value. Get out of here
          break;
        } catch (NoSuchFieldException nsfe) {
          // Can't find DVA going up that parent's heirarchy. Continue on to another parent
          if (!e.hasMoreElements()) {
            // No more parents to try. We are here if we exausted our parent's list and
            // still can't find the DVA. Throw exception
            throw nsfe;
          }
        }
      }
    }
    // value can't be found and I'm not a subclass. It doesn't exist in this heirarchy
    else {
      throw new NoSuchFieldException("Attribute \"" + dvaName + "\" is not a valid DVA");
    }

    this.commit(scda);
  }
  public Object getDvaValue(String dvaName, ParserAdapter scda) throws Exception {
    Object value = null;

    // See if its immediate in this class
    ClassDef myClass = this.getClassDef(scda);
    Attribute myAttribute = myClass.getAttribute(dvaName);
    if (myAttribute != null && myAttribute.getClass() == DVA.class) {
      value = this.dvaValues.get(dvaName);
    }
    // Not immediate, go check parents if I'm an object of a subclass
    else if (myClass.getClass() == SubclassDef.class) {
      Enumeration e = parents.keys();
      while (true) {
        try {
          String parentClass = (String) e.nextElement();
          Integer parentUid = (Integer) parents.get(parentClass);
          WDBObject parent = scda.getObject(parentClass, parentUid);

          value = parent.getDvaValue(dvaName, scda);
          // If we reached here, we got our value. Get out of here
          break;
        } catch (NoSuchFieldException nsfe) {
          // Can't find DVA going up that parent's heirarchy. Continue on to another parent
          if (!e.hasMoreElements()) {
            // No more parents to try. We are here if we exausted our parent's list and
            // still can't find the DVA. Throw exception
            throw nsfe;
          }
        }
      }
    }
    // value can't be found and I'm not a subclass. It doesn't exist in this heirarchy
    else {
      throw new NoSuchFieldException("Attribute \"" + dvaName + "\" is not a valid DVA");
    }

    return value;
  }
 public WDBObject getBaseObject(ParserAdapter scda) throws Exception {
   ClassDef myClass = this.getClassDef(scda);
   // See if its parent of this class
   if (myClass.getClass() == SubclassDef.class) {
     // Check my parents.
     Enumeration e = parents.keys();
     while (e.hasMoreElements()) {
       String parentClass = (String) e.nextElement();
       Integer parentUid = (Integer) parents.get(parentClass);
       WDBObject parent = scda.getObject(parentClass, parentUid);
       WDBObject grandparent = parent.getBaseObject(scda);
       if (grandparent != null) {
         return grandparent;
       }
     }
     // Not any superClass of mine!
     return null;
   } else if (myClass.getClass() == ClassDef.class) {
     return this;
   } else {
     return null;
   }
 }
  /*
  private void addEvaInverse(EVA ownerEva, ClassDef ownerEvaClass, WDBObject ownerEvaObject, ParserAdapter scda) throws Exception
  {
      //Try to see if other class's inverse EVA is declared on my side
      ClassDef myClass = this.getClassDef(scda);
      Attribute myAttribute = myClass.getAttribute(ownerEva.inverseEVA);
      if(myAttribute != null && myAttribute.getClass() == EVA.class)
      {
          //Oh it is, good. Use the declared settings
          if(((EVA)myAttribute).cardinality == EVA.MULTIVALUED)
          {
              ArrayList targetObjectList = ((ArrayList)this.evaObjects.get(myAttribute.name));
              if(targetObjectList == null)
              {
                  targetObjectList = new ArrayList();
              }
              targetObjectList.add(ownerEvaObject.getUid());
              this.evaObjects.put(myAttribute.name, targetObjectList);
          }
          else if(((EVA)myAttribute).cardinality == EVA.SINGLEVALUED)
          {
              //For singlevalued EVAs, just put the UID as the value;
              this.evaObjects.put(myAttribute.name, ownerEvaObject.getUid());
          }
          else
          {
              throw new NoSuchFieldException("Attribute \"" + myAttribute.name + "\" uses a invalid cardinality");
          }
      }
      else
      {
          throw new Exception("Implication of target class inverse EVAs is not implemented");

          //The inverse EVA is not defined in this class or there is no inverse EVA specified
          //We have to infer the cardinality of our inverse based on the cardinality EVA from the owner's class
          if(ownerEva.cardinality == EVA.SINGLEVALUED)
          {
              //Imply MV UNIQUE
              if(myAttribute != null)
              {
                  ArrayList targetObjectList = ((ArrayList)this.evaObjects.get(myAttribute.name));
                  if(targetObjectList == null)
                  {
                      targetObjectList = new ArrayList();
                  }
                  targetObjectList.add(ownerEvaObject.getUid());
              }
          }

      }

      this.commit(scda);
  }
  */
  public WDBObject[] getEvaObjects(String evaName, ParserAdapter scda) throws Exception {
    ClassDef myClass = this.getClassDef(scda);
    Attribute myAttribute = myClass.getAttribute(evaName);

    WDBObject[] evaObjects = new WDBObject[0];
    if (myAttribute != null && myAttribute.getClass() == EVA.class) {
      if (((EVA) myAttribute).cardinality.equals(EVA.MULTIVALUED)) {
        ArrayList<Object> targetObjectList = ((ArrayList) this.evaObjects.get(evaName));
        ArrayList<WDBObject> targetObjects = new ArrayList<WDBObject>();
        if (targetObjectList != null) {
          for (int i = 0; i < targetObjectList.size(); i++) {
            String[] targetKey = ((String) targetObjectList.get(i)).split(":");
            String targetClass = targetKey[0];
            Integer targetUid = Integer.valueOf(targetKey[1]);
            WDBObject targetObject = scda.getObject(targetClass, targetUid);
            targetObjects.add(targetObject);
          }
          evaObjects = ((WDBObject[]) targetObjects.toArray(evaObjects));
        }
      } else if (((EVA) myAttribute).cardinality.equals(EVA.SINGLEVALUED)) {
        if (this.evaObjects.get(evaName) != null) {
          String[] targetKey = ((String) this.evaObjects.get(evaName)).split(":");
          String targetClass = targetKey[0];
          Integer targetUid = Integer.valueOf(targetKey[1]);
          WDBObject targetObject = scda.getObject(targetClass, targetUid);
          if (targetObject != null) {
            WDBObject[] targetObjs = {((WDBObject) targetObject)};
            evaObjects = targetObjs;
          }
        }
      } else {
        throw new NoSuchFieldException("Attribute \"" + evaName + "\" uses a invalid cardinality");
      }

    } else if (myClass.getClass() == SubclassDef.class) {
      Enumeration e = parents.keys();
      while (true) {
        try {
          String parentClass = (String) e.nextElement();
          Integer parentUid = (Integer) parents.get(parentClass);
          WDBObject parent = scda.getObject(parentClass, parentUid);

          return parent.getEvaObjects(evaName, scda);
          // If we reached here, we get our value. Get out of here
          // break;
        } catch (NoSuchFieldException nsfe) {
          // Can't find DVA going up that parent's heirarchy. Continue on to another parent
          if (!e.hasMoreElements()) {
            // No more parents to try. We are here if we exausted our parent's list and
            // still can't find the DVA. Throw exception
            throw nsfe;
          }
        }
      }
    }
    // value can't be found and I'm not a subclass. It doesn't exist in this heirarchy
    else {
      throw new NoSuchFieldException("Attribute \"" + evaName + "\" is not a valid EVA");
    }

    return evaObjects;
  }
  public void removeEvaObjects(
      String evaName, String targetClass, WDBObject[] targetObjects, ParserAdapter scda)
      throws Exception {
    // Don't do anything if the target objects to remove is null
    if (targetObjects != null) {
      ClassDef myClass = this.getClassDef(scda);
      Attribute myAttribute = myClass.getAttribute(evaName);
      if (myAttribute != null && myAttribute.getClass() == EVA.class) {
        ClassDef targetClassDef = scda.getClass(targetClass);
        if (targetClassDef.name.equals(((EVA) myAttribute).baseClassName)
            || targetClassDef.isSubclassOf((((EVA) myAttribute).baseClassName), scda)) {
          ClassDef baseClassDef = scda.getClass(((EVA) myAttribute).baseClassName);
          WDBObject baseObject;
          for (int i = 0; i < targetObjects.length; i++) {
            // See if we can remove it from our end first
            if (this.removeEvaObject((EVA) myAttribute, targetObjects[i], scda)) {
              // Get the object that belongs to the base class of the EVA
              if ((((EVA) myAttribute).baseClassName).equals(targetClassDef.name)) {
                baseObject = targetObjects[i];
              } else {
                baseObject =
                    targetObjects[i].getParentObject((((EVA) myAttribute).baseClassName), scda);
              }
              // Get the inverse EVA, if there is one
              Attribute inverseAttribute =
                  baseClassDef.getAttribute(((EVA) myAttribute).inverseEVA);
              // Put myself as a reference in the target's EVA
              if (inverseAttribute != null && inverseAttribute.getClass() == EVA.class) {
                baseObject.removeEvaObject((EVA) inverseAttribute, this, scda);
              } else {
                throw new Exception("Implication of target class inverse EVAs is not implemented");
              }
              // Update the object
              baseObject.commit(scda);
            }
          }
        }
      }
      // Not immediate, go check parents if I'm an object of a subclass
      else if (myClass.getClass() == SubclassDef.class) {
        Enumeration e = parents.keys();
        while (true) {
          try {
            String parentClass = (String) e.nextElement();
            Integer parentUid = (Integer) parents.get(parentClass);
            WDBObject parent = scda.getObject(parentClass, parentUid);

            parent.removeEvaObjects(evaName, targetClass, targetObjects, scda);
            // If we reached here, we set our value. Get out of here
            break;
          } catch (NoSuchFieldException nsfe) {
            // Can't find DVA going up that parent's heirarchy. Continue on to another parent
            if (!e.hasMoreElements()) {
              // No more parents to try. We are here if we exausted our parent's list and
              // still can't find the DVA. Throw exception
              throw nsfe;
            }
          }
        }
      }
      // value can't be found and I'm not a subclass. It doesn't exist in this heirarchy
      else {
        throw new NoSuchFieldException("Attribute \"" + evaName + "\" is not a valid EVA");
      }

      this.commit(scda);
    }
  }
 public ClassDef getClassDef(ParserAdapter scda) throws Exception {
   return scda.getClass(this.classDefName);
 }
 public void commit(ParserAdapter scda) throws Exception {
   scda.putObject(this);
 }