system/src/sc/lang/html/Element.java
private SemanticNodeList<Object> addChildren(Element parentElement, Element derivedElement, SemanticNodeList<Object> res, boolean unique, boolean iface, boolean canInherit, AddChildResult childRes) {
      if (derivedElement == this) {
         System.out.println("*** Error - invalid recursive element tree!");
         derivedElement = null;
      }
      SemanticNodeList<Object> derivedChildren = derivedElement == null ? null : derivedElement.getChildren(false, true); // Get all inherited children - when we have to reorder, it's all or nothing.

      boolean needsSort = false;

      if (canInherit) {
         // TODO: this can be optimized so that we use inheritance unless the sort order of the parent elements changes in this element.
         needsSort = getNeedsSort(children);
         if (!needsSort && derivedChildren != null) {
            needsSort = getNeedsSort(derivedChildren);
         }
         if (needsSort)
            canInherit = false;
      }

      MergeMode bodyMerge = getBodyMergeMode();

      if (bodyMerge == MergeMode.Replace) {
         // When not self-closed, replace with an empty method by creating an empty list rather than null signalling that we do not have any unique children.
         // when self-closed, just replace the attributes, not the body, like an annotation tag, for example to reorder an existing element.
         if (children == null && !selfClosed()) {
            res = new SemanticNodeList<Object>();
            res.parentNode = parentElement;
            childRes.needsSuper = false;
            childRes.needsBody = true;
            return res;
         }
         childRes.needsSuper = false;
         childRes.needsBody = children != null;
         return children;
      }
      else if (bodyMerge == MergeMode.Merge) {
         // look for children which do not match one of those in the parent type
         childRes.needsSuper = derivedElement != null && canInherit;
         childRes.needsBody = childRes.needsBody || children != null || (derivedElement != null && !derivedElement.isEmptyBody());
         if (!canInherit && derivedChildren != null) {
            if (res == null) {
               res = new SemanticNodeList<Object>();
               res.parentNode = parentElement;
            }
            addDerivedChildren(res, derivedChildren);
         }
         if (children != null) {
            for (Object child:children) {
               if (!(child instanceof Element)) {
                  if (res == null) {
                     res = new SemanticNodeList<Object>();
                     res.parentNode = parentElement;
                     if (!unique) {
                        addDerivedChildren(res, derivedChildren);
                     }
                  }
                  res.add(child);
               }
               else {
                  // This element may not be derived in the type hierarchy if it's 'replace=true' so getDerivedElement will not work.  Still that should not count as a unique child since we are replacing a previous object
                  Element childElement = (Element) child;
                  int childElementIx = -1;
                  // This is the logic which determines whether we by default 'merge' a child tag with the previous version or append it.  For simple content tags, we should
                  // not ever merge because content tags just get appended. Thinking we might have some logic which says we only merge singleton tags (body, and head) or tags with
                  // an explicit id.
                  // Using needsObjectDef here, not needsObject because otherwise we initialize the extends type too soon as part of execOmitObject() which calls getDefinedExecFlags.
                  if (childElement.needsObjectDef() || childElement.isSingletonTag())
                     childElementIx = findChildInList(derivedChildren, childElement.getRawObjectName());
                  // If this is a new piece of static content, non dynamic element, or an element which did not match for whatever reason it's derived element.
                  if (childElementIx == -1) {
                     if (res == null) {
                        res = new SemanticNodeList<Object>();
                        res.parentNode = parentElement;
                        if (!unique) {
                           addDerivedChildren(res, derivedChildren);
                        }
                     }
                     res.add(childElement); // Do not copy because this child is part of children already
                  }
                  else if (!canInherit) {
                     // Since we've already copied the derived elements into res in the non-inherit case, need to replace the derived element's child with the overriding element's child
                     res.set(childElementIx, childElement);
                  }
               }
            }
            if (!unique && res == null) {
               return derivedChildren;
            }
         }
         else {
            if (unique && !iface && canInherit)
               res = null;
            else
               res = derivedChildren;
         }
         if (iface)
            res = cloneChildren(res);
         if (needsSort) {
            sortChildren(res);
         }
         return res;
      }
      if (unique && canInherit) {
         // bodyMerge == Prepend or Append: we are not merging the children, always include all of them.
         return children;  // I don't see any reason to sort a single list right?
      }
      else {
         res = new SemanticNodeList<Object>();
         res.parentNode = parentElement;
         if (bodyMerge == MergeMode.Prepend) {
            if (children != null)
               res.addAll(children);
            addDerivedChildren(res, derivedChildren);
         }
         else if (bodyMerge == MergeMode.Append) {
            addDerivedChildren(res, derivedChildren);
            if (children != null)
               res.addAll(children);
         }
         if (needsSort)
            sortChildren(res);
         return res;
      }
   }
