001    package com.thaiopensource.validate.nrl;
002    
003    import com.thaiopensource.xml.util.Naming;
004    
005    import java.util.Vector;
006    
007    class Path {
008      private final boolean root;
009      private final Vector names;
010    
011      Path(boolean root, Vector names) {
012        this.root = root;
013        this.names = names;
014      }
015    
016      boolean isRoot() {
017        return root;
018      }
019    
020      Vector getNames() {
021        return names;
022      }
023    
024      public String toString() {
025        StringBuffer buf = new StringBuffer();
026        if (root)
027          buf.append('/');
028        for (int i = 0, len = names.size(); i < len; i++) {
029          if (i != 0)
030            buf.append('/');
031          buf.append((String)names.elementAt(i));
032        }
033        return buf.toString();
034      }
035    
036      static class ParseException extends Exception {
037        private final String messageKey;
038    
039        ParseException(String messageKey) {
040          super(messageKey);
041          this.messageKey = messageKey;
042        }
043    
044        public String getMessageKey() {
045          return messageKey;
046        }
047      }
048    
049      private static final int START = 0;
050      private static final int IN_NAME = 1;
051      private static final int AFTER_NAME = 2;
052      private static final int AFTER_SLASH = 3;
053    
054      static Vector parse(String str) throws ParseException {
055        int state = START;
056        int nameStartIndex = -1;
057        Vector paths = new Vector();
058        Vector names = new Vector();
059        boolean root = false;
060        for (int i = 0, len = str.length(); i < len; i++) {
061          char c = str.charAt(i);
062          switch (c) {
063          case ' ':
064          case '\r':
065          case '\n':
066          case '\t':
067            if (state == IN_NAME) {
068              names.addElement(makeName(str, nameStartIndex, i));
069              state = AFTER_NAME;
070            }
071            break;
072          case '/':
073            switch (state) {
074            case IN_NAME:
075              names.addElement(makeName(str, nameStartIndex, i));
076              break;
077            case START:
078              root = true;
079              break;
080            case AFTER_SLASH:
081              throw new ParseException("unexpected_slash");
082            }
083            state = AFTER_SLASH;
084            break;
085          case '|':
086            switch (state) {
087            case START:
088              throw new ParseException("empty_path");
089            case AFTER_NAME:
090              break;
091            case AFTER_SLASH:
092              throw new ParseException("expected_name");
093            case IN_NAME:
094              names.addElement(makeName(str, nameStartIndex, i));
095              break;
096            }
097            paths.addElement(new Path(root, names));
098            root = false;
099            names = new Vector();
100            state = START;
101            break;
102          default:
103            switch (state) {
104            case AFTER_NAME:
105              throw new ParseException("expected_slash");
106            case AFTER_SLASH:
107            case START:
108              nameStartIndex = i;
109              state = IN_NAME;
110              break;
111            case IN_NAME:
112              break;
113            }
114            break;
115          }
116        }
117        switch (state) {
118        case START:
119          throw new ParseException("empty_path");
120        case AFTER_NAME:
121          break;
122        case AFTER_SLASH:
123          throw new ParseException("expected_name");
124        case IN_NAME:
125          names.addElement(makeName(str, nameStartIndex, str.length()));
126          break;
127        }
128        paths.addElement(new Path(root, names));
129        return paths;
130      }
131    
132      private static String makeName(String str, int start, int end) throws ParseException {
133        String name = str.substring(start, end);
134        if (!Naming.isNcname(name))
135          throw new ParseException("invalid_name");
136        return name;
137      }
138    
139      static public void main(String[] args) throws ParseException {
140        Vector paths = parse(args[0]);
141        for (int i = 0; i < paths.size(); i++) {
142          if (i != 0)
143            System.out.println("---");
144          Path path = (Path)paths.elementAt(i);
145          if (path.isRoot())
146            System.out.println("/");
147          for (int j = 0; j < path.getNames().size(); j++)
148            System.out.println(path.getNames().elementAt(j));
149        }
150      }
151    }