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;
}
}
}