001: /*
002: * Enhydra Java Application Server Project
003: *
004: * The contents of this file are subject to the Enhydra Public License
005: * Version 1.1 (the "License"); you may not use this file except in
006: * compliance with the License. You may obtain a copy of the License on
007: * the Enhydra web site ( http://www.enhydra.org/ ).
008: *
009: * Software distributed under the License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
011: * the License for the specific terms governing rights and limitations
012: * under the License.
013: *
014: * The Initial Developer of the Enhydra Application Server is Lutris
015: * Technologies, Inc. The Enhydra Application Server and portions created
016: * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
017: * All Rights Reserved.
018: *
019: * Contributor(s):
020: *
021: * $Id: KeywordParser.java,v 1.2 2006-06-15 14:07:00 sinisa Exp $
022: */
023:
024: package com.lutris.util;
025:
026: import java.text.MessageFormat;
027: import java.util.StringTokenizer;
028:
029: /**
030: * Class used to parse KeywordsValueTable keywords.
031: *
032: * @version $Revision: 1.2 $
033: * @author Mark Diekhans
034: * @since Jolt1.0
035: */
036: public class KeywordParser {
037: static private String separator = ".";
038:
039: /**
040: * Parse and validate the next component of a keyword.
041: *
042: * @param tokens Parsed token object.
043: * @param compIdx Index of the component we are about to parse. Used for
044: * error messages.
045: * @param keyword Entire keyword for use in error messages.
046: * @return The parsed keyword component.
047: */
048: static private String parseComponent(StringTokenizer tokens,
049: int compIdx, String keyword) throws KeywordValueException {
050: String comp = tokens.nextToken();
051:
052: /*
053: * Special check for keywords starting out with a separator, generates
054: * a more helpful error message.
055: */
056: if (comp.equals(separator) && (compIdx == 0)) {
057: String pattern = "keyword should not start with a {0} separator: \"{1} \"";
058: Object[] args = new String[] { separator, keyword };
059: String msg = MessageFormat.format(pattern, args);
060:
061: //String msg = "keyword should not start with a '" +
062: // separator + "' separator: \"" + keyword + "\"";
063: throw new KeywordValueException(msg);
064: }
065:
066: /*
067: * Validate the legality of the name.
068: */
069: boolean isOk = (comp.length() > 0);
070: if (isOk) {
071: if (!Character.isJavaIdentifierStart(comp.charAt(0))) {
072: isOk = false;
073: }
074: for (int j = 1; j < comp.length(); j++) {
075: if (!Character.isJavaIdentifierPart(comp.charAt(j))) {
076: isOk = false;
077: break;
078: }
079: }
080: }
081: if (!isOk) {
082: String msg = "keyword component must be a legal Java identifier "
083: + "component \"" + comp + "\": \"" + keyword + "\"";
084: throw new KeywordValueException(msg);
085: }
086:
087: /*
088: * Check the separator if its not the last component.
089: */
090: if (tokens.hasMoreTokens()) {
091: String sep = tokens.nextToken();
092: if (!sep.equals(separator)) {
093: String msg = "keyword component separator must be a "
094: + "single '" + separator + "', got \"" + sep
095: + "\": " + keyword + "\"";
096: throw new KeywordValueException(msg);
097: }
098: }
099: return comp;
100: }
101:
102: /**
103: * Parse a keyword into its components, validating that the components
104: * are legal names.
105: *
106: * @return An array of the keyword components.
107: * @exception KeywordValueException If the keyword is not syntactically legal.
108: */
109: static public String[] parse(String keyword)
110: throws KeywordValueException {
111:
112: StringTokenizer tokens = new StringTokenizer(keyword,
113: separator, true);
114: /*
115: * Set up the array for the keywords, making sure that an odd
116: * number of tokens are present, either single word or words
117: * separated by `.'.
118: */
119: int numTokens = tokens.countTokens();
120: if ((numTokens % 2) != 1) {
121: String msg = "keyword component must be single word or words "
122: + "separated by '"
123: + separator
124: + "': \""
125: + keyword
126: + "\"";
127: throw new KeywordValueException(msg);
128: }
129: int numComps = (numTokens / 2) + 1;
130: String[] keyParts = new String[numComps];
131:
132: for (int compIdx = 0; compIdx < numComps; compIdx++) {
133: keyParts[compIdx] = parseComponent(tokens, compIdx, keyword);
134: }
135:
136: return keyParts;
137: }
138:
139: /**
140: * Create a keyword from its components.
141: *
142: * @param keywordPath Array of path components.
143: * @return The keyword path string.
144: */
145: static public String join(String[] keywordPath) {
146: StringBuffer keyword = new StringBuffer();
147:
148: for (int idx = 0; idx < keywordPath.length; idx++) {
149: if (idx > 0) {
150: keyword.append(separator);
151: }
152: keyword.append(keywordPath[idx]);
153: }
154: return keyword.toString();
155: }
156:
157: /**
158: * Concatenate two keyword paths.
159: *
160: * @param keyword1 First keyword.
161: * @param keyword2 Second keyword.
162: * @return The keyword path string.
163: */
164: static public String concat(String keyword1, String keyword2) {
165: return keyword1 + separator + keyword2;
166: }
167: }
|