001    package com.thaiopensource.relaxng.impl;
002    
003    import org.xml.sax.Locator;
004    import org.xml.sax.SAXException;
005    
006    class AttributePattern extends Pattern {
007      private final NameClass nameClass;
008      private final Pattern p;
009      private final Locator loc;
010    
011      AttributePattern(NameClass nameClass, Pattern value, Locator loc) {
012        super(false,
013              EMPTY_CONTENT_TYPE,
014              combineHashCode(ATTRIBUTE_HASH_CODE,
015                              nameClass.hashCode(),
016                              value.hashCode()));
017        this.nameClass = nameClass;
018        this.p = value;
019        this.loc = loc;
020      }
021    
022      Pattern expand(SchemaPatternBuilder b) {
023        Pattern ep = p.expand(b);
024        if (ep != p)
025          return b.makeAttribute(nameClass, ep, loc);
026        else
027          return this;
028      }
029    
030      void checkRestrictions(int context, DuplicateAttributeDetector dad, Alphabet alpha)
031        throws RestrictionViolationException {
032        switch (context) {
033        case START_CONTEXT:
034          throw new RestrictionViolationException("start_contains_attribute");
035        case ELEMENT_CONTEXT:
036          if (nameClass.isOpen())
037            throw new RestrictionViolationException("open_name_class_not_repeated");
038          break;
039        case ELEMENT_REPEAT_GROUP_CONTEXT:
040          throw new RestrictionViolationException("one_or_more_contains_group_contains_attribute");
041        case ELEMENT_REPEAT_INTERLEAVE_CONTEXT:
042          throw new RestrictionViolationException("one_or_more_contains_interleave_contains_attribute");
043        case LIST_CONTEXT:
044          throw new RestrictionViolationException("list_contains_attribute");
045        case ATTRIBUTE_CONTEXT:
046          throw new RestrictionViolationException("attribute_contains_attribute");
047        case DATA_EXCEPT_CONTEXT:
048          throw new RestrictionViolationException("data_except_contains_attribute");
049        }
050        if (!dad.addAttribute(nameClass)) {
051          if (nameClass instanceof SimpleNameClass)
052            throw new RestrictionViolationException("duplicate_attribute_detail", ((SimpleNameClass)nameClass).getName());
053          else
054            throw new RestrictionViolationException("duplicate_attribute");
055        }
056        try {
057          p.checkRestrictions(ATTRIBUTE_CONTEXT, null, null);
058        }
059        catch (RestrictionViolationException e) {
060          e.maybeSetLocator(loc);
061          throw e;
062        }
063      }
064    
065      boolean samePattern(Pattern other) {
066        if (!(other instanceof AttributePattern))
067          return false;
068        AttributePattern ap = (AttributePattern)other;
069        return nameClass.equals(ap.nameClass)&& p == ap.p;
070      }
071    
072      void checkRecursion(int depth) throws SAXException {
073        p.checkRecursion(depth);
074      }
075    
076      void accept(PatternVisitor visitor) {
077        visitor.visitAttribute(nameClass, p);
078      }
079    
080      Object apply(PatternFunction f) {
081        return f.caseAttribute(this);
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    }