001 package com.thaiopensource.relaxng.impl;
002
003 public class PatternBuilder {
004 private final EmptyPattern empty;
005 protected final NotAllowedPattern notAllowed;
006 protected final PatternInterner interner;
007
008 public PatternBuilder() {
009 empty = new EmptyPattern();
010 notAllowed = new NotAllowedPattern();
011 interner = new PatternInterner();
012 }
013
014 public PatternBuilder(PatternBuilder parent) {
015 empty = parent.empty;
016 notAllowed = parent.notAllowed;
017 interner = new PatternInterner(parent.interner);
018 }
019
020 Pattern makeEmpty() {
021 return empty;
022 }
023
024 Pattern makeNotAllowed() {
025 return notAllowed;
026 }
027
028 Pattern makeGroup(Pattern p1, Pattern p2) {
029 if (p1 == empty)
030 return p2;
031 if (p2 == empty)
032 return p1;
033 if (p1 == notAllowed || p2 == notAllowed)
034 return notAllowed;
035 if (false && p1 instanceof GroupPattern) {
036 GroupPattern sp = (GroupPattern)p1;
037 return makeGroup(sp.p1, makeGroup(sp.p2, p2));
038 }
039 Pattern p = new GroupPattern(p1, p2);
040 return interner.intern(p);
041 }
042
043 Pattern makeInterleave(Pattern p1, Pattern p2) {
044 if (p1 == empty)
045 return p2;
046 if (p2 == empty)
047 return p1;
048 if (p1 == notAllowed || p2 == notAllowed)
049 return notAllowed;
050 if (false && p1 instanceof InterleavePattern) {
051 InterleavePattern ip = (InterleavePattern)p1;
052 return makeInterleave(ip.p1, makeInterleave(ip.p2, p2));
053 }
054 if (false) {
055 if (p2 instanceof InterleavePattern) {
056 InterleavePattern ip = (InterleavePattern)p2;
057 if (p1.hashCode() > ip.p1.hashCode())
058 return makeInterleave(ip.p1, makeInterleave(p1, ip.p2));
059 }
060 else if (p1.hashCode() > p2.hashCode())
061 return makeInterleave(p2, p1);
062 }
063 Pattern p = new InterleavePattern(p1, p2);
064 return interner.intern(p);
065 }
066
067 Pattern makeChoice(Pattern p1, Pattern p2) {
068 if (p1 == empty && p2.isNullable())
069 return p2;
070 if (p2 == empty && p1.isNullable())
071 return p1;
072 Pattern p = new ChoicePattern(p1, p2);
073 return interner.intern(p);
074 }
075
076 Pattern makeOneOrMore(Pattern p) {
077 if (p == empty
078 || p == notAllowed
079 || p instanceof OneOrMorePattern)
080 return p;
081 Pattern p1 = new OneOrMorePattern(p);
082 return interner.intern(p1);
083 }
084
085 Pattern makeOptional(Pattern p) {
086 return makeChoice(p, empty);
087 }
088
089 Pattern makeZeroOrMore(Pattern p) {
090 return makeOptional(makeOneOrMore(p));
091 }
092 }