01: package org.kohsuke.rngom.binary;
02:
03: import org.kohsuke.rngom.binary.visitor.PatternFunction;
04: import org.kohsuke.rngom.binary.visitor.PatternVisitor;
05:
06: public class InterleavePattern extends BinaryPattern {
07: InterleavePattern(Pattern p1, Pattern p2) {
08: super (p1.isNullable() && p2.isNullable(), combineHashCode(
09: INTERLEAVE_HASH_CODE, p1.hashCode(), p2.hashCode()),
10: p1, p2);
11: }
12:
13: Pattern expand(SchemaPatternBuilder b) {
14: Pattern ep1 = p1.expand(b);
15: Pattern ep2 = p2.expand(b);
16: if (ep1 != p1 || ep2 != p2)
17: return b.makeInterleave(ep1, ep2);
18: else
19: return this ;
20: }
21:
22: void checkRestrictions(int context, DuplicateAttributeDetector dad,
23: Alphabet alpha) throws RestrictionViolationException {
24: switch (context) {
25: case START_CONTEXT:
26: throw new RestrictionViolationException(
27: "start_contains_interleave");
28: case DATA_EXCEPT_CONTEXT:
29: throw new RestrictionViolationException(
30: "data_except_contains_interleave");
31: case LIST_CONTEXT:
32: throw new RestrictionViolationException(
33: "list_contains_interleave");
34: }
35: if (context == ELEMENT_REPEAT_CONTEXT)
36: context = ELEMENT_REPEAT_INTERLEAVE_CONTEXT;
37: Alphabet a1;
38: if (alpha != null && alpha.isEmpty())
39: a1 = alpha;
40: else
41: a1 = new Alphabet();
42: p1.checkRestrictions(context, dad, a1);
43: if (a1.isEmpty())
44: p2.checkRestrictions(context, dad, a1);
45: else {
46: Alphabet a2 = new Alphabet();
47: p2.checkRestrictions(context, dad, a2);
48: a1.checkOverlap(a2);
49: if (alpha != null) {
50: if (alpha != a1)
51: alpha.addAlphabet(a1);
52: alpha.addAlphabet(a2);
53: }
54: }
55: if (context != LIST_CONTEXT
56: && !contentTypeGroupable(p1.getContentType(), p2
57: .getContentType()))
58: throw new RestrictionViolationException("interleave_string");
59: if (p1.getContentType() == MIXED_CONTENT_TYPE
60: && p2.getContentType() == MIXED_CONTENT_TYPE)
61: throw new RestrictionViolationException(
62: "interleave_text_overlap");
63: }
64:
65: public void accept(PatternVisitor visitor) {
66: visitor.visitInterleave(p1, p2);
67: }
68:
69: public Object apply(PatternFunction f) {
70: return f.caseInterleave(this);
71: }
72: }
|