001 package com.thaiopensource.relaxng.impl;
002
003 import java.util.Hashtable;
004
005 public class ValidatorPatternBuilder extends PatternBuilder {
006 private final Hashtable patternMemoMap = new Hashtable();
007 private final PatternFunction endAttributesFunction;
008 private final PatternFunction ignoreMissingAttributesFunction;
009 private final PatternFunction endTagDerivFunction;
010 private final PatternFunction mixedTextDerivFunction;
011 private final PatternFunction textOnlyFunction;
012 private final PatternFunction recoverAfterFunction;
013 private final PatternFunction dataDerivTypeFunction;
014
015 private final Hashtable choiceMap = new Hashtable();
016 private final PatternFunction removeChoicesFunction = new RemoveChoicesFunction();
017 private final PatternFunction noteChoicesFunction = new NoteChoicesFunction();
018
019 private class NoteChoicesFunction extends AbstractPatternFunction {
020 public Object caseOther(Pattern p) {
021 choiceMap.put(p, p);
022 return null;
023 }
024
025 public Object caseChoice(ChoicePattern p) {
026 p.getOperand1().apply(this);
027 p.getOperand2().apply(this);
028 return null;
029 }
030 }
031
032 private class RemoveChoicesFunction extends AbstractPatternFunction {
033 public Object caseOther(Pattern p) {
034 if (choiceMap.get(p) != null)
035 return notAllowed;
036 return p;
037 }
038
039 public Object caseChoice(ChoicePattern p) {
040 Pattern p1 = p.getOperand1().applyForPattern(this);
041 Pattern p2 = p.getOperand2().applyForPattern(this);
042 if (p1 == p.getOperand1() && p2 == p.getOperand2())
043 return p;
044 if (p1 == notAllowed)
045 return p2;
046 if (p2 == notAllowed)
047 return p1;
048 Pattern p3 = new ChoicePattern(p1, p2);
049 return interner.intern(p3);
050 }
051 }
052
053 public ValidatorPatternBuilder(PatternBuilder builder) {
054 super(builder);
055 endAttributesFunction = new EndAttributesFunction(this);
056 ignoreMissingAttributesFunction = new IgnoreMissingAttributesFunction(this);
057 endTagDerivFunction = new EndTagDerivFunction(this);
058 mixedTextDerivFunction = new MixedTextDerivFunction(this);
059 textOnlyFunction = new TextOnlyFunction(this);
060 recoverAfterFunction = new RecoverAfterFunction(this);
061 dataDerivTypeFunction = new DataDerivTypeFunction(this);
062 }
063
064 PatternMemo getPatternMemo(Pattern p) {
065 PatternMemo memo = (PatternMemo)patternMemoMap.get(p);
066 if (memo == null) {
067 memo = new PatternMemo(p, this);
068 patternMemoMap.put(p, memo);
069 }
070 return memo;
071 }
072
073 PatternFunction getEndAttributesFunction() {
074 return endAttributesFunction;
075 }
076
077 PatternFunction getIgnoreMissingAttributesFunction() {
078 return ignoreMissingAttributesFunction;
079 }
080
081 PatternFunction getEndTagDerivFunction() {
082 return endTagDerivFunction;
083 }
084
085 PatternFunction getMixedTextDerivFunction() {
086 return mixedTextDerivFunction;
087 }
088
089 PatternFunction getTextOnlyFunction() {
090 return textOnlyFunction;
091 }
092
093 PatternFunction getRecoverAfterFunction() {
094 return recoverAfterFunction;
095 }
096
097 PatternFunction getDataDerivTypeFunction() {
098 return dataDerivTypeFunction;
099 }
100
101 Pattern makeAfter(Pattern p1, Pattern p2) {
102 Pattern p = new AfterPattern(p1, p2);
103 return interner.intern(p);
104 }
105
106 Pattern makeChoice(Pattern p1, Pattern p2) {
107 if (p1 == p2)
108 return p1;
109 if (p1 == notAllowed)
110 return p2;
111 if (p2 == notAllowed)
112 return p1;
113 if (!(p1 instanceof ChoicePattern)) {
114 if (p2.containsChoice(p1))
115 return p2;
116 }
117 else if (!(p2 instanceof ChoicePattern)) {
118 if (p1.containsChoice(p2))
119 return p1;
120 }
121 else {
122 p1.apply(noteChoicesFunction);
123 p2 = p2.applyForPattern(removeChoicesFunction);
124 if (choiceMap.size() > 0)
125 choiceMap.clear();
126 }
127 if (p1 instanceof AfterPattern && p2 instanceof AfterPattern) {
128 AfterPattern ap1 = (AfterPattern)p1;
129 AfterPattern ap2 = (AfterPattern)p2;
130 if (ap1.getOperand1() == ap2.getOperand1())
131 return makeAfter(ap1.getOperand1(), makeChoice(ap1.getOperand2(), ap2.getOperand2()));
132 if (ap1.getOperand1() == notAllowed)
133 return ap2;
134 if (ap2.getOperand1() == notAllowed)
135 return ap1;
136 if (ap1.getOperand2() == ap2.getOperand2())
137 return makeAfter(makeChoice(ap1.getOperand1(), ap2.getOperand1()), ap1.getOperand2());
138 }
139 return super.makeChoice(p1, p2);
140 }
141 }