static public VoltXMLDiff computeDiff ( VoltXMLElement before , VoltXMLElement after ) { // Top level call needs both names to match (I think this makes sense) if ( ! before . getUniqueName ( ) . equals ( after . getUniqueName ( ) ) ) { // not sure this is best behavior, ponder as progress is made return null ; } VoltXMLDiff result = new VoltXMLDiff ( before . getUniqueName ( ) ) ; // Short-circuit check for any differences first. Can return early if there are no changes if ( before . toMinString ( ) . equals ( after . toMinString ( ) ) ) { return result ; } // Store the final desired element order for ( int i = 0 ; i < after . children . size ( ) ; i ++ ) { VoltXMLElement child = after . children . get ( i ) ; result . m_elementOrder . put ( child . getUniqueName ( ) , i ) ; } // first, check the attributes Set < String > firstKeys = before . attributes . keySet ( ) ; Set < String > secondKeys = new HashSet <> ( ) ; secondKeys . addAll ( after . attributes . keySet ( ) ) ; // Do removed and changed attributes walking the first element's attributes for ( String firstKey : firstKeys ) { if ( ! secondKeys . contains ( firstKey ) ) { result . m_removedAttributes . add ( firstKey ) ; } else if ( ! ( after . attributes . get ( firstKey ) . equals ( before . attributes . get ( firstKey ) ) ) ) { result . m_changedAttributes . put ( firstKey , after . attributes . get ( firstKey ) ) ; } // remove the firstKey from secondKeys to track things added secondKeys . remove ( firstKey ) ; } // everything in secondKeys should be something added for ( String key : secondKeys ) { result . m_addedAttributes . put ( key , after . attributes . get ( key ) ) ; } // Now, need to check the children. Each pair of children with the same names // need to be descended to look for changes // Probably more efficient ways to do this, but brute force it for now // Would be helpful if the underlying children objects were Maps rather than // Lists. Set < String > firstChildren = new HashSet <> ( ) ; for ( VoltXMLElement child : before . children ) { firstChildren . add ( child . getUniqueName ( ) ) ; } Set < String > secondChildren = new HashSet <> ( ) ; for ( VoltXMLElement child : after . children ) { secondChildren . add ( child . getUniqueName ( ) ) ; } Set < String > commonNames = new HashSet <> ( ) ; for ( VoltXMLElement firstChild : before . children ) { if ( ! secondChildren . contains ( firstChild . getUniqueName ( ) ) ) { // Need to duplicate the result . m_removedElements . add ( firstChild ) ; } else { commonNames . add ( firstChild . getUniqueName ( ) ) ; } } for ( VoltXMLElement secondChild : after . children ) { if ( ! firstChildren . contains ( secondChild . getUniqueName ( ) ) ) { result . m_addedElements . add ( secondChild ) ; } else { assert ( commonNames . contains ( secondChild . getUniqueName ( ) ) ) ; } } // This set contains uniquenames for ( String name : commonNames ) { VoltXMLDiff childDiff = computeDiff ( before . findChild ( name ) , after . findChild ( name ) ) ; if ( ! childDiff . isEmpty ( ) ) { result . m_changedElements . put ( name , childDiff ) ; } } return result ; }
Compute the diff necessary to turn the before tree into the after tree .