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 }