001 package com.thaiopensource.relaxng.impl;
002
003 import org.xml.sax.Locator;
004 import org.xml.sax.SAXException;
005
006 class ElementPattern extends Pattern {
007 private Pattern p;
008 private final NameClass origNameClass;
009 private NameClass nameClass;
010 private boolean expanded = false;
011 private boolean checkedRestrictions = false;
012 private final Locator loc;
013
014 ElementPattern(NameClass nameClass, Pattern p, Locator loc) {
015 super(false,
016 ELEMENT_CONTENT_TYPE,
017 combineHashCode(ELEMENT_HASH_CODE,
018 nameClass.hashCode(),
019 p.hashCode()));
020 this.nameClass = nameClass;
021 this.origNameClass = nameClass;
022 this.p = p;
023 this.loc = loc;
024 }
025
026 void checkRestrictions(int context, DuplicateAttributeDetector dad, Alphabet alpha)
027 throws RestrictionViolationException {
028 if (alpha != null)
029 alpha.addElement(origNameClass);
030 if (checkedRestrictions)
031 return;
032 switch (context) {
033 case DATA_EXCEPT_CONTEXT:
034 throw new RestrictionViolationException("data_except_contains_element");
035 case LIST_CONTEXT:
036 throw new RestrictionViolationException("list_contains_element");
037 case ATTRIBUTE_CONTEXT:
038 throw new RestrictionViolationException("attribute_contains_element");
039 }
040 checkedRestrictions = true;
041 try {
042 p.checkRestrictions(ELEMENT_CONTEXT, new DuplicateAttributeDetector(), null);
043 }
044 catch (RestrictionViolationException e) {
045 checkedRestrictions = false;
046 e.maybeSetLocator(loc);
047 throw e;
048 }
049 }
050
051 Pattern expand(SchemaPatternBuilder b) {
052 if (!expanded) {
053 expanded = true;
054 p = p.expand(b);
055 if (p.isNotAllowed())
056 nameClass = new NullNameClass();
057 }
058 return this;
059 }
060
061 boolean samePattern(Pattern other) {
062 if (!(other instanceof ElementPattern))
063 return false;
064 ElementPattern ep = (ElementPattern)other;
065 return nameClass.equals(ep.nameClass) && p == ep.p;
066 }
067
068 void checkRecursion(int depth) throws SAXException {
069 p.checkRecursion(depth + 1);
070 }
071
072 void accept(PatternVisitor visitor) {
073 visitor.visitElement(nameClass, p);
074 }
075
076 Object apply(PatternFunction f) {
077 return f.caseElement(this);
078 }
079
080 void setContent(Pattern p) {
081 this.p = p;
082 }
083
084 Pattern getContent() {
085 return p;
086 }
087
088 NameClass getNameClass() {
089 return nameClass;
090 }
091
092 Locator getLocator() {
093 return loc;
094 }
095 }