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 }