001    package com.thaiopensource.relaxng.impl;
002    
003    import com.thaiopensource.xml.util.Name;
004    
005    class StartTagOpenDerivFunction extends AbstractPatternFunction {
006      private final Name name;
007      private final ValidatorPatternBuilder builder;
008    
009      StartTagOpenDerivFunction(Name name, ValidatorPatternBuilder builder) {
010        this.name = name;
011        this.builder = builder;
012      }
013    
014      public Object caseChoice(ChoicePattern p) {
015        return builder.makeChoice(memoApply(p.getOperand1()),
016                                  memoApply(p.getOperand2()));
017      }
018    
019      public Object caseGroup(GroupPattern p) {
020        final Pattern p1 = p.getOperand1();
021        final Pattern p2 = p.getOperand2();
022        Pattern tem = memoApply(p1).applyForPattern(
023                                          new ApplyAfterFunction(builder) {
024                                              Pattern apply(Pattern x) {
025                                                return builder.makeGroup(x, p2);
026                                              }
027                                            });
028        return p1.isNullable() ? builder.makeChoice(tem, memoApply(p2)) : tem;
029      }
030    
031      public Object caseInterleave(InterleavePattern p) {
032        final Pattern p1 = p.getOperand1();
033        final Pattern p2 = p.getOperand2();
034        return builder.makeChoice(
035                                  memoApply(p1).applyForPattern(new ApplyAfterFunction(builder) {
036                                      Pattern apply(Pattern x) {
037                                        return builder.makeInterleave(x, p2);
038                                      }
039                                    }),
040                                  memoApply(p2).applyForPattern(new ApplyAfterFunction(builder) {
041                                      Pattern apply(Pattern x) {
042                                        return builder.makeInterleave(p1, x);
043                                      }
044                                    }));
045      }
046    
047      public Object caseAfter(AfterPattern p) {
048        final Pattern p1 = p.getOperand1();
049        final Pattern p2 = p.getOperand2();
050        return memoApply(p1).applyForPattern(
051                                   new ApplyAfterFunction(builder) {
052                                       Pattern apply(Pattern x) {
053                                         return builder.makeAfter(x, p2);
054                                       }
055                                     });
056      }
057    
058      public Object caseOneOrMore(final OneOrMorePattern p) {
059        final Pattern p1 = p.getOperand();
060        return memoApply(p1).applyForPattern(
061                                   new ApplyAfterFunction(builder) {
062                                       Pattern apply(Pattern x) {
063                                         return builder.makeGroup(x,
064                                                                  builder.makeOptional(p));
065                                       }
066                                     });
067      }
068    
069    
070      public Object caseElement(ElementPattern p) {
071        if (!p.getNameClass().contains(name))
072          return builder.makeNotAllowed();
073        return builder.makeAfter(p.getContent(), builder.makeEmpty());
074      }
075    
076      public Object caseOther(Pattern p) {
077        return builder.makeNotAllowed();
078      }
079    
080      final Pattern memoApply(Pattern p) {
081        return apply(builder.getPatternMemo(p)).getPattern();
082      }
083    
084      PatternMemo apply(PatternMemo memo) {
085        return memo.startTagOpenDeriv(this);
086      }
087    
088      Name getName() {
089        return name;
090      }
091    
092      ValidatorPatternBuilder getPatternBuilder() {
093        return builder;
094      }
095    }