001    package com.thaiopensource.relaxng.impl;
002    
003    class InterleavePattern extends BinaryPattern {
004      InterleavePattern(Pattern p1, Pattern p2) {
005        super(p1.isNullable() && p2.isNullable(),
006              combineHashCode(INTERLEAVE_HASH_CODE, p1.hashCode(), p2.hashCode()),
007              p1,
008              p2);
009      }
010      Pattern expand(SchemaPatternBuilder b) {
011        Pattern ep1 = p1.expand(b);
012        Pattern ep2 = p2.expand(b);
013        if (ep1 != p1 || ep2 != p2)
014          return b.makeInterleave(ep1, ep2);
015        else
016          return this;
017      }
018      void checkRestrictions(int context, DuplicateAttributeDetector dad, Alphabet alpha)
019        throws RestrictionViolationException {
020        switch (context) {
021        case START_CONTEXT:
022          throw new RestrictionViolationException("start_contains_interleave");
023        case DATA_EXCEPT_CONTEXT:
024          throw new RestrictionViolationException("data_except_contains_interleave");
025        case LIST_CONTEXT:
026          throw new RestrictionViolationException("list_contains_interleave");
027        }
028        if (context == ELEMENT_REPEAT_CONTEXT)
029          context = ELEMENT_REPEAT_INTERLEAVE_CONTEXT;
030        Alphabet a1;
031        if (alpha != null && alpha.isEmpty())
032          a1 = alpha;
033        else
034          a1 = new Alphabet();
035        p1.checkRestrictions(context, dad, a1);
036        if (a1.isEmpty())
037          p2.checkRestrictions(context, dad, a1);
038        else {
039          Alphabet a2 = new Alphabet();
040          p2.checkRestrictions(context, dad, a2);
041          a1.checkOverlap(a2);
042          if (alpha != null) {
043            if (alpha != a1)
044              alpha.addAlphabet(a1);
045            alpha.addAlphabet(a2);
046          }
047        }
048        if (!contentTypeGroupable(p1.getContentType(), p2.getContentType()))
049          throw new RestrictionViolationException("interleave_string");
050        if (p1.getContentType() == MIXED_CONTENT_TYPE
051            && p2.getContentType() == MIXED_CONTENT_TYPE)
052          throw new RestrictionViolationException("interleave_text_overlap");
053      }
054    
055      void accept(PatternVisitor visitor) {
056        visitor.visitInterleave(p1, p2);
057      }
058      Object apply(PatternFunction f) {
059        return f.caseInterleave(this);
060      }
061    }