~ubuntu-branches/debian/wheezy/jing-trang/wheezy

« back to all changes in this revision

Viewing changes to mod/nvdl/src/main/com/thaiopensource/validate/nvdl/Path.java

  • Committer: Bazaar Package Importer
  • Author(s): Samuel Thibault
  • Date: 2009-09-01 15:53:03 UTC
  • Revision ID: james.westby@ubuntu.com-20090901155303-2kweef05h5v9j3ni
Tags: upstream-20090818
ImportĀ upstreamĀ versionĀ 20090818

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package com.thaiopensource.validate.nvdl;
 
2
 
 
3
import com.thaiopensource.xml.util.Naming;
 
4
 
 
5
import java.util.Vector;
 
6
 
 
7
/**
 
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
 
12
 * /path1/path2 or
 
13
 * path1/path2.
 
14
 * 
 
15
 */
 
16
class Path {
 
17
  /**
 
18
   * Flag indicating wether the path starts with / or not.
 
19
   */
 
20
  private final boolean root;
 
21
 
 
22
  /**
 
23
   * The list of local names that form the path.
 
24
   */
 
25
  private final Vector names;
 
26
 
 
27
  /**
 
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.
 
31
   */
 
32
  Path(boolean root, Vector names) {
 
33
    this.root = root;
 
34
    this.names = names;
 
35
  }
 
36
 
 
37
  /**
 
38
   * Determines if the path starts with / or not.
 
39
   * @return true if the path starts with /.
 
40
   */
 
41
  boolean isRoot() {
 
42
    return root;
 
43
  }
 
44
 
 
45
  /**
 
46
   * Get the local names list.
 
47
   * @return A vector with the local names.
 
48
   */
 
49
  Vector getNames() {
 
50
    return names;
 
51
  }
 
52
 
 
53
  /**
 
54
   * Get a string representation of this path.
 
55
   * It can be either /name1/name2 or name1/name2.
 
56
   */
 
57
  public String toString() {
 
58
    StringBuffer buf = new StringBuffer();
 
59
    if (root)
 
60
      buf.append('/');
 
61
    for (int i = 0, len = names.size(); i < len; i++) {
 
62
      if (i != 0)
 
63
        buf.append('/');
 
64
      buf.append((String)names.elementAt(i));
 
65
    }
 
66
    return buf.toString();
 
67
  }
 
68
 
 
69
  /**
 
70
   * Exception thrown in case we get errors parsing a path.
 
71
   */
 
72
  static class ParseException extends Exception {
 
73
    /**
 
74
     * The message key.
 
75
     */
 
76
    private final String messageKey;
 
77
 
 
78
    /**
 
79
     * Creates an exception with a given message key.
 
80
     * @param messageKey The message key.
 
81
     */
 
82
    ParseException(String messageKey) {
 
83
      super(messageKey);
 
84
      this.messageKey = messageKey;
 
85
    }
 
86
 
 
87
    /**
 
88
     * Get the message key.
 
89
     * @return The message key.
 
90
     */
 
91
    public String getMessageKey() {
 
92
      return messageKey;
 
93
    }
 
94
  }
 
95
 
 
96
  // states for parsing the path.
 
97
  
 
98
  /**
 
99
   * Initial state.
 
100
   */
 
101
  private static final int START = 0;
 
102
 
 
103
  /**
 
104
   * In a local name.
 
105
   */
 
106
  private static final int IN_NAME = 1;
 
107
 
 
108
  /**
 
109
   * After a local name.
 
110
   */
 
111
  private static final int AFTER_NAME = 2;
 
112
 
 
113
  /**
 
114
   * After a slash.
 
115
   */
 
116
  private static final int AFTER_SLASH = 3;
 
117
 
 
118
  /**
 
119
   * Gets the list of Path from the path string.
 
120
   * The path string can represent more paths separated by |.
 
121
   * 
 
122
   * @param str The path string.
 
123
   * @return A Vector with the determined Path objects.
 
124
   * @throws ParseException In case of invalid path expression.
 
125
   */
 
126
  static Vector parse(String str) throws ParseException {
 
127
    int state = START;
 
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);
 
134
      switch (c) {
 
135
      case ' ':
 
136
      case '\r':
 
137
      case '\n':
 
138
      case '\t':
 
139
        if (state == IN_NAME) {
 
140
          names.addElement(makeName(str, nameStartIndex, i));
 
141
          state = AFTER_NAME;
 
142
        }
 
143
        break;
 
144
      case '/':
 
145
        switch (state) {
 
146
        case IN_NAME:
 
147
          names.addElement(makeName(str, nameStartIndex, i));
 
148
          break;
 
149
        case START:
 
150
          root = true;
 
151
          break;
 
152
        case AFTER_SLASH:
 
153
          throw new ParseException("unexpected_slash");
 
154
        }
 
155
        state = AFTER_SLASH;
 
156
        break;
 
157
      case '|':
 
158
        switch (state) {
 
159
        case START:
 
160
          throw new ParseException("empty_path");
 
161
        case AFTER_NAME:
 
162
          break;
 
163
        case AFTER_SLASH:
 
164
          throw new ParseException("expected_name");
 
165
        case IN_NAME:
 
166
          names.addElement(makeName(str, nameStartIndex, i));
 
167
          break;
 
168
        }
 
169
        paths.addElement(new Path(root, names));
 
170
        root = false;
 
171
        names = new Vector();
 
172
        state = START;
 
173
        break;
 
174
      default:
 
175
        switch (state) {
 
176
        case AFTER_NAME:
 
177
          throw new ParseException("expected_slash");
 
178
        case AFTER_SLASH:
 
179
        case START:
 
180
          nameStartIndex = i;
 
181
          state = IN_NAME;
 
182
          break;
 
183
        case IN_NAME:
 
184
          break;
 
185
        }
 
186
        break;
 
187
      }
 
188
    }
 
189
    switch (state) {
 
190
    case START:
 
191
      throw new ParseException("empty_path");
 
192
    case AFTER_NAME:
 
193
      break;
 
194
    case AFTER_SLASH:
 
195
      throw new ParseException("expected_name");
 
196
    case IN_NAME:
 
197
      names.addElement(makeName(str, nameStartIndex, str.length()));
 
198
      break;
 
199
    }
 
200
    paths.addElement(new Path(root, names));
 
201
    return paths;
 
202
  }
 
203
 
 
204
  /**
 
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).
 
208
   * 
 
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.
 
214
   */
 
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");
 
219
    return name;
 
220
  }
 
221
 
 
222
  /**
 
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.
 
226
   */
 
227
  static public void main(String[] args) throws ParseException {
 
228
    Vector paths = parse(args[0]);
 
229
    for (int i = 0; i < paths.size(); i++) {
 
230
      if (i != 0)
 
231
        System.out.println("---");
 
232
      Path path = (Path)paths.elementAt(i);
 
233
      if (path.isRoot())
 
234
        System.out.println("/");
 
235
      for (int j = 0; j < path.getNames().size(); j++)
 
236
        System.out.println(path.getNames().elementAt(j));
 
237
    }
 
238
  }
 
239
}