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 }