1
package com.thaiopensource.validate.nvdl;
3
import com.thaiopensource.xml.util.Naming;
5
import java.util.Vector;
8
* Stores a NVDL/NRL path information.
9
* Parses a path string and returns a list of Path objects.
10
* This stores a single path that can optionally start with a / and
11
* contains a list of local names separated by /, like
18
* Flag indicating wether the path starts with / or not.
20
private final boolean root;
23
* The list of local names that form the path.
25
private final Vector names;
28
* Constructor, creates a Path.
29
* @param root Flag specifying wether the path starts with / or not.
30
* @param names The list of local names.
32
Path(boolean root, Vector names) {
38
* Determines if the path starts with / or not.
39
* @return true if the path starts with /.
46
* Get the local names list.
47
* @return A vector with the local names.
54
* Get a string representation of this path.
55
* It can be either /name1/name2 or name1/name2.
57
public String toString() {
58
StringBuffer buf = new StringBuffer();
61
for (int i = 0, len = names.size(); i < len; i++) {
64
buf.append((String)names.elementAt(i));
66
return buf.toString();
70
* Exception thrown in case we get errors parsing a path.
72
static class ParseException extends Exception {
76
private final String messageKey;
79
* Creates an exception with a given message key.
80
* @param messageKey The message key.
82
ParseException(String messageKey) {
84
this.messageKey = messageKey;
88
* Get the message key.
89
* @return The message key.
91
public String getMessageKey() {
96
// states for parsing the path.
101
private static final int START = 0;
106
private static final int IN_NAME = 1;
109
* After a local name.
111
private static final int AFTER_NAME = 2;
116
private static final int AFTER_SLASH = 3;
119
* Gets the list of Path from the path string.
120
* The path string can represent more paths separated by |.
122
* @param str The path string.
123
* @return A Vector with the determined Path objects.
124
* @throws ParseException In case of invalid path expression.
126
static Vector parse(String str) throws ParseException {
128
int nameStartIndex = -1;
129
Vector paths = new Vector();
130
Vector names = new Vector();
131
boolean root = false;
132
for (int i = 0, len = str.length(); i < len; i++) {
133
char c = str.charAt(i);
139
if (state == IN_NAME) {
140
names.addElement(makeName(str, nameStartIndex, i));
147
names.addElement(makeName(str, nameStartIndex, i));
153
throw new ParseException("unexpected_slash");
160
throw new ParseException("empty_path");
164
throw new ParseException("expected_name");
166
names.addElement(makeName(str, nameStartIndex, i));
169
paths.addElement(new Path(root, names));
171
names = new Vector();
177
throw new ParseException("expected_slash");
191
throw new ParseException("empty_path");
195
throw new ParseException("expected_name");
197
names.addElement(makeName(str, nameStartIndex, str.length()));
200
paths.addElement(new Path(root, names));
205
* Extracts a name from a given string (path) from the specified
206
* start position to the specified end position.
207
* It also checks that the extracted name is a valid non qualified name (local name).
209
* @param str The path string.
210
* @param start The start position.
211
* @param end The end position.
212
* @return A string representing the extracted local name.
213
* @throws ParseException In case of invalid local name.
215
private static String makeName(String str, int start, int end) throws ParseException {
216
String name = str.substring(start, end);
217
if (!Naming.isNcname(name))
218
throw new ParseException("invalid_name");
223
* Main method, for test.
224
* @param args Command line arguments, the first argument is a path.
225
* @throws ParseException In case the parsing fails.
227
static public void main(String[] args) throws ParseException {
228
Vector paths = parse(args[0]);
229
for (int i = 0; i < paths.size(); i++) {
231
System.out.println("---");
232
Path path = (Path)paths.elementAt(i);
234
System.out.println("/");
235
for (int j = 0; j < path.getNames().size(); j++)
236
System.out.println(path.getNames().elementAt(j));