package org.kohsuke.bali.automaton.builder;
import java.util.HashMap;
import java.util.Map;
import javax.naming.NameClassPair;
import com.sun.msv.grammar.AnyNameClass;
import com.sun.msv.grammar.ChoiceNameClass;
import com.sun.msv.grammar.DifferenceNameClass;
import com.sun.msv.grammar.NameClass;
import com.sun.msv.grammar.NameClassVisitor;
import com.sun.msv.grammar.NamespaceNameClass;
import com.sun.msv.grammar.NotNameClass;
import com.sun.msv.grammar.SimpleNameClass;
import com.sun.msv.grammar.util.NameClassSimplifier;
import com.sun.msv.util.StringPair;
/**
* Unifies name class objects so that two equivalent name classes
* can be compared by referencial identitiy.
*
* The caller should use the <code>unify</code> method.
* Firstly, structual equivalence is guaranteed by the NameClassSimplifier,
* and then referencial equivalence is guaranteed by interning.
*
*
* @author Kohsuke Kawaguchi (kk@kohsuke.org)
*/
public class NameClassUnifier implements NameClassVisitor {
public NameClass unify( NameClass nc ) {
return (NameClass)NameClassSimplifier.simplify(nc).visit(this);
}
/** Pair of NameClasses. */
private static class NameClassPair {
public final NameClass lhs,rhs;
public NameClassPair( NameClass l, NameClass r ) {
this.lhs=l; this.rhs=r;
}
public int hashCode() { return lhs.hashCode()^rhs.hashCode(); }
public boolean equals( Object o ) {
return ((NameClassPair)o).rhs==rhs && ((NameClassPair)o).lhs==lhs;
}
}
private Map choices = new HashMap();
public Object onChoice(ChoiceNameClass nc) {
NameClassPair p = new NameClassPair( (NameClass)nc.nc1.visit(this), (NameClass)nc.nc2.visit(this) );
nc = (ChoiceNameClass)choices.get(p);
if(nc==null)
choices.put(p,nc=new ChoiceNameClass(p.lhs,p.rhs));
return nc;
}
public Object onAnyName(AnyNameClass nc) {
return AnyNameClass.theInstance;
}
private Map simples = new HashMap();
public Object onSimple(SimpleNameClass nc) {
StringPair p = new StringPair( nc.namespaceURI.intern(), nc.localName.intern() );
nc = (SimpleNameClass)simples.get(p);
if(nc==null)
simples.put(p,nc=new SimpleNameClass(p.namespaceURI,p.localName));
return nc;
}
private Map namespaces = new HashMap();
public Object onNsName(NamespaceNameClass nc) {
String ns = nc.namespaceURI.intern();
nc = (NamespaceNameClass)namespaces.get(ns);
if(nc==null)
namespaces.put(ns,nc=new NamespaceNameClass(ns));
return nc;
}
private Map nots = new HashMap();
public Object onNot(NotNameClass nc) {
NameClass n = (NameClass)nc.child.visit(this);
nc = (NotNameClass)nots.get(n);
if(nc==null)
nots.put(n,nc=new NotNameClass(n));
return nc;
}
private Map differences = new HashMap();
public Object onDifference(DifferenceNameClass nc) {
NameClassPair p = new NameClassPair( (NameClass)nc.nc1.visit(this), (NameClass)nc.nc2.visit(this) );
nc = (DifferenceNameClass)differences.get(p);
if(nc==null)
differences.put(p,nc=new DifferenceNameClass(p.lhs,p.rhs));
return nc;
}
}