Well I've been mentioning it for a while but haven't had time to set it up,
but I've attached my xml comparator.  You give it 2 nodes and it gives you
back an element listing the differences with navigation info.  I didn't
know xpath when I wrote it, which might be a better way of showing where
the differences are.  

If it saves someone a few hours writing something, great, if it's not
appropriate, that's fine too.

Thanks
david jencks

On 2002.02.25 01:28:04 -0500 Ara Abrahamian wrote:
> > I am very inexperienced with threads, so I would never have spotted
> the
> > deadlock by just reading the code.
> > Did you "see" it or did you experience the deadlock, Konstantin? If
> you
> > saw
> > it, Im really impressed, because
> > I have tried to understand threads for a very long time, and I never
> seem
> > to
> > get it completely.
> 
> I experienced it in classdump. Classdump is a good and realistic test!
> Btw, it hangs when a syntax error is reported by javacc!! I think we
> need to take a look at javacc's error handling docs :-)
> 
> > Anyway, we're now three active committers on xjavadoc, and that's good
> for
> > time-to-market. I'm still baffled with
> > the multithreading approach Ara came up with. I only implementeded it.
> By
> > now it seems to me you're both very much
> > up to speed with xjavadoc's under the hood workings. Isn't JavaCC
> great?
> 
> Absolutely!
> 
> > One way to solve it is to provide two different parsers, one with
> unicode
> > enabled and one without. Can be achieved
> > by preprocessing the grammar with XDoclet's ReplaceCopy task (see
> samples)
> > and generate parser into two different
> > packages. Then we can add a -unicode runtime flag which indicates
> which
> > one
> > to use.
> 
> Agree but you're talking about how much performance decrease?!
> 
> > 2) Class resolving. I have experienced some problems if a class
> imports
> > both
> > a package (say foo.bar.*) and also
> > a class in the same package (say foo.bar.Grunt), because of ambiguity.
> I
> > have solved this temporarily by juggling
> > in SourceClass.qualify(). -But we should verify with the java language
> > spec
> > to see what the exact semantics are.
> 
> Yup, I guess it'll fail because we find two classes in two tests and we
> don't check if it's the already found one! Very easy to fix.
> 
> > 3) Trailing ; (semicolons). Many sources have kinda this:
> > public abstract Foo bar();;
> > or
> > public Foo bar() {};
> > or something like that..
> > 
> > The issue is that this is wrong according to the language spec, but
> both
> > javac and javadoc accepts it, and therefore
> > there will always be some sources around that uses it. If there is an
> easy
> > way (which doesn't degrade persformance)
> > to make the grammar accept it, we'll support it. Otherwise not. It's
> not
> > hard for people to remove some semicolons
> > as long as xjavadoc reports where the problem is (it does). -But you
> > should
> > be aware of it, because it will happen if you
> > run xjavadoc on large sources like Ant or Xalan.
> 
> Isn't it a matter of a (SEMICOLON)* after each block?
> 
> > 4) We should design a little class hierarchy with as many oddities as
> > possible and use that as test data for our
> > JUnit tests. The Hello alone is no good, neither are the xdoclet
> samples.
> > They're too ordinary. What we need to test
> > especially is:
> > -javadocs in front of methods/classes with/without modifiers (Because
> as
> > far
> > as the parser is concerned, the modifier/no modifier
> > situations are treated differently).
> > -tricky import ambiguities (as described above).
> > -nested inner classes.
> > -anonymous inner classes.
> > -references to nonexisting classes (like there is a lot of when you
> use
> > xdoclet).
> > -modifying docs (on methods/classes with/without modifiers) and saving
> > them.
> 
> Concentrate on xdoclet's usage scenarios for the time being :-)
> 
> > -reading back the modified and saved classes and do asserts in junit
> test.
> > -adding docs to undocumented classes/methods, both with and without
> > modifiers
> > -verify that we don't have any more deadlocks/race conditions.
> > -verify that the tag parameter stuff works properly for read,update
> and
> > delete (update should do an add if the tag doesn't exist)
> > -verify that doc indentation is aligned with the class or method when
> > saving
> > (must do this manually)
> > -do all the above that applies to fields and methods too.
> > -test if sources with unicode escapes work properly.
> > -this list (plus your additions) should be in the header of the
> > XJavaDocTest
> > class(es), so we can mark whether the tests are implemented or not)
> > -the test hierarchy should of course compile, and the junit target
> shoul
> > depend on them being compiled.
> 
> This is a great summary of various ambiguous cases, you've thought about
> it deeply!
> 
> Since plugging it in xdoclet is a major project itself we should handle
> "Doclet API compatibility test" with testing for equal results with
> Sun's API. What you guys think about a XML outputer for both Sun's API
> and ours and check for their equality? I believe it'll be useful for
> other cases too, we can use the xml equality code for testing
> ejb-jar.xml and other xmls for example.
> 
> > One other idea I have is to write a javadoc doclet which scans a big
> > source
> > tree and generates JUnit test classes (using xdoclet's
> > template engine.) This is a good way to test if xjavadoc works the
> same
> > way
> > as javadoc. This shouldn't be too hard to do, and it
> > would make us really sure that xjavadoc is ready for action.
> 
> "generates JUnit test classes"? I don't get it.
> 
> > I'll be very busy this week, and won't be able to do much, and the
> week
> > after I'm on holiday (skiing in switzerland, yohoo),
> 
> Have fun ;-)
> 
> > so I hope you can start on some of this. I'll leave it up to you to
> > prioritise the items and assign them among us. This
> > should really be added to the SF tracker under xjavadoc, but I don't
> have
> > time to do that now.
> 
> Yup. Konstantin, what's your schedule? What you're interested in?
> 
> Ara.
> 
> 
> 
> _______________________________________________
> Xdoclet-devel mailing list
> [EMAIL PROTECTED]
> https://lists.sourceforge.net/lists/listinfo/xdoclet-devel
> 
> 
package xdoclet;

