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 }