/** Utility method to add the children from the current element to the list of children from the derivedElement.
    * When unique is true, only the unique items are returned.  This will == children or null if we can inherit the base types outputBody method.
    * When unique is false, all items for the given element are returned, included those that are inherited.
    */
Utility method to add the children from the current element to the list of children from the derivedElement.
When unique is true, only the unique items are returned.  This will == children or null if we can inherit the base types outputBody method.
When unique is false, all items for the given element are returned, included those that are inherited.
Utility method to add the children from the current element to the list of children from the derivedElement . When unique is true only the unique items are returned . This will == children or null if we can inherit the base types outputBody method . When unique is false all items for the given element are returned included those that are inherited .
private SemanticNodeList<Object> addChildren(Element parentElement, Element derivedElement, SemanticNodeList<Object> res, boolean unique, boolean iface, boolean canInherit, AddChildResult childRes) {
      if (derivedElement == this) {
         System.out.println("*** Error - invalid recursive element tree!");
         derivedElement = null;
      }
      SemanticNodeList<Object> derivedChildren = derivedElement == null ? null : derivedElement.getChildren(false, true); 
      boolean needsSort = false;
      if (canInherit) {
         needsSort = getNeedsSort(children);
         if (!needsSort && derivedChildren != null) {
            needsSort = getNeedsSort(derivedChildren);
         }
         if (needsSort)
            canInherit = false;
      }
      MergeMode bodyMerge = getBodyMergeMode();
      if (bodyMerge == MergeMode.Replace) {
         if (children == null && !selfClosed()) {
            res = new SemanticNodeList<Object>();
            res.parentNode = parentElement;
            childRes.needsSuper = false;
            childRes.needsBody = true;
            return res;
         }
         childRes.needsSuper = false;
         childRes.needsBody = children != null;
         return children;
      }
      else if (bodyMerge == MergeMode.Merge) {
         childRes.needsSuper = derivedElement != null && canInherit;
         childRes.needsBody = childRes.needsBody || children != null || (derivedElement != null && !derivedElement.isEmptyBody());
         if (!canInherit && derivedChildren != null) {
            if (res == null) {
               res = new SemanticNodeList<Object>();
               res.parentNode = parentElement;
            }
            addDerivedChildren(res, derivedChildren);
         }
         if (children != null) {
            for (Object child:children) {
               if (!(child instanceof Element)) {
                  if (res == null) {
                     res = new SemanticNodeList<Object>();
                     res.parentNode = parentElement;
                     if (!unique) {
                        addDerivedChildren(res, derivedChildren);
                     }
                  }
                  res.add(child);
               }
               else {
                  Element childElement = (Element) child;
                  int childElementIx = -1;
                  if (childElement.needsObjectDef() || childElement.isSingletonTag())
                     childElementIx = findChildInList(derivedChildren, childElement.getRawObjectName());
                  if (childElementIx == -1) {
                     if (res == null) {
                        res = new SemanticNodeList<Object>();
                        res.parentNode = parentElement;
                        if (!unique) {
                           addDerivedChildren(res, derivedChildren);
                        }
                     }
                     res.add(childElement); 
                  }
                  else if (!canInherit) {
                     res.set(childElementIx, childElement);
                  }
               }
            }
            if (!unique && res == null) {
               return derivedChildren;
            }
         }
         else {
            if (unique && !iface && canInherit)
               res = null;
            else
               res = derivedChildren;
         }
         if (iface)
            res = cloneChildren(res);
         if (needsSort) {
            sortChildren(res);
         }
         return res;
      }
      if (unique && canInherit) {
         return children;  
      }
      else {
         res = new SemanticNodeList<Object>();
         res.parentNode = parentElement;
         if (bodyMerge == MergeMode.Prepend) {
            if (children != null)
               res.addAll(children);
            addDerivedChildren(res, derivedChildren);
         }
         else if (bodyMerge == MergeMode.Append) {
            addDerivedChildren(res, derivedChildren);
            if (children != null)
               res.addAll(children);
         }
         if (needsSort)
            sortChildren(res);
         return res;
      }
   }