import java.io.*;
//import java.text.NumberFormat;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
/**
 * @author    David Jencks ([EMAIL PROTECTED])
 * @created   February 25, 2002
 * @see       <related>
 * @version   $ $
 */

public class XMLComparator
{

	Stack              refStack = new Stack();
	Stack              compStack = new Stack();
	Document           doc = null;
	Element            diffs = null;

	public XMLComparator( Document doc )
	{
		this.doc = doc;
	}

	private static boolean valueDiffers( String r, String c )
	{
		if( r == null && c == null )
		{
			return false;
		}
		if( r != null && c != null )
		{
			return !r.equals( c );
		}
		return true;
	}

	private static Node skipEmpty( Node node )
	{
		Node n = node;

		while( n != null && !nodeHasContentOrAttributes( n ) )
		{
			n = n.getNextSibling();
		}
		return n;
	}

	private static boolean nodeHasContentOrAttributes( Node n )
	{
		if( n == null )
		{
			return false;
		}
		if( n.getNodeValue() != null && !n.getNodeValue().trim().equals( "" ) )
		{
			return true;
		}

		NamedNodeMap AttList = n.getAttributes();

		if( AttList != null && AttList.getLength() > 0 )
		{
			return true;
		}

		Node c = n.getFirstChild();

		while( c != null )
		{
			if( nodeHasContentOrAttributes( c ) )
			{
				return true;
			}
			c = c.getNextSibling();
		}
		return false;
	}

	public Element compare( Node reference, Node comp )
	{
		diffs = doc.createElement( "diffs" );
		compare( reference, comp, new Counter() );
		return diffs;
	}

	private void compare( Node reference, Node comp, Counter c )
	{
		if( reference == null )
		{
			if( comp == null )
			{
				return;
			}
			else
			{
				logDifference( "null reference node unmatched" );
				return;
			}
		}
		if( comp == null )
		{
			logDifference( "null comparison node unmatched" );
			return;
		}
		if( reference instanceof Element )
		{
			refStack.push( ( ( Element ) reference ).getTagName() + c.incRefCount() );
		}
		if( comp instanceof Element )
		{
			compStack.push( ( ( Element ) comp ).getTagName() + c.incCompCount() );
		}
		if( valueDiffers( reference.getNodeValue(), comp.getNodeValue() ) )
		{
			logDifference( "Mismatch, reference : " + reference.getNodeValue() +
				" differs from new: " + comp.getNodeValue() );
		}

		NamedNodeMap refAttList = reference.getAttributes();
		NamedNodeMap compAttList = comp.getAttributes();
		int refAttListLength = ( refAttList == null ) ? 0 : refAttList.getLength();
		int compAttListLength = ( compAttList == null ) ? 0 : compAttList.getLength();

		if( refAttListLength != compAttListLength )
		{
			logDifference( "Differing attribute count, reference : " + refAttListLength +
				" differs from new: " + compAttListLength );
		}
		for( int i = 0; i < Math.min( refAttListLength, compAttListLength ); i++ )
		{
			compare( refAttList.item( i ), compAttList.item( i ), c );
		}

		Node refChild = skipEmpty( reference.getFirstChild() );
		Node compChild = skipEmpty( comp.getFirstChild() );
		Counter subC = new Counter();

		while( refChild != null && compChild != null )
		{
			compare( refChild, compChild, subC );
			refChild = skipEmpty( refChild.getNextSibling() );
			compChild = skipEmpty( compChild.getNextSibling() );
		}
		//check for leftovers
		while( refChild != null )
		{
			logDifference( "unmatched reference : " + refChild.getNodeValue() );
			refChild = skipEmpty( refChild.getNextSibling() );
		}
		while( compChild != null )
		{
			logDifference( "unmatched compare : " + compChild.getNodeValue() );
			compChild = skipEmpty( compChild.getNextSibling() );
		}

		if( reference instanceof Element )
		{
			refStack.pop();
		}
		if( comp instanceof Element )
		{
			compStack.pop();
		}
	}

	private void logDifference( String message )
	{
		Element diff = doc.createElement( "diff" );

		diff.setAttribute( "reference", refStack.toString() );
		diff.setAttribute( "compare", compStack.toString() );
		diff.appendChild( doc.createTextNode( message ) );
		diffs.appendChild( diff );
	}

	/**
	 * @created   February 25, 2002
	 */
	private class Counter
	{
		private int       refCount = 0;
		private int       compCount = 0;
		int incRefCount()
		{
			return ++refCount;
		}
		int incCompCount()
		{
			return ++compCount;
		}
	}

}

Reply via email to