001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.sql.framework.model;
042:
043: import java.util.HashMap;
044: import java.util.List;
045: import java.util.ListIterator;
046: import java.util.Map;
047:
048: import org.netbeans.modules.sql.framework.common.utils.TagParserUtility;
049: import org.netbeans.modules.sql.framework.common.utils.XmlUtil;
050: import org.netbeans.modules.sql.framework.codegen.SQLOperatorFactory;
051: import org.netbeans.modules.sql.framework.model.utils.OperatorUtil;
052: import org.netbeans.modules.sql.framework.ui.graph.IOperatorField;
053: import org.netbeans.modules.sql.framework.ui.graph.IOperatorXmlInfo;
054: import org.w3c.dom.Element;
055: import org.w3c.dom.Node;
056: import org.w3c.dom.NodeList;
057: import net.java.hulp.i18n.Logger;
058: import com.sun.sql.framework.exception.BaseException;
059: import com.sun.sql.framework.utils.Attribute;
060: import org.netbeans.modules.etl.logger.Localizer;
061: import org.netbeans.modules.etl.logger.LogUtil;
062:
063: /**
064: * Singleton object factory for SQL objects.
065: *
066: * @author Ritesh Adval
067: * @version $Revision$
068: */
069: public class SQLObjectFactory {
070:
071: /* Log4J category string */
072: private static final String LOG_CATEGORY = SQLObjectFactory.class
073: .getName();
074: private static transient final Logger mLogger = LogUtil
075: .getLogger(SQLObjectFactory.class.getName());
076: private static transient final Localizer mLoc = Localizer.get();
077: private static final String OBJECT_TYPE_CLASS = "class";
078: private static final String OBJECT_TYPE_CLASS_TAG = "objectTypeClass";
079: private static final String OBJECT_TYPE_MAP_FILE = "org/netbeans/modules/sql/framework/model/impl/objectTypeMap.xml";
080: private static final String OBJECT_TYPE_NAME = "name";
081: private static Map objectTagToTypeMap = new HashMap();
082: private static final String USER_FUNCTION_ID = "userFx";
083:
084: static {
085: init();
086: }
087:
088: /**
089: * Creates a new SQLObject instance of the type represented by the given tag name.
090: * Does not add the the vended SQLObject to a SQLDefinitionImpl instance. To correctly
091: * associate the returned SQLObject instance with a SQLDefinitionImpl instance, the
092: * calling method should call SQLDefinitionImpl.addSQLObject(SQLObject).
093: *
094: * @param objTag objTag of object to create
095: * @return new SQLObject instance
096: * @throws BaseException if error occurs during creation
097: * @see org.netbeans.modules.sql.framework.model#addSQLObject(SQLObject)
098: */
099: public static SQLObject createObjectForTag(String objTag)
100: throws BaseException {
101: String className = (String) objectTagToTypeMap.get(objTag);
102: SQLObject obj = createSQLObject(className);
103: return obj;
104: }
105:
106: /**
107: * Creates a SQLOperator instance of the given operator name and using the give List
108: * of SQLObjects as argument inputs. This method should only be called from
109: * SQLConditionParser.
110: *
111: * @param dbSpName name of parsed DB operator to be created
112: * @param args List of SQLObjects representing parsed argument inputs
113: */
114: public static SQLOperator createOperatorFromParsedList(
115: String dbSpName, List args) throws BaseException {
116: boolean userFunction = false;
117: String userFunctionName = dbSpName;
118: if ("STANDARDIZE".equalsIgnoreCase(dbSpName)) {
119: SQLLiteral literal = (SQLLiteral) args.get(0);
120: String arg0 = literal.getValue();
121: dbSpName = dbSpName + "_" + arg0;
122: }
123:
124: // first try all lower case
125: String cdbSpName = dbSpName.toLowerCase();
126: SQLOperatorDefinition operatorDefinition = SQLOperatorFactory
127: .getDefault().getDbSpecficOperatorDefinition(cdbSpName);
128: if (operatorDefinition == null) {
129: // now try upper case
130: cdbSpName = dbSpName.toUpperCase();
131: operatorDefinition = SQLOperatorFactory.getDefault()
132: .getDbSpecficOperatorDefinition(cdbSpName);
133: // if it is still null then throw exception
134: if (operatorDefinition == null) {
135: operatorDefinition = SQLOperatorFactory.getDefault()
136: .getDbSpecficOperatorDefinition(dbSpName);
137: userFunction = true;
138: }
139: }
140:
141: // set IOperatorXmlInfo
142: String opName = userFunction ? USER_FUNCTION_ID
143: : operatorDefinition.getOperatorName();
144: IOperatorXmlInfo operatorXml = OperatorUtil
145: .findOperatorXmlInfo(opName);
146: if (operatorXml != null) {
147: SQLOperator operator = (SQLOperator) createSQLObject(operatorXml
148: .getObjectClassName());
149: operator.setDisplayName(opName);
150: operator
151: .setDbSpecificOperator(userFunction ? USER_FUNCTION_ID
152: : operatorDefinition.getDbSpecficName());
153: if (userFunction) {
154: operator.setCustomOperatorName(userFunctionName);
155: operator.setOperatorXmlInfo(operatorXml);
156: }
157:
158: replaceVisibleLiteralsForStaticFields(args, operatorXml);
159: operator.setArguments(args);
160: return operator;
161: }
162: throw new BaseException(
163: "Cannot locate definition for operator " + opName);
164: }
165:
166: /**
167: * Creates a new SQLObject instance of the given type. Does not add the the vended
168: * SQLObject to a SQLDefinitionImpl instance. To correctly associate the returned
169: * SQLObject instance with a SQLDefinitionImpl instance, the calling method should
170: * call SQLDefinitionImpl.addSQLObject(SQLObject).
171: *
172: * @param className className of object to create
173: * @return new SQLObject instance
174: * @throws BaseException if error occurs during creation
175: * @see org.netbeans.modules.sql.framework.model#addSQLObject(SQLObject)
176: */
177: public static SQLObject createSQLObject(String className)
178: throws BaseException {
179: SQLObject obj = null;
180:
181: if (className != null) {
182: try {
183: Class sqlObject = Class.forName(className);
184: obj = (SQLObject) sqlObject.newInstance();
185: } catch (ClassNotFoundException e) {
186: throw new BaseException(
187: "Cannot create object of class " + className);
188: } catch (ClassCastException e1) {
189: throw new BaseException(
190: "Cannot create object of class " + className);
191: } catch (InstantiationException e2) {
192: throw new BaseException(
193: "Cannot create object of class " + className);
194: } catch (IllegalAccessException e3) {
195: throw new BaseException(
196: "Cannot create object of class " + className);
197: }
198: }
199:
200: return obj;
201: }
202:
203: public static SQLObject createSQLObjectForElement(Object parent,
204: Element element) throws BaseException {
205: SQLObject sqlObj = null;
206: String objType = element.getAttribute(SQLObject.OBJECT_TYPE);
207: if (objType == null) {
208: throw new BaseException(SQLObject.OBJECT_TYPE
209: + " attribute not found for element: "
210: + element.getNodeName());
211: }
212:
213: int objectType = TagParserUtility.getIntType(objType);
214: if ((SQLConstants.GENERIC_OPERATOR == objectType)
215: || (SQLConstants.VISIBLE_PREDICATE == objectType)
216: || (SQLConstants.CUSTOM_OPERATOR == objectType)) {
217: sqlObj = createSQLOperator(element);
218: } else {
219: sqlObj = createObjectForTag(objType);
220: }
221:
222: if (sqlObj != null) {
223: sqlObj.setParentObject(parent);
224: sqlObj.parseXML(element);
225: }
226: return sqlObj;
227: }
228:
229: /**
230: * Creates a new SQLObject representing a SQLOperator implementation, using the given
231: * Element for initialization. Does not add the the vended SQLObject to a
232: * SQLDefinitionImpl instance. To correctly associate the returned SQLObject instance
233: * with a SQLDefinitionImpl instance, the calling method should call
234: * SQLDefinition.addSQLObject(SQLObject).
235: *
236: * @param element XML Element containing initialization information for the new
237: * function
238: * @return new SQLObject instance representing a SQLOperator implementation
239: * @throws BaseException if error occurs during creation
240: * @see org.netbeans.modules.sql.framework.model#addSQLObject(SQLObject)
241: */
242: private static SQLObject createSQLOperator(Element element)
243: throws BaseException {
244: NodeList list = element.getChildNodes();
245: String script = null;
246: for (int i = 0; i < list.getLength(); i++) {
247: Node node = list.item(i);
248: if (!Attribute.TAG_ATTR.equals(node.getNodeName())) {
249: continue;
250: }
251:
252: Element attrElem = (Element) node;
253: Attribute attr = TagParserUtility.parseAttribute(attrElem);
254:
255: if (SQLOperator.ATTR_SCRIPTREF.equals(attr
256: .getAttributeName())) {
257: script = (String) attr.getAttributeValue();
258: break;
259: }
260: }
261:
262: if (script == null) {
263: throw new BaseException(SQLOperator.ATTR_SCRIPTREF
264: + " attribute not found for element: "
265: + element.getNodeName());
266: }
267:
268: IOperatorXmlInfo operatorXml = OperatorUtil
269: .findOperatorXmlInfo(script);
270: SQLOperator operator = null;
271: if (operatorXml != null) {
272: operator = (SQLOperator) createSQLObject(operatorXml
273: .getObjectClassName());
274: }
275:
276: return operator;
277: }
278:
279: private static void init() {
280: try {
281: Element elem = XmlUtil.loadXMLFile(OBJECT_TYPE_MAP_FILE);
282: NodeList objMap = elem
283: .getElementsByTagName(OBJECT_TYPE_CLASS_TAG);
284: parseObjectMap(objMap);
285: } catch (Exception e) {
286: mLogger.errorNoloc(mLoc.t(
287: "PRSR136: Failed to load the Object Map{0}",
288: LOG_CATEGORY), e);
289: }
290: }
291:
292: private static void parseObjectMap(NodeList objMap) {
293: for (int i = 0; i < objMap.getLength(); i++) {
294: Element elem = (Element) objMap.item(i);
295: String objType = elem.getAttribute(OBJECT_TYPE_NAME);
296: String objClass = elem.getAttribute(OBJECT_TYPE_CLASS);
297:
298: if (objType != null && objClass != null) {
299: objectTagToTypeMap.put(objType, objClass);
300: }
301: }
302: }
303:
304: /**
305: * Substitutes SQLLiteralImpl instances for VisibleSQLLiteralImpl instances in the
306: * given List of SQLObjects, based on whether a field is declared as static in the
307: * given IOperatorXmlInfo class. (Static fields do not accept inputs from other canvas
308: * objects; their values are set via Swing controls such as combo boxes and/or text
309: * fields which are embedded in the canvas object.)
310: *
311: * @param operatorArgs List containing SQLObjects which represent operator inputs to
312: * be evaluated and replaced if necessary
313: * @param operatorXml IOperatorXmlInfo instance
314: */
315: private static void replaceVisibleLiteralsForStaticFields(
316: List operatorArgs, IOperatorXmlInfo operatorXml)
317: throws BaseException {
318: List inputFields = operatorXml.getInputFields();
319: if (operatorArgs != null && inputFields != null
320: && operatorArgs.size() == inputFields.size()) {
321: ListIterator it = inputFields.listIterator();
322:
323: while (it.hasNext()) {
324: IOperatorField fieldInfo = (IOperatorField) it.next();
325: int argIdx = it.previousIndex();
326:
327: SQLObject argValue = (SQLObject) operatorArgs
328: .get(argIdx);
329: if (fieldInfo.isStatic()
330: && argValue instanceof VisibleSQLLiteral) {
331: VisibleSQLLiteral vlit = (VisibleSQLLiteral) argValue;
332: SQLLiteral replacement = SQLModelObjectFactory
333: .getInstance()
334: .createSQLLiteral(vlit.getDisplayName(),
335: vlit.getValue(), vlit.getJdbcType());
336: operatorArgs.set(argIdx, replacement);
337: }
338: }
339: }
340: }
341:
342: private SQLObjectFactory() {
343: }
344: }
|