private SemanticNodeList < Object > addChildren ( Element parentElement , Element derivedElement , SemanticNodeList < Object > res , boolean unique , boolean iface , boolean canInherit , AddChildResult childRes ) { if ( derivedElement == this ) { System . out . println ( "*** Error - invalid recursive element tree!" ) ; derivedElement = null ; } SemanticNodeList < Object > derivedChildren = derivedElement == null ? null : derivedElement . getChildren ( false , true ) ; boolean needsSort = false ; if ( canInherit ) { needsSort = getNeedsSort ( children ) ; if ( ! needsSort && derivedChildren != null ) { needsSort = getNeedsSort ( derivedChildren ) ; } if ( needsSort ) canInherit = false ; } MergeMode bodyMerge = getBodyMergeMode ( ) ; if ( bodyMerge == MergeMode . Replace ) { if ( children == null && ! selfClosed ( ) ) { res = new SemanticNodeList < Object > ( ) ; res . parentNode = parentElement ; childRes . needsSuper = false ; childRes . needsBody = true ; return res ; } childRes . needsSuper = false ; childRes . needsBody = children != null ; return children ; } else if ( bodyMerge == MergeMode . Merge ) { childRes . needsSuper = derivedElement != null && canInherit ; childRes . needsBody = childRes . needsBody || children != null || ( derivedElement != null && ! derivedElement . isEmptyBody ( ) ) ; if ( ! canInherit && derivedChildren != null ) { if ( res == null ) { res = new SemanticNodeList < Object > ( ) ; res . parentNode = parentElement ; } addDerivedChildren ( res , derivedChildren ) ; } if ( children != null ) { for ( Object child : children ) { if ( ! ( child instanceof Element ) ) { if ( res == null ) { res = new SemanticNodeList < Object > ( ) ; res . parentNode = parentElement ; if ( ! unique ) { addDerivedChildren ( res , derivedChildren ) ; } } res . add ( child ) ; } else { Element childElement = ( Element ) child ; int childElementIx = - 1 ; if ( childElement . needsObjectDef ( ) || childElement . isSingletonTag ( ) ) childElementIx = findChildInList ( derivedChildren , childElement . getRawObjectName ( ) ) ; if ( childElementIx == - 1 ) { if ( res == null ) { res = new SemanticNodeList < Object > ( ) ; res . parentNode = parentElement ; if ( ! unique ) { addDerivedChildren ( res , derivedChildren ) ; } } res . add ( childElement ) ; } else if ( ! canInherit ) { res . set ( childElementIx , childElement ) ; } } } if ( ! unique && res == null ) { return derivedChildren ; } } else { if ( unique && ! iface && canInherit ) res = null ; else res = derivedChildren ; } if ( iface ) res = cloneChildren ( res ) ; if ( needsSort ) { sortChildren ( res ) ; } return res ; } if ( unique && canInherit ) { return children ; } else { res = new SemanticNodeList < Object > ( ) ; res . parentNode = parentElement ; if ( bodyMerge == MergeMode . Prepend ) { if ( children != null ) res . addAll ( children ) ; addDerivedChildren ( res , derivedChildren ) ; } else if ( bodyMerge == MergeMode . Append ) { addDerivedChildren ( res , derivedChildren ) ; if ( children != null ) res . addAll ( children ) ; } if ( needsSort ) sortChildren ( res ) ; return res ; } }
Utility method to add the children from the current element to the list of children from the derivedElement.
Utility method to add the children from the current element to the list of children from the derivedElement .
// Get all inherited children - when we have to reorder, it's all or nothing. // TODO: this can be optimized so that we use inheritance unless the sort order of the parent elements changes in this element. // When not self-closed, replace with an empty method by creating an empty list rather than null signalling that we do not have any unique children. // when self-closed, just replace the attributes, not the body, like an annotation tag, for example to reorder an existing element. // look for children which do not match one of those in the parent type // This element may not be derived in the type hierarchy if it's 'replace=true' so getDerivedElement will not work.  Still that should not count as a unique child since we are replacing a previous object // This is the logic which determines whether we by default 'merge' a child tag with the previous version or append it.  For simple content tags, we should // not ever merge because content tags just get appended. Thinking we might have some logic which says we only merge singleton tags (body, and head) or tags with // an explicit id. // Using needsObjectDef here, not needsObject because otherwise we initialize the extends type too soon as part of execOmitObject() which calls getDefinedExecFlags. // If this is a new piece of static content, non dynamic element, or an element which did not match for whatever reason it's derived element. // Do not copy because this child is part of children already // Since we've already copied the derived elements into res in the non-inherit case, need to replace the derived element's child with the overriding element's child // bodyMerge == Prepend or Append: we are not merging the children, always include all of them. // I don't see any reason to sort a single list right?