001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064: package com.jcorporate.expresso.core.dataobjects.jdbc;
065:
066: import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
067: import org.apache.commons.digester.Digester;
068: import org.apache.log4j.Logger;
069: import org.xml.sax.SAXException;
070:
071: import javax.xml.parsers.FactoryConfigurationError;
072: import java.io.InputStream;
073: import java.net.URL;
074: import java.util.List;
075: import java.util.Map;
076: import java.util.StringTokenizer;
077:
078: /**
079: * Not yet released - do not use in your own code yet.
080: * This class provides the Digester information to parse the join definitions
081: * so that we can define the join definition in an XML file.
082: *
083: * @author Michael Rimov
084: */
085:
086: public class JoinedDigesterBean {
087:
088: /**
089: * The log4j Logger
090: */
091: private static final Logger log = Logger
092: .getLogger(JoinedDigesterBean.class);
093:
094: /**
095: * A list of dataobjects
096: */
097: private List dataObjects = new java.util.ArrayList();
098:
099: /**
100: * A list of relations.
101: */
102: private List relations = new java.util.ArrayList();
103:
104: private Map permissions = new java.util.HashMap();
105:
106: /**
107: * set whether the queries are distinct or not.
108: */
109: private boolean distinct = false;
110:
111: /**
112: * Description of the join.
113: */
114: private String description = "";
115:
116: public JoinedDigesterBean() {
117: }
118:
119: public void addDataObject(String className, String definitionName,
120: String alias, String fieldExpressionList) {
121: dataObjects.add(new DigesterJoinedDataObject(className,
122: definitionName, alias, fieldExpressionList));
123: }
124:
125: public void addDataObject(String className, String definitionName,
126: String alias) {
127: addDataObject(className, definitionName, alias, null);
128: }
129:
130: /**
131: * Adds a relation to the data we've collected from Digester
132: *
133: * @param localAlias the local 'short name' of the dbobject
134: * @param localKey the local 'key' of the dbobject [Pipe delimited for multiple keys]
135: * @param foreignAlias the foreign 'short name' of the dbobject
136: * @param foreignKey the foreign keys (Pipe Delimited for multiple keys)
137: * @param joinType The type of join. Either left|right|inner or blank
138: */
139: public void addRelation(String localAlias, String localKey,
140: String foreignAlias, String foreignKey, String joinType) {
141: DigesterJoinRelations newRelation = new DigesterJoinRelations();
142:
143: StringTokenizer stoklocal = new StringTokenizer(localKey, "|");
144: StringTokenizer stokForeign = new StringTokenizer(foreignKey,
145: "|");
146: if (stoklocal.countTokens() != stokForeign.countTokens()) {
147: throw new IllegalArgumentException("Foreign key and local"
148: + " key must have the same number of keys");
149: }
150: newRelation.setLocalAlias(localAlias);
151: newRelation.setLocalKey(localKey);
152: newRelation.setForeignAlias(foreignAlias);
153: newRelation.setForeignKey(foreignKey);
154: newRelation.setJoinType(joinType);
155: relations.add(newRelation);
156:
157: }
158:
159: /**
160: * Loads the join data by constructing the Digester object and then merging
161: * the given URL into the current data.
162: *
163: * @param location the location to load the data from.
164: */
165: public void loadJoinData(URL location) {
166: Digester d = buildDigester();
167: digest(d, location);
168: }
169:
170: /**
171: * Set the permissions of the join
172: *
173: * @param create create permission
174: * @param read read permission
175: * @param update update permission
176: * @param delete delete permission
177: */
178: public void setPermissions(Boolean create, Boolean read,
179: Boolean update, Boolean delete) {
180:
181: permissions.put(SecuredDBObject.ADD, create);
182: permissions.put(SecuredDBObject.SEARCH, read);
183: permissions.put(SecuredDBObject.UPDATE, update);
184: permissions.put(SecuredDBObject.DELETE, delete);
185: }
186:
187: /**
188: * Retrieve the permissions
189: *
190: * @return java.util.Map
191: */
192: public Map getPermissions() {
193: return permissions;
194: }
195:
196: /**
197: * Builds the digester so it is ready to parse rules.
198: *
199: * @return a commons Digester instance with all rules built.
200: */
201: public Digester buildDigester() {
202: Digester digester = new Digester();
203: digester.setClassLoader(Thread.currentThread()
204: .getContextClassLoader());
205: setupResolvers(digester);
206:
207: digester.push(this );
208: digester.addSetProperties("dataobject-join");
209: digester.addCallMethod("dataobject-join/dataobject",
210: "addDataObject", 4);
211: digester.addCallParam("dataobject-join/dataobject", 0,
212: "className");
213: digester.addCallParam("dataobject-join/dataobject", 1,
214: "definitionName");
215: digester.addCallParam("dataobject-join/dataobject", 2, "alias");
216: digester.addCallParam("dataobject-join/dataobject", 3,
217: "fieldExpressionList");
218:
219: digester.addCallMethod("dataobject-join/distinct",
220: "setDistinct", 1,
221: new Class[] { java.lang.Boolean.class });
222: digester.addCallParam("dataobject-join/distinct", 0,
223: "distinctJoin");
224:
225: digester.addCallMethod("dataobject-join/permissions",
226: "setPermissions", 4, new Class[] {
227: java.lang.Boolean.class,
228: java.lang.Boolean.class,
229: java.lang.Boolean.class,
230: java.lang.Boolean.class });
231: digester.addCallParam("dataobject-join/permissions", 0, "add");
232: digester.addCallParam("dataobject-join/permissions", 1, "read");
233: digester.addCallParam("dataobject-join/permissions", 2,
234: "update");
235: digester.addCallParam("dataobject-join/permissions", 3,
236: "delete");
237:
238: digester.addCallMethod("dataobject-join/relations/foreign-key",
239: "addRelation", 5);
240: digester.addCallParam("dataobject-join/relations/foreign-key",
241: 0, "local-alias-ref");
242: digester.addCallParam("dataobject-join/relations/foreign-key",
243: 1, "local-alias-key");
244: digester.addCallParam("dataobject-join/relations/foreign-key",
245: 2, "foreign-alias-ref");
246: digester.addCallParam("dataobject-join/relations/foreign-key",
247: 3, "foreign-alias-key");
248: digester.addCallParam("dataobject-join/relations/foreign-key",
249: 4, "join-type");
250: return digester;
251: }
252:
253: /**
254: * Sets up the appropriate locations to resolve the Doctypes
255: *
256: * @param digester the Apache digester to register the resolvers with.
257: */
258: private void setupResolvers(Digester digester) {
259: URL url = this
260: .getClass()
261: .getResource(
262: "/com/jcorporate/expresso/core/dataobjects/jdbc/jdbc-join_5_1.dtd");
263: if (url != null) {
264: digester
265: .register(
266: "-//Jcorporate Ltd//DTD Expresso DataObject Join 5.1//EN",
267: url.toString());
268: } else {
269: throw new IllegalArgumentException("Unable to locate "
270: + "jdbc-join_5_1.dtd in package");
271: }
272: }
273:
274: /**
275: * Mergest the data from the given URL into the current object. If the load fails,
276: * nothing will be added, and a log will be noted
277: *
278: * @param parser the constructed Digester object
279: * @param location the URL location to load.
280: */
281: public void digest(Digester parser, URL location) {
282: try {
283: InputStream is = location.openStream();
284: parser.parse(is);
285: } catch (FactoryConfigurationError ex) {
286: log
287: .error(
288: "Fatal error trying to find a suitable Digester compatible parser.",
289: ex);
290: } catch (SAXException ex) {
291: log
292: .error(
293: "Fatal error trying to digest expresso-services.xml file",
294: ex);
295: } catch (java.io.IOException ex) {
296: log.error("Fatal IO error parsing input.", ex);
297: }
298:
299: }
300:
301: /**
302: * Retrieve a list of the dataobjects for this join.
303: *
304: * @return java.util.List of DigesterJoinedDataObject beans/
305: */
306: public List getDataObjects() {
307: return dataObjects;
308: }
309:
310: /**
311: * Returns whether the join is distinct or not.
312: *
313: * @return true if the join needs to be distinct.
314: */
315: public boolean isDistinct() {
316: return distinct;
317: }
318:
319: /**
320: * Sets whether the join is distinct or not. Should normally only be
321: * called by the digester
322: *
323: * @param distinct new distinct value.
324: */
325: public void setDistinct(boolean distinct) {
326: this .distinct = distinct;
327: }
328:
329: /**
330: * Sets whether the join is distinct or not with a Boolean value. Expresso
331: * parses the value appropriately
332: *
333: * @param newValue the new String value
334: */
335: public void setDistinct(Boolean newValue) {
336: if (newValue != null) {
337: this .distinct = newValue.booleanValue();
338: }
339: }
340:
341: /**
342: * Sets whether the join is distinct or not with a string value. Expresso
343: * parses the value appropriately
344: *
345: * @param newValue the new String value
346: */
347: public void setDistinct(String newValue) {
348: this .distinct = com.jcorporate.expresso.core.misc.StringUtil
349: .toBoolean(newValue);
350: }
351:
352: /**
353: * Retrieves a list of the relations with this bean.
354: *
355: * @return java.util.List of DigesterJoinRelations beans
356: */
357: public List getRelations() {
358: return relations;
359: }
360:
361: public String getDescription() {
362: return description;
363: }
364:
365: public void setDescription(String description) {
366: this .description = description;
367: }
368:
369: /**
370: * Bean representing all the dataobject information. Instances of
371: * this bean are retrieved by getDataObjects();
372: * <p/>
373: * author Michael Rimov
374: */
375: public class DigesterJoinedDataObject {
376:
377: private String definitionName;
378: private String alias;
379: private String className;
380: private String fieldExpressionList;
381:
382: private DigesterJoinedDataObject() {
383: }
384:
385: public DigesterJoinedDataObject(String name, String definition,
386: String newAlias, String fieldExpression) {
387: className = name;
388: definitionName = definition;
389: alias = newAlias;
390: fieldExpressionList = fieldExpression;
391: }
392:
393: public String getClassName() {
394: return this .className;
395: }
396:
397: public String getDefinitionName() {
398: return definitionName;
399: }
400:
401: public void setDefinitionName(String definitionName) {
402: this .definitionName = definitionName;
403: }
404:
405: public void setAlias(String alias) {
406: this .alias = alias;
407: }
408:
409: public String getAlias() {
410: return alias;
411: }
412:
413: public String getFieldExpressionList() {
414: return fieldExpressionList;
415: }
416:
417: }
418:
419: /**
420: * Bean representing all the joined relation information. Instances of
421: * this bean are retrieved by getRelations();
422: * <p/>
423: * author Michael Rimov
424: */
425: public class DigesterJoinRelations {
426:
427: private String localAlias;
428: private String localKey;
429: private String foreignAlias;
430: private String foreignKey;
431: private String joinType;
432:
433: public DigesterJoinRelations() {
434: }
435:
436: public String getLocalAlias() {
437: return localAlias;
438: }
439:
440: public void setLocalAlias(String localAlias) {
441: this .localAlias = localAlias;
442: }
443:
444: public void setLocalKey(String localKey) {
445: this .localKey = localKey;
446: }
447:
448: public String getLocalKey() {
449: return localKey;
450: }
451:
452: public void setForeignAlias(String foreignAlias) {
453: this .foreignAlias = foreignAlias;
454: }
455:
456: public String getForeignAlias() {
457: return foreignAlias;
458: }
459:
460: public void setForeignKey(String foreignKey) {
461: this .foreignKey = foreignKey;
462: }
463:
464: public String getForeignKey() {
465: return foreignKey;
466: }
467:
468: public String getJoinType() {
469: return joinType;
470: }
471:
472: public void setJoinType(String newValue) {
473: joinType = newValue;
474: }
475: }
476: }
|