001: /**********************************************************************
002: Copyright (c) 2002 Mike Martin (TJDO) and others. All rights reserved.
003: Licensed under the Apache License, Version 2.0 (the "License");
004: you may not use this file except in compliance with the License.
005: You may obtain a copy of the License at
006:
007: http://www.apache.org/licenses/LICENSE-2.0
008:
009: Unless required by applicable law or agreed to in writing, software
010: distributed under the License is distributed on an "AS IS" BASIS,
011: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: See the License for the specific language governing permissions and
013: limitations under the License.
014:
015:
016: Contributors:
017: 2003 Andy Jefferson - commented
018: ...
019: **********************************************************************/package org.jpox.util;
020:
021: import org.jpox.ClassLoaderResolver;
022: import org.jpox.exceptions.ClassNotResolvedException;
023: import org.jpox.exceptions.JPOXUserException;
024:
025: /**
026: * Macro String Utilities
027: *
028: * @version $Revision: 1.9 $
029: **/
030: public class MacroString {
031: protected static final Localiser LOCALISER = Localiser
032: .getInstance("org.jpox.Localisation");
033:
034: private final String this ClassName;
035: private final Imports imports;
036: private final String macroString;
037:
038: /**
039: * Constructor.
040: * @param className The class name
041: * @param importsString String containing IMPORTs
042: * @param macroString String containing macro
043: **/
044: public MacroString(String className, String importsString,
045: String macroString) {
046: this .this ClassName = className;
047: this .macroString = macroString;
048:
049: imports = new Imports();
050: if (this ClassName != null) {
051: imports.importPackage(this ClassName);
052: }
053: if (importsString != null) {
054: imports.parseImports(importsString);
055: }
056: }
057:
058: /**
059: * Utility to substitute macros using the supplier handler.
060: * @param mh Macro handler.
061: * @param clr ClassLoaderResolver
062: * @return The updated string
063: **/
064: public String substituteMacros(MacroHandler mh,
065: ClassLoaderResolver clr) {
066: StringBuffer outBuf = new StringBuffer();
067: int left, right;
068:
069: /* Pass 1: Substitute SQL identifier macros "{...}". */
070: for (int curr = 0; curr < macroString.length(); curr = right + 1) {
071: if ((left = macroString.indexOf('{', curr)) < 0) {
072: outBuf.append(macroString.substring(curr));
073: break;
074: }
075:
076: outBuf.append(macroString.substring(curr, left));
077:
078: if ((right = macroString.indexOf('}', left + 1)) < 0) {
079: throw new JPOXUserException(LOCALISER.msg("031000",
080: macroString));
081: }
082:
083: IdentifierMacro im = parseIdentifierMacro(macroString
084: .substring(left + 1, right), clr);
085: mh.onIdentifierMacro(im);
086:
087: outBuf.append(im.value);
088: }
089:
090: String tmpString = outBuf.toString();
091: outBuf = new StringBuffer();
092:
093: /* Pass 2: Substitute parameter macros "?...?". */
094: for (int curr = 0; curr < tmpString.length(); curr = right + 1) {
095: if ((left = tmpString.indexOf('?', curr)) < 0) {
096: outBuf.append(tmpString.substring(curr));
097: break;
098: }
099:
100: outBuf.append(tmpString.substring(curr, left));
101:
102: if ((right = tmpString.indexOf('?', left + 1)) < 0) {
103: throw new JPOXUserException(LOCALISER.msg("031001",
104: tmpString));
105: }
106:
107: ParameterMacro pm = new ParameterMacro(tmpString.substring(
108: left + 1, right));
109: mh.onParameterMacro(pm);
110:
111: outBuf.append('?');
112: }
113:
114: return outBuf.toString();
115: }
116:
117: /**
118: * Utility to resolve a class declaration.
119: * @param className Name of the class
120: * @param clr the ClassLoaderResolver
121: * @return The class
122: **/
123: private Class resolveClassDeclaration(String className,
124: ClassLoaderResolver clr) {
125: try {
126: return className.equals("this") ? clr.classForName(
127: this ClassName, null) : imports
128: .resolveClassDeclaration(className, clr, null);
129: } catch (ClassNotResolvedException e) {
130: return null;
131: }
132: }
133:
134: /**
135: * Utility to parse the identitifer macro.
136: * @param unparsed The unparsed string
137: * @param clr ClassLoaderResolver
138: * @return The parsed string
139: **/
140: private IdentifierMacro parseIdentifierMacro(String unparsed,
141: ClassLoaderResolver clr) {
142: String className = null;
143: String fieldName = null;
144: String subfieldName = null;
145:
146: Class c = resolveClassDeclaration(unparsed, clr);
147:
148: if (c == null) {
149: /* The last '.' in the string. */
150: int lastDot = unparsed.lastIndexOf('.');
151:
152: if (lastDot < 0) {
153: throw new JPOXUserException(LOCALISER.msg("031002",
154: unparsed));
155: }
156:
157: fieldName = unparsed.substring(lastDot + 1);
158: className = unparsed.substring(0, lastDot);
159: c = resolveClassDeclaration(className, clr);
160:
161: if (c == null) {
162: /* The second to the last dot in the string. */
163: int lastDot2 = unparsed.lastIndexOf('.', lastDot - 1);
164:
165: if (lastDot2 < 0) {
166: throw new JPOXUserException(LOCALISER.msg("031002",
167: unparsed));
168: }
169:
170: subfieldName = fieldName;
171: fieldName = unparsed.substring(lastDot2 + 1, lastDot);
172: className = unparsed.substring(0, lastDot2);
173: c = resolveClassDeclaration(className, clr);
174:
175: if (c == null) {
176: throw new JPOXUserException(LOCALISER.msg("031002",
177: unparsed));
178: }
179: }
180: }
181:
182: return new IdentifierMacro(unparsed, c.getName(), fieldName,
183: subfieldName);
184: }
185:
186: /**
187: * Inner class : Identifier Macro
188: **/
189: public static class IdentifierMacro {
190: /** unparsed identifier macro **/
191: public final String unparsed;
192: /** the class name **/
193: public final String className;
194: /** the field name **/
195: public final String fieldName;
196: /** the sub field name TODO what is this **/
197: public final String subfieldName;
198: /** the value **/
199: public String value;
200:
201: /**
202: * Constructor
203: * @param unparsed the unparsed macro
204: * @param className the class name
205: * @param fieldName the field name
206: * @param subfieldName the sub field name TODO what is this
207: */
208: IdentifierMacro(String unparsed, String className,
209: String fieldName, String subfieldName) {
210: this .unparsed = unparsed;
211: this .className = className;
212: this .fieldName = fieldName;
213: this .subfieldName = subfieldName;
214: this .value = null;
215: }
216:
217: public String toString() {
218: return "{" + unparsed + "}";
219: }
220: }
221:
222: /**
223: * Inner class : Parameter Macro
224: **/
225: public static class ParameterMacro {
226: /** the parameter name **/
227: public final String parameterName;
228:
229: /**
230: * Constructor
231: * @param parameterName the parameter name
232: */
233: ParameterMacro(String parameterName) {
234: this .parameterName = parameterName;
235: }
236:
237: public String toString() {
238: return "?" + parameterName + "?";
239: }
240: }
241:
242: /**
243: * Inner class : Macro Handler
244: **/
245: public static interface MacroHandler {
246: /**
247: * handles identifier macros
248: * @param im the identitifier macro to handle
249: */
250: void onIdentifierMacro(IdentifierMacro im);
251:
252: /**
253: * handler parameter macros
254: * @param pm the parameter macro to handle
255: */
256: void onParameterMacro(ParameterMacro pm);
257: }
258: }
|