system/src/sc/lang/SemanticNode.java
public void diffNode(Object other, StringBuilder diffs) {
      if (other == this)
         return;

      if (other == null) {
         diffAppend(diffs, "No other model for comparison against this: " + toString());
         return;
      }

      if (getClass() != other.getClass()) {
         diffAppend(diffs, "class mismatch - this: " + CTypeUtil.getClassName(getClass().getName()) + " = " + toString() + " other: " + CTypeUtil.getClassName(other.getClass().getName()) + " = " + other.toString());
         return;
      }

      DynType type = TypeUtil.getPropertyCache(getClass());
      IBeanMapper[] props = type.getSemanticPropertyList();
      for (int i = 0; i < props.length; i++) {
         Field field = (Field) props[i].getField();
         Object thisProp = PTypeUtil.getProperty(this, field, false);
         Object otherProp = PTypeUtil.getProperty(other, field, false);
         // If both are null it is ok.  If thisProp is not null it has to equal other prop to go on.
         if (thisProp != otherProp) {
            if (thisProp instanceof ISemanticNode && otherProp != null) {
               ISemanticNode thisPropNode = (ISemanticNode) thisProp;
               StringBuilder newDiffs = new StringBuilder();
               thisPropNode.diffNode(otherProp, newDiffs);
               if (newDiffs.length() != 0) {
                  diffAppend(diffs, field.getName());
                  diffAppend(diffs, "->");
                  diffAppend(diffs, newDiffs);
               }
               else if (!thisPropNode.deepEquals(otherProp)) {
                  diffAppend(diffs, CTypeUtil.getClassName(getClass().getName()) + "." + field.getName() + " = " + thisProp + " other's = " + otherProp);
                  diffAppend(diffs, FileUtil.LINE_SEPARATOR);
               }
            }
            else if (thisProp == null || otherProp == null || !thisProp.equals(otherProp)) {
               diffAppend(diffs, CTypeUtil.getClassName(getClass().getName()) + "." + field.getName() + " = " + thisProp + " other's = " + otherProp);
            }
         }
      }
   }
/**
    * The semantic node classes are treated like value classes - they are equal if all of their properties
    * are equal.
    */
The semantic node classes are treated like value classes - they are equal if all of their properties
are equal.
The semantic node classes are treated like value classes - they are equal if all of their properties are equal .
public void diffNode(Object other, StringBuilder diffs) {
      if (other == this)
         return;
      if (other == null) {
         diffAppend(diffs, "No other model for comparison against this: " + toString());
         return;
      }
      if (getClass() != other.getClass()) {
         diffAppend(diffs, "class mismatch - this: " + CTypeUtil.getClassName(getClass().getName()) + " = " + toString() + " other: " + CTypeUtil.getClassName(other.getClass().getName()) + " = " + other.toString());
         return;
      }
      DynType type = TypeUtil.getPropertyCache(getClass());
      IBeanMapper[] props = type.getSemanticPropertyList();
      for (int i = 0; i < props.length; i++) {
         Field field = (Field) props[i].getField();
         Object thisProp = PTypeUtil.getProperty(this, field, false);
         Object otherProp = PTypeUtil.getProperty(other, field, false);
         if (thisProp != otherProp) {
            if (thisProp instanceof ISemanticNode && otherProp != null) {
               ISemanticNode thisPropNode = (ISemanticNode) thisProp;
               StringBuilder newDiffs = new StringBuilder();
               thisPropNode.diffNode(otherProp, newDiffs);
               if (newDiffs.length() != 0) {
                  diffAppend(diffs, field.getName());
                  diffAppend(diffs, "->");
                  diffAppend(diffs, newDiffs);
               }
               else if (!thisPropNode.deepEquals(otherProp)) {
                  diffAppend(diffs, CTypeUtil.getClassName(getClass().getName()) + "." + field.getName() + " = " + thisProp + " other's = " + otherProp);
                  diffAppend(diffs, FileUtil.LINE_SEPARATOR);
               }
            }
            else if (thisProp == null || otherProp == null || !thisProp.equals(otherProp)) {
               diffAppend(diffs, CTypeUtil.getClassName(getClass().getName()) + "." + field.getName() + " = " + thisProp + " other's = " + otherProp);
            }
         }
      }
   }
public void diffNode ( Object other , StringBuilder diffs ) { if ( other == this ) return ; if ( other == null ) { diffAppend ( diffs , "No other model for comparison against this: " + toString ( ) ) ; return ; } if ( getClass ( ) != other . getClass ( ) ) { diffAppend ( diffs , "class mismatch - this: " + CTypeUtil . getClassName ( getClass ( ) . getName ( ) ) + " = " + toString ( ) + " other: " + CTypeUtil . getClassName ( other . getClass ( ) . getName ( ) ) + " = " + other . toString ( ) ) ; return ; } DynType type = TypeUtil . getPropertyCache ( getClass ( ) ) ; IBeanMapper [ ] props = type . getSemanticPropertyList ( ) ; for ( int i = 0 ; i < props . length ; i ++ ) { Field field = ( Field ) props [ i ] . getField ( ) ; Object thisProp = PTypeUtil . getProperty ( this , field , false ) ; Object otherProp = PTypeUtil . getProperty ( other , field , false ) ; if ( thisProp != otherProp ) { if ( thisProp instanceof ISemanticNode && otherProp != null ) { ISemanticNode thisPropNode = ( ISemanticNode ) thisProp ; StringBuilder newDiffs = new StringBuilder ( ) ; thisPropNode . diffNode ( otherProp , newDiffs ) ; if ( newDiffs . length ( ) != 0 ) { diffAppend ( diffs , field . getName ( ) ) ; diffAppend ( diffs , "->" ) ; diffAppend ( diffs , newDiffs ) ; } else if ( ! thisPropNode . deepEquals ( otherProp ) ) { diffAppend ( diffs , CTypeUtil . getClassName ( getClass ( ) . getName ( ) ) + "." + field . getName ( ) + " = " + thisProp + " other's = " + otherProp ) ; diffAppend ( diffs , FileUtil . LINE_SEPARATOR ) ; } } else if ( thisProp == null || otherProp == null || ! thisProp . equals ( otherProp ) ) { diffAppend ( diffs , CTypeUtil . getClassName ( getClass ( ) . getName ( ) ) + "." + field . getName ( ) + " = " + thisProp + " other's = " + otherProp ) ; } } } }
The semantic node classes are treated like value classes - they are equal if all of their properties
 are equal.
The semantic node classes are treated like value classes - they are equal if all of their properties are equal .
// If both are null it is ok.  If thisProp is not null it has to equal other prop to go on.