0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041: package org.netbeans.modules.sql.framework.model.impl;
0042:
0043: import java.io.Serializable;
0044: import java.util.ArrayList;
0045: import java.util.Collection;
0046: import java.util.HashSet;
0047: import java.util.Iterator;
0048: import java.util.LinkedHashMap;
0049: import java.util.List;
0050: import java.util.Map;
0051: import java.util.Set;
0052: import org.netbeans.modules.sql.framework.common.utils.TagParserUtility;
0053: import org.netbeans.modules.sql.framework.common.utils.XmlUtil;
0054: import org.netbeans.modules.sql.framework.model.ColumnRef;
0055: import org.netbeans.modules.sql.framework.model.RuntimeDatabaseModel;
0056: import org.netbeans.modules.sql.framework.model.SQLCondition;
0057: import org.netbeans.modules.sql.framework.model.SQLConnectableObject;
0058: import org.netbeans.modules.sql.framework.model.SQLConstants;
0059: import org.netbeans.modules.sql.framework.model.SQLDBColumn;
0060: import org.netbeans.modules.sql.framework.model.SQLDBModel;
0061: import org.netbeans.modules.sql.framework.model.SQLDBTable;
0062: import org.netbeans.modules.sql.framework.model.SQLDefinition;
0063: import org.netbeans.modules.sql.framework.model.SQLFilter;
0064: import org.netbeans.modules.sql.framework.model.SQLFrameworkParentObject;
0065: import org.netbeans.modules.sql.framework.model.SQLGenericOperator;
0066: import org.netbeans.modules.sql.framework.model.SQLInputObject;
0067: import org.netbeans.modules.sql.framework.model.SQLJoinOperator;
0068: import org.netbeans.modules.sql.framework.model.SQLJoinView;
0069: import org.netbeans.modules.sql.framework.model.SQLLiteral;
0070: import org.netbeans.modules.sql.framework.model.SQLModelObjectFactory;
0071: import org.netbeans.modules.sql.framework.model.SQLObject;
0072: import org.netbeans.modules.sql.framework.model.SQLObjectFactory;
0073: import org.netbeans.modules.sql.framework.model.SQLObjectListener;
0074: import org.netbeans.modules.sql.framework.model.SQLPredicate;
0075: import org.netbeans.modules.sql.framework.model.SourceColumn;
0076: import org.netbeans.modules.sql.framework.model.SourceTable;
0077: import org.netbeans.modules.sql.framework.model.TargetTable;
0078: import org.netbeans.modules.sql.framework.model.VisibleSQLLiteral;
0079: import org.netbeans.modules.sql.framework.model.VisibleSQLPredicate;
0080: import org.netbeans.modules.sql.framework.model.utils.SQLObjectUtil;
0081: import org.netbeans.modules.sql.framework.model.visitors.SQLDBSynchronizationValidationVisitor;
0082: import org.netbeans.modules.sql.framework.model.visitors.SQLOperatorInfoVisitor;
0083: import org.netbeans.modules.sql.framework.model.visitors.SQLValidationVisitor;
0084: import org.netbeans.modules.sql.framework.model.visitors.SQLVisitor;
0085: import org.netbeans.modules.sql.framework.ui.graph.IOperatorField;
0086: import org.netbeans.modules.sql.framework.ui.graph.IOperatorXmlInfo;
0087: import org.netbeans.modules.sql.framework.ui.view.conditionbuilder.ConditionBuilderUtil;
0088: import org.w3c.dom.Element;
0089: import org.w3c.dom.Node;
0090: import org.w3c.dom.NodeList;
0091: import com.sun.sql.framework.exception.BaseException;
0092: import com.sun.sql.framework.utils.Attribute;
0093: import net.java.hulp.i18n.Logger;
0094: import com.sun.sql.framework.utils.StringUtil;
0095: import org.netbeans.modules.etl.logger.Localizer;
0096: import org.netbeans.modules.etl.logger.LogUtil;
0097: import org.netbeans.modules.sql.framework.model.DBColumn;
0098: import org.netbeans.modules.sql.framework.model.DBTable;
0099: import org.netbeans.modules.sql.framework.model.DatabaseModel;
0100: import org.netbeans.modules.sql.framework.model.ValidationInfo;
0101: import org.netbeans.modules.sql.framework.model.visitors.SQLDBDriverValidationVisitor;
0102:
0103: /**
0104: * Implements SQLDefinition.
0105: *
0106: * @author Ahimanikya Satapathy
0107: */
0108: public class SQLDefinitionImpl implements SQLDefinition, Serializable {
0109:
0110: private static final String J = "J";
0111: private static final String S = "S";
0112: private static final String T = "T";
0113: private static final String STAGING = "Staging";
0114: private static final String BEST_FIT = "Best Fit";
0115: private static final String PIPELINE = "Pipeline";
0116: private static transient final Logger mLogger = LogUtil
0117: .getLogger(SQLDefinitionImpl.class.getName());
0118: private static transient final Localizer mLoc = Localizer.get();
0119:
0120: class SecondParseObjectInfo {
0121:
0122: private Element mElm;
0123: private SQLObject mObj;
0124:
0125: SecondParseObjectInfo(SQLObject obj, Element elm) {
0126: this .mObj = obj;
0127: this .mElm = elm;
0128: }
0129:
0130: @Override
0131: public boolean equals(Object obj) {
0132: SecondParseObjectInfo other = (SecondParseObjectInfo) obj;
0133: return other.mObj == this .mObj
0134: && other.mElm.equals(this .mElm);
0135: }
0136:
0137: public Element getElement() {
0138: return mElm;
0139: }
0140:
0141: public SQLObject getSQLObject() {
0142: return mObj;
0143: }
0144:
0145: @Override
0146: public int hashCode() {
0147: int hashCode = (mObj != null) ? mObj.hashCode() : 0;
0148: hashCode += (mElm != null) ? mElm.hashCode() : 0;
0149: return hashCode;
0150: }
0151: }
0152:
0153: /** TAG_DEFINITION is the tag for an SQL definition */
0154: protected static final String TAG_DEFINITION = "sqlDefinition";
0155: /* Log category string */
0156: private static final String LOG_CATEGORY = SQLDefinitionImpl.class
0157: .getName();
0158: private static String VERSION = "6.0";
0159: /**
0160: * Map of attributes; used by concrete implementations to store class-specific fields
0161: * without hard coding them as member variables
0162: */
0163: protected Map<String, Attribute> attributes = new LinkedHashMap<String, Attribute>();
0164: private String displayName;
0165: private List<SQLObjectListener> listeners = new ArrayList<SQLObjectListener>();
0166: private transient SQLFrameworkParentObject mParent;
0167: private Map<String, SQLObject> objectMap = new LinkedHashMap<String, SQLObject>();
0168: private Object parent; // Parent ETLObject.
0169: private transient Set<SecondParseObjectInfo> secondPassList = new HashSet<SecondParseObjectInfo>();
0170:
0171: /**
0172: * Creates a new default instance of SQLDefinitionImpl.
0173: */
0174: public SQLDefinitionImpl() {
0175: this .init();
0176: }
0177:
0178: /**
0179: * Creates a new instance of SQLDefinitionImpl, parsing the given DOM Element to
0180: * retrieve its contents.
0181: *
0182: * @param xmlElement DOM element containing content information
0183: * @exception BaseException if error occurs while parsing
0184: */
0185: public SQLDefinitionImpl(Element xmlElement) throws BaseException {
0186: this ();
0187: parseXML(xmlElement);
0188: }
0189:
0190: /**
0191: * Creates a new instance of SQLDefinitionImpl, parsing the given DOM Element to
0192: * retrieve its contents.
0193: *
0194: * @param xmlElement DOM element containing content information
0195: * @exception BaseException if error occurs while parsing
0196: */
0197: public SQLDefinitionImpl(Element xmlElement,
0198: SQLFrameworkParentObject parent) throws BaseException {
0199: this ();
0200: mParent = parent;
0201: parseXML(xmlElement);
0202: }
0203:
0204: /**
0205: * Creates a new instance of SQLDefinitionImpl with the given display name.
0206: *
0207: * @param aDisplayName for this
0208: */
0209: public SQLDefinitionImpl(String aDisplayName) {
0210: this ();
0211: this .displayName = aDisplayName;
0212: }
0213:
0214: /**
0215: * Adds given SQLObject instance to this SQLDefinition.
0216: *
0217: * @param newObject new instance to add
0218: * @throws BaseException if add fails or instance implements an unrecognized object
0219: * type.
0220: */
0221: public void addObject(SQLObject newObject) throws BaseException {
0222: // check if object already exist -- Do we still need this check ?? -- Ahi
0223: if (objectMap.get(newObject.getId()) != null) {
0224: //throw new BaseException("Object " + newObject.getDisplayName() + "already exists.");
0225: }
0226:
0227: // always set the id first.
0228: if (newObject.getId() == null) {
0229: newObject.setId(generateId());
0230: }
0231:
0232: // set the object properties
0233: setSQLObjectProperties(newObject);
0234:
0235: // special handling for tables and columns
0236: // we need to generate unique ids for them
0237: switch (newObject.getObjectType()) {
0238: // Tables are not added directly to object map, but rather through
0239: // its parent database model.
0240: case SQLConstants.SOURCE_TABLE:
0241: case SQLConstants.TARGET_TABLE:
0242: case SQLConstants.RUNTIME_INPUT:
0243: case SQLConstants.RUNTIME_OUTPUT:
0244: addTable((SQLDBTable) newObject);
0245: break;
0246: case SQLConstants.SOURCE_DBMODEL:
0247: case SQLConstants.TARGET_DBMODEL:
0248: case SQLConstants.RUNTIME_DBMODEL:
0249:
0250: objectMap.put(newObject.getId(), newObject);
0251: SQLDBModel dbModel = (SQLDBModel) newObject;
0252: setTableId(dbModel.getTables());
0253: newObject.setParentObject(this );
0254: break;
0255: default:
0256: add(newObject);
0257: break;
0258: }
0259: }
0260:
0261: /**
0262: * Add SecondPass SQLObject to list
0263: *
0264: * @param sqlObj to be added
0265: * @param element xmlElement of SQLObject
0266: */
0267: public void addSecondPassSQLObject(SQLObject sqlObj, Element element) {
0268: // this is a fix for problem with equal and hashcode method of SQL object
0269: // equal method usually use some object which are not yet resolved when
0270: // this method is called during parsing. so different object become
0271: // equal breaking the code because of hash map get and put method
0272: // may return a different object or overwrite existing object
0273: secondPassList.add(new SecondParseObjectInfo(sqlObj, element));
0274: }
0275:
0276: /**
0277: * add an SQL object listener
0278: *
0279: * @param listener SQL object listener
0280: */
0281: public synchronized void addSQLObjectListener(
0282: SQLObjectListener listener) {
0283: if (!listeners.contains(listener)) {
0284: listeners.add(listener);
0285: }
0286: }
0287:
0288: public void clearOverride(boolean clearCatalogOverride,
0289: boolean clearSchemaOverride) {
0290: List<SQLDBModel> dbModels = this .getAllDatabases();
0291: SQLDBModel dbModel = null;
0292: for (Iterator<SQLDBModel> itr = dbModels.iterator(); itr
0293: .hasNext();) {
0294: dbModel = itr.next();
0295: dbModel.clearOverride(clearCatalogOverride,
0296: clearSchemaOverride);
0297: }
0298: }
0299:
0300: /**
0301: * all sql objects are cloneable
0302: */
0303: public Object cloneSQLObject() throws CloneNotSupportedException {
0304: throw new java.lang.UnsupportedOperationException();
0305: }
0306:
0307: /**
0308: * Creates a new SQLObject instance of the given type. Does not add the the vended
0309: * SQLObject to this SQLDefinition, although it does set its parent reference to this.
0310: * To correctly associate the returned SQLObject instance with this instance, the
0311: * calling method should call addSQLObject(SQLObject).
0312: *
0313: * @param objTag objTag of object to create
0314: * @return new SQLObject instance
0315: * @throws BaseException if error occurs during creation
0316: * @see #addObject(SQLObject)
0317: */
0318: public SQLObject createObject(String objTag) throws BaseException {
0319: return SQLObjectFactory.createObjectForTag(objTag);
0320: }
0321:
0322: /**
0323: * Creates a new SQLObject instance of the given type. Does not add the the vended
0324: * SQLObject to this SQLDefinition, although it does set its parent reference to this.
0325: * To correctly associate the returned SQLObject instance with this instance, the
0326: * calling method should call addSQLObject(SQLObject).
0327: *
0328: * @param className className of object to create
0329: * @return new SQLObject instance
0330: * @throws BaseException if error occurs during creation
0331: * @see #addObject(SQLObject)
0332: */
0333: public SQLObject createSQLObject(String className)
0334: throws BaseException {
0335: return SQLObjectFactory.createSQLObject(className);
0336: }
0337:
0338: /**
0339: * Overrides default implementation to determine value based on any associated
0340: * attributes as well as values of non-transient member variables.
0341: *
0342: * @param o Object to be compared
0343: * @return true if o is equivalent to this; false otherwise
0344: */
0345: @Override
0346: public boolean equals(Object o) {
0347: if (o == null) {
0348: return false;
0349: } else if (o == this ) {
0350: return true;
0351: }
0352:
0353: boolean response = false;
0354:
0355: if (o instanceof SQLDefinitionImpl) {
0356: SQLDefinitionImpl target = (SQLDefinitionImpl) o;
0357: response = (objectMap != null) ? objectMap
0358: .equals(target.objectMap)
0359: : (target.objectMap == null);
0360: response &= (displayName != null) ? displayName
0361: .equals(target.displayName)
0362: : (target.displayName == null);
0363: }
0364:
0365: return response;
0366: }
0367:
0368: public String generateId() {
0369: int cnt = 0;
0370: String id = "sqlObject" + "_" + cnt;
0371: while (isIdExists(id)) {
0372: cnt++;
0373: id = "sqlObject" + "_" + cnt;
0374: }
0375: return id;
0376: }
0377:
0378: /**
0379: * Gets Collection of all SQLObjects in this model.
0380: *
0381: * @return Collection, possibly empty, of all SQLObjects
0382: */
0383: public Collection<SQLObject> getAllObjects() {
0384: return objectMap.values();
0385: }
0386:
0387: /**
0388: * Gets List of all Databases associated with this model.
0389: *
0390: * @return List of DatabaseModels representing participating Databases
0391: */
0392: public List<SQLDBModel> getAllDatabases() {
0393: List<SQLDBModel> list = new ArrayList<SQLDBModel>();
0394: Iterator it = getObjectsOfType(SQLConstants.SOURCE_DBMODEL)
0395: .iterator();
0396: while (it.hasNext()) {
0397: list.add((SQLDBModel) it.next());
0398: }
0399:
0400: it = getObjectsOfType(SQLConstants.TARGET_DBMODEL).iterator();
0401: while (it.hasNext()) {
0402: list.add((SQLDBModel) it.next());
0403: }
0404: return list;
0405: }
0406:
0407: /**
0408: * Gets an attribute based on its name
0409: *
0410: * @param attrName attribute Name
0411: * @return Attribute instance associated with attrName, or null if none exists
0412: */
0413: public Attribute getAttribute(String attrName) {
0414: return attributes.get(attrName);
0415: }
0416:
0417: /**
0418: * @see SQLObject#getAttributeNames
0419: */
0420: public Collection<String> getAttributeNames() {
0421: return attributes.keySet();
0422: }
0423:
0424: /**
0425: * @see SQLObject#getAttributeObject
0426: */
0427: public Object getAttributeValue(String attrName) {
0428: Attribute attr = getAttribute(attrName);
0429: return (attr != null) ? attr.getAttributeValue() : null;
0430: }
0431:
0432: /**
0433: * Gets display name.
0434: *
0435: * @return current display name
0436: */
0437: public String getDisplayName() {
0438: return displayName;
0439: }
0440:
0441: public Integer getExecutionStrategyCode() {
0442: return (Integer) this
0443: .getAttributeValue(ATTR_EXECUTION_STRATEGY_CODE);
0444: }
0445:
0446: public String getDBWorkingFolder() {
0447: String workingFolder = (String) this
0448: .getAttributeValue(AXION_DB_WORKING_FOLDER);
0449: workingFolder = (workingFolder == null) ? "" : workingFolder;
0450: return workingFolder;
0451: }
0452:
0453: public String getDbInstanceName() {
0454: String dbName = (String) this
0455: .getAttributeValue(AXION_DB_INSTANCE_NAME);
0456: dbName = (dbName == null) ? "" : dbName;
0457: return dbName;
0458: }
0459:
0460: public String getExecutionStrategyStr() {
0461: int code = getExecutionStrategyCode().intValue();
0462: switch (code) {
0463: case SQLDefinition.EXECUTION_STRATEGY_PIPELINE:
0464: return SQLDefinitionImpl.PIPELINE;
0465: case SQLDefinition.EXECUTION_STRATEGY_STAGING:
0466: return SQLDefinitionImpl.STAGING;
0467: case SQLDefinition.EXECUTION_STRATEGY_BEST_FIT:
0468: default:
0469: return SQLDefinitionImpl.BEST_FIT;
0470: }
0471: }
0472:
0473: public List<DBTable> getJoinSources() {
0474: List<DBTable> joinSources = new ArrayList<DBTable>();
0475: List<DBTable> sTables = this .getSourceTables();
0476: Iterator it = sTables.iterator();
0477:
0478: while (it.hasNext()) {
0479: SourceTable sTable = (SourceTable) it.next();
0480: if (sTable.isUsedInJoin()) {
0481: continue;
0482: }
0483: joinSources.add(sTable);
0484: }
0485: // add any join views also
0486: return joinSources;
0487: }
0488:
0489: /**
0490: * Gets associated SQLObject instance, if any, with the given object ID.
0491: *
0492: * @param objectId ID of SQLObject instance to be retrieved
0493: * @param type type of object to retrieve
0494: * @return associated SQLObject instance, or null if no such instance exists
0495: */
0496: public SQLObject getObject(String objectId, int type) {
0497: SQLObject sqlObj;
0498:
0499: switch (type) {
0500: // for source table and source column we need to look in each db model
0501: // if that id exists
0502: case SQLConstants.SOURCE_TABLE:
0503: case SQLConstants.SOURCE_COLUMN:
0504: sqlObj = getObjectFromDBModel(objectId,
0505: SQLConstants.SOURCE_DBMODEL);
0506: // if sqlObj is null then we should check in runtime model
0507: // as it also contains SOURCE_COLUMN
0508: if (sqlObj == null) {
0509: sqlObj = getObjectFromDBModel(objectId,
0510: SQLConstants.RUNTIME_DBMODEL);
0511: }
0512: break;
0513: case SQLConstants.TARGET_TABLE:
0514: case SQLConstants.TARGET_COLUMN:
0515: sqlObj = getObjectFromDBModel(objectId,
0516: SQLConstants.TARGET_DBMODEL);
0517: // if sqlObj is null then we should check in runtime model
0518: // as it also contains TARGET_COLUMN
0519: if (sqlObj == null) {
0520: sqlObj = getObjectFromDBModel(objectId,
0521: SQLConstants.RUNTIME_DBMODEL);
0522: }
0523: break;
0524: case SQLConstants.RUNTIME_INPUT:
0525: case SQLConstants.RUNTIME_OUTPUT:
0526: sqlObj = getObjectFromDBModel(objectId,
0527: SQLConstants.RUNTIME_DBMODEL);
0528: break;
0529: case SQLConstants.LITERAL:
0530: sqlObj = objectMap.get(objectId);
0531: break;
0532: default:
0533: sqlObj = objectMap.get(objectId);
0534: }
0535:
0536: return sqlObj;
0537: }
0538:
0539: /**
0540: * Gets Collection of SQLObjects matching the given object type.
0541: *
0542: * @param type type of objects to retrieve
0543: * @return Collection, possibly empty, of SQLObjects with matching type
0544: */
0545: @SuppressWarnings(value="unchecked")
0546: public Collection getObjectsOfType(int type) {
0547: switch (type) {
0548: case SQLConstants.SOURCE_TABLE:
0549: return getSourceTables();
0550: case SQLConstants.SOURCE_COLUMN:
0551: return getSourceColumns();
0552: case SQLConstants.TARGET_TABLE:
0553: return getTargetTables();
0554: case SQLConstants.TARGET_COLUMN:
0555: return getTargetColumns();
0556: }
0557:
0558: List<SQLObject> list = new ArrayList<SQLObject>();
0559: Iterator<SQLObject> it = objectMap.values().iterator();
0560:
0561: while (it.hasNext()) {
0562: SQLObject sqlObject = it.next();
0563: if (sqlObject.getObjectType() == type) {
0564: list.add(sqlObject);
0565: }
0566: }
0567:
0568: return list;
0569: }
0570:
0571: /**
0572: * @see SQLDefinition#getParent
0573: */
0574: public Object getParent() {
0575: return parent;
0576: }
0577:
0578: /**
0579: * Gets the Root SQLJoinOperator Object in a given List
0580: *
0581: * @param sourceTables List of Source Table SQLObjects
0582: * @return SQLObject Root Join from List
0583: * @throws BaseException while getting the Root
0584: */
0585: public SQLObject getRootJoin(List<DBTable> sourceTables)
0586: throws BaseException {
0587: if (sourceTables == null || sourceTables.size() == 0) {
0588: throw new BaseException(
0589: "Source Table List is null or Empty");
0590: }
0591:
0592: List<DBTable> tables = new ArrayList<DBTable>();
0593: Iterator it1 = this .getRootJoins(SQLConstants.JOIN).iterator();
0594: while (it1.hasNext()) {
0595: SQLObject joinObject = (SQLObject) it1.next();
0596: discoverSourceTables(joinObject, tables);
0597: if (tables.containsAll(sourceTables)) {
0598: return joinObject;
0599: }
0600: }
0601: return null;
0602: }
0603:
0604: /**
0605: * Gets Collection of SQLJoinOperators representing "root" joins for this model.
0606: *
0607: * @param type ???
0608: * @return Collection, possibly empty, of root SQLJoinOperators
0609: */
0610: public Collection<SQLObject> getRootJoins(int type) {
0611: List<SQLObject> list = new ArrayList<SQLObject>();
0612: Iterator it = objectMap.values().iterator();
0613: while (it.hasNext()) {
0614: SQLObject sqlObject = (SQLObject) it.next();
0615: if (sqlObject.getObjectType() == type) {
0616: if (((SQLJoinOperator) sqlObject).isRoot()) {
0617: list.add(sqlObject);
0618: }
0619: }
0620: }
0621: return list;
0622: }
0623:
0624: public RuntimeDatabaseModel getRuntimeDbModel() {
0625: Collection runtimeModels = getObjectsOfType(SQLConstants.RUNTIME_DBMODEL);
0626: if (runtimeModels.size() == 0) {
0627: RuntimeDatabaseModelImpl runtimeDbModel = new RuntimeDatabaseModelImpl();
0628: try {
0629: this .addObject(runtimeDbModel);
0630: } catch (BaseException ex) {
0631: mLogger
0632: .errorNoloc(
0633: mLoc
0634: .t(
0635: "PRSR116: can not add runtime database model to definition{0}",
0636: LOG_CATEGORY), ex);
0637: runtimeDbModel = null;
0638: }
0639: return runtimeDbModel;
0640: }
0641: return (RuntimeDatabaseModel) runtimeModels.iterator().next();
0642: }
0643:
0644: /**
0645: * Gets List of source columns associated with source tables of this model.
0646: *
0647: * @return List of SourceColumn instances
0648: */
0649: public List<DBColumn> getSourceColumns() {
0650: List<DBTable> sTables = getSourceTables();
0651: List<DBColumn> sColumns = new ArrayList<DBColumn>();
0652: for (Iterator<DBTable> it = sTables.iterator(); it.hasNext();) {
0653: sColumns.addAll(it.next().getColumnList());
0654: }
0655: return sColumns;
0656: }
0657:
0658: /**
0659: * Gets List of source DatabaseModels associated with this model.
0660: *
0661: * @return List of DatabaseModels containing source tables
0662: */
0663: public List<SQLDBModel> getSourceDatabaseModels() {
0664: List<SQLDBModel> sourceModels = new ArrayList<SQLDBModel>();
0665: Iterator it = getObjectsOfType(SQLConstants.SOURCE_DBMODEL)
0666: .iterator();
0667: while (it.hasNext()) {
0668: sourceModels.add((SQLDBModel) it.next());
0669: }
0670: return sourceModels;
0671: }
0672:
0673: /**
0674: * Gets List of source tables participating in this model.
0675: *
0676: * @return List of instances
0677: */
0678: public List<DBTable> getSourceTables() {
0679: Collection sDBModel = getObjectsOfType(SQLConstants.SOURCE_DBMODEL);
0680: List<DBTable> sTables = new ArrayList<DBTable>();
0681: for (Iterator it = sDBModel.iterator(); it.hasNext();) {
0682: SQLDBModel dbModel = (SQLDBModel) it.next();
0683: sTables.addAll(dbModel.getTables());
0684: }
0685: return sTables;
0686: }
0687:
0688: /**
0689: * Given a column find out the filters when the given column is used in left or right
0690: * of it.
0691: *
0692: * @param sColumn sourceColumn
0693: * @return list of filters which have reference to these columns
0694: */
0695: public List<SQLFilter> getSQLFilterFor(SourceColumn sColumn) {
0696: List<SQLFilter> filterList = new ArrayList<SQLFilter>();
0697: Collection filters = getObjectsOfType(SQLConstants.FILTER);
0698: Iterator it = filters.iterator();
0699: while (it.hasNext()) {
0700: SQLFilter filter = (SQLFilter) it.next();
0701: SQLObject leftObj = filter.getSQLObject(SQLFilter.LEFT);
0702: SQLObject rightObj = filter.getSQLObject(SQLFilter.RIGHT);
0703:
0704: if (leftObj != null && leftObj.equals(sColumn)
0705: || rightObj != null && rightObj.equals(sColumn)) {
0706: filterList.add(filter);
0707: }
0708: }
0709: return filterList;
0710: }
0711:
0712: public SQLFrameworkParentObject getSQLFrameworkParentObject() {
0713: return mParent;
0714: }
0715:
0716: /**
0717: * get the tag name for this SQLDefinition override at subclass level to return a
0718: * different tag name
0719: *
0720: * @return tag name to be used in xml representation of this object
0721: */
0722: public String getTagName() {
0723: return SQLDefinitionImpl.TAG_DEFINITION;
0724: }
0725:
0726: /**
0727: * Gets List of target columns associated with target tables of this model.
0728: *
0729: * @return List of TargetColumn instances
0730: */
0731: public List<DBColumn> getTargetColumns() {
0732: Collection<DBTable> tTables = getTargetTables();
0733: List<DBColumn> tColumns = new ArrayList<DBColumn>();
0734: for (Iterator<DBTable> it = tTables.iterator(); it.hasNext();) {
0735: DBTable table = it.next();
0736: tColumns.addAll(table.getColumnList());
0737: }
0738: return tColumns;
0739: }
0740:
0741: /**
0742: * Gets List of target DatabaseModels associated with this model.
0743: *
0744: * @return List of DatabaseModels containing target tables
0745: */
0746: public List<SQLDBModel> getTargetDatabaseModels() {
0747: List<SQLDBModel> targetModels = new ArrayList<SQLDBModel>();
0748: Iterator it = getObjectsOfType(SQLConstants.TARGET_DBMODEL)
0749: .iterator();
0750: while (it.hasNext()) {
0751: targetModels.add((SQLDBModel) it.next());
0752: }
0753: return targetModels;
0754: }
0755:
0756: /**
0757: * Gets List of target tables participating in this model.
0758: *
0759: * @return List of TargetTable instances
0760: */
0761: public List<DBTable> getTargetTables() {
0762: Collection tDBModel = getObjectsOfType(SQLConstants.TARGET_DBMODEL);
0763: List<DBTable> tTables = new ArrayList<DBTable>();
0764: for (Iterator it = tDBModel.iterator(); it.hasNext();) {
0765: SQLDBModel dbModel = (SQLDBModel) it.next();
0766: tTables.addAll(dbModel.getTables());
0767: }
0768: return tTables;
0769: }
0770:
0771: public String getVersion() {
0772: return (String) this .getAttributeValue(ATTR_VERSION);
0773: }
0774:
0775: /**
0776: * Overrides default implementation to compute hashcode based on any associated
0777: * attributes as well as values of non-transient member variables.
0778: *
0779: * @return hashcode for this instance
0780: */
0781: @Override
0782: public int hashCode() {
0783: int hashCode = (displayName != null) ? displayName.hashCode()
0784: : 0;
0785: hashCode += objectMap.hashCode();
0786: return hashCode;
0787: }
0788:
0789: /**
0790: * @see org.netbeans.modules.sql.framework.model.SQLDefinition#hasValidationConditions()
0791: */
0792: public boolean hasValidationConditions() {
0793: Iterator it = this .getSourceTables().iterator();
0794: while (it.hasNext()) {
0795: SourceTable table = (SourceTable) it.next();
0796: SQLCondition vCondition = table
0797: .getDataValidationCondition();
0798: if (vCondition != null && vCondition.isConditionDefined()
0799: && vCondition.getRootPredicate() != null) {
0800: return true;
0801: }
0802: }
0803: return false;
0804: }
0805:
0806: /**
0807: * Check if a java operator is used in the model.
0808: *
0809: * @return true if a java operator is used.
0810: */
0811: public boolean isContainsJavaOperators() {
0812: Boolean containsJavaOperators = (Boolean) this
0813: .getAttributeValue(ATTR_CONTAINS_JAVA_OPERATORS);
0814: if (containsJavaOperators != null) {
0815: return containsJavaOperators.booleanValue();
0816: }
0817: return false;
0818: }
0819:
0820: /**
0821: * Check if a table already exists in this definition
0822: *
0823: * @param table - table
0824: * @return the existing object
0825: * @throws BaseException - exception
0826: */
0827: public Object isTableExists(DBTable table) throws BaseException {
0828: SQLDBModel dbModel = getExistingDatabaseModelFor((SQLDBTable) table);
0829: if (dbModel != null) {
0830: // Check for duplication
0831: DBTable existing = dbModel.getTable(dbModel
0832: .getFullyQualifiedTableName(table));
0833: return existing;
0834: }
0835: return null;
0836: }
0837:
0838: /**
0839: * @see org.netbeans.modules.sql.framework.model.SQLDefinition#migrateFromOlderVersions()
0840: */
0841: public void migrateFromOlderVersions() throws BaseException {
0842: // Upgrade version string to current value
0843: this .setAttribute(ATTR_VERSION, VERSION);
0844: }
0845:
0846: public void overrideCatalogNamesForDb(Map overrideMapMap) {
0847: if (overrideMapMap != null) {
0848: List dbModels = this .getAllDatabases();
0849: Iterator itr = dbModels.iterator();
0850: SQLDBModel dbModel = null;
0851: Map catalogOverride = null;
0852: StringBuilder sb = null;
0853: while (itr.hasNext()) {
0854: dbModel = (SQLDBModel) itr.next();
0855: // sb = new StringBuilder(dbModel.getSource().getOID());
0856: sb = new StringBuilder();
0857: if (dbModel.getObjectType() == SQLConstants.SOURCE_DBMODEL) {
0858: sb.append(SQLConstants.SOURCE_DB_MODEL_NAME_SUFFIX);
0859: } else {
0860: sb.append(SQLConstants.TARGET_DB_MODEL_NAME_SUFFIX);
0861: }
0862:
0863: catalogOverride = (Map) overrideMapMap.get(sb
0864: .toString());
0865: if (catalogOverride != null) {
0866: dbModel.overrideCatalogNames(catalogOverride);
0867: }
0868: }
0869: }
0870: }
0871:
0872: public void overrideSchemaNamesForDb(Map overrideMapMap) {
0873: if (overrideMapMap != null) {
0874: List dbModels = this .getAllDatabases();
0875: Iterator itr = dbModels.iterator();
0876: SQLDBModel dbModel = null;
0877: Map catalogOverride = null;
0878: StringBuilder sb = null;
0879: while (itr.hasNext()) {
0880: dbModel = (SQLDBModel) itr.next();
0881: sb = new StringBuilder();
0882: if (dbModel.getObjectType() == SQLConstants.SOURCE_DBMODEL) {
0883: sb.append(SQLConstants.SOURCE_DB_MODEL_NAME_SUFFIX);
0884: } else {
0885: sb.append(SQLConstants.TARGET_DB_MODEL_NAME_SUFFIX);
0886: }
0887:
0888: catalogOverride = (Map) overrideMapMap.get(sb
0889: .toString());
0890: if (catalogOverride != null) {
0891: dbModel.overrideSchemaNames(catalogOverride);
0892: }
0893: }
0894: }
0895: }
0896:
0897: /**
0898: * Parses the XML content, if any, using the given Element as a source for
0899: * reconstituting the member variables and collections of this instance.
0900: *
0901: * @param xmlElement DOM element containing XML marshalled version of a SQLDefinition
0902: * instance
0903: * @exception BaseException thrown while parsing XML, or if xmlElement is null
0904: */
0905: public void parseXML(Element xmlElement) throws BaseException {
0906: NodeList list;
0907:
0908: if (xmlElement == null) {
0909: throw new BaseException("xmlElement is null");
0910: }
0911:
0912: // displayName - String
0913: this .displayName = xmlElement
0914: .getAttribute(SQLDefinition.ATTR_DISPLAYNAME);
0915:
0916: list = xmlElement.getChildNodes();
0917: attributes.putAll(parseAttributeList(list));
0918:
0919: list = xmlElement.getElementsByTagName(SQLDBModel.MODEL_TAG);
0920: parseDatabaseModels(list);
0921:
0922: list = xmlElement
0923: .getElementsByTagName(RuntimeDatabaseModel.RUNTIME_MODEL_TAG);
0924: parseRuntimeDatabaseModels(list);
0925:
0926: list = xmlElement.getChildNodes();
0927: parseXML(list);
0928: doSecondPassParse();
0929: }
0930:
0931: /**
0932: * Remove all objects from this container
0933: */
0934: public void removeAllObjects() {
0935: this .objectMap.clear();
0936: }
0937:
0938: /**
0939: * Removes given SQLObject instance from this SQLDefinition.
0940: *
0941: * @param sqlObj instance to remove
0942: * @throws BaseException if error occurs during removal
0943: */
0944: public void removeObject(SQLObject sqlObj) throws BaseException {
0945: // check if it is a table object
0946: if (sqlObj == null) {
0947: throw new BaseException("Can not delete null object");
0948: }
0949:
0950: switch (sqlObj.getObjectType()) {
0951: case SQLConstants.SOURCE_TABLE:
0952: case SQLConstants.TARGET_TABLE:
0953: case SQLConstants.RUNTIME_INPUT:
0954: case SQLConstants.RUNTIME_OUTPUT:
0955: deleteTable((SQLDBTable) sqlObj);
0956: break;
0957: case SQLConstants.JOIN_VIEW:
0958: // remove tables used in join view
0959: SQLJoinView joinView = (SQLJoinView) sqlObj;
0960: Iterator sTables = joinView.getSourceTables().iterator();
0961: while (sTables.hasNext()) {
0962: deleteTable((SQLDBTable) sTables.next());
0963: }
0964: // now remove join view
0965: objectMap.remove(sqlObj.getId());
0966: break;
0967: default:
0968: objectMap.remove(sqlObj.getId());
0969: }
0970: }
0971:
0972: /**
0973: * Removes given SQLObjects from SQLDefinition collection.
0974: *
0975: * @param sqlObjects to be removed
0976: * @throws BaseException while removing
0977: */
0978: public void removeObjects(Collection sqlObjs) throws BaseException {
0979: if (sqlObjs == null) {
0980: throw new BaseException("Can not delete null object");
0981: }
0982:
0983: Iterator itr = sqlObjs.iterator();
0984: while (itr.hasNext()) {
0985: this .removeObject((SQLObject) itr.next());
0986: }
0987: }
0988:
0989: /**
0990: * remove SQL object listener
0991: *
0992: * @param listener SQL object listener
0993: */
0994: public synchronized void removeSQLObjectListener(
0995: SQLObjectListener listener) {
0996: listeners.remove(listener);
0997: }
0998:
0999: /**
1000: * check if we have to use axion database if definition contains a java operator or
1001: * there is a validation condition on one of source tables.
1002: *
1003: * @return
1004: */
1005: // TODO: Find java operator using visitor
1006: public boolean requiresPipelineProcess() {
1007: if (SQLDefinition.EXECUTION_STRATEGY_PIPELINE == getExecutionStrategyCode()
1008: .intValue()) {
1009: return true;
1010: }
1011:
1012: if (isContainsJavaOperators()) {
1013: return true;
1014: }
1015:
1016: SQLOperatorInfoVisitor oInfoVisitor = new SQLOperatorInfoVisitor();
1017: oInfoVisitor.visit(this );
1018: if ((oInfoVisitor.isJavaOperatorFound())
1019: || (oInfoVisitor.isValidationConditionFound())) {
1020: return true;
1021: }
1022:
1023: return false;
1024: }
1025:
1026: /**
1027: * @see SQLObject#setAttribute
1028: */
1029: public void setAttribute(String attrName, Object val) {
1030: Attribute attr = getAttribute(attrName);
1031: if (attr != null) {
1032: attr.setAttributeValue(val);
1033: } else {
1034: attr = new Attribute(attrName, val);
1035: attributes.put(attrName, attr);
1036: }
1037: }
1038:
1039: /**
1040: * set it to true if a java operator is used in the model
1041: *
1042: * @param javaOp true if there is a java operator
1043: */
1044: public void setContainsJavaOperators(boolean javaOp) {
1045: this .setAttribute(ATTR_CONTAINS_JAVA_OPERATORS, Boolean
1046: .valueOf(javaOp));
1047: }
1048:
1049: /**
1050: * Sets display name to given value.
1051: *
1052: * @param newName new display name
1053: */
1054: public void setDisplayName(String newName) {
1055: displayName = newName;
1056: }
1057:
1058: public void setExecutionStrategyCode(Integer code) {
1059: this .setAttribute(ATTR_EXECUTION_STRATEGY_CODE, code);
1060: }
1061:
1062: /**
1063: * sets the axion database working folder
1064: * @param appDataRoot
1065: */
1066: public void setWorkingFolder(String appDataRoot) {
1067: this .setAttribute(AXION_DB_WORKING_FOLDER, appDataRoot);
1068: }
1069:
1070: /**
1071: * sets the axion database instance name
1072: * @param dbInstanceName
1073: */
1074: public void setDbInstanceName(String dbInstanceName) {
1075: this .setAttribute(AXION_DB_INSTANCE_NAME, dbInstanceName);
1076: }
1077:
1078: /**
1079: * @see SQLDefinition#setParent
1080: */
1081: public void setParent(Object newParent) {
1082: if (newParent == null) {
1083: throw new IllegalArgumentException(
1084: "Must supply non-null reference for Parent Object.");
1085: }
1086: this .parent = newParent;
1087: }
1088:
1089: public void setSQLFrameworkParentObject(
1090: SQLFrameworkParentObject aParent) {
1091: mParent = aParent;
1092: }
1093:
1094: public void setVersion(String newVersion) {
1095: if (getVersionInt(getVersion()) < getVersionInt(newVersion)) {
1096: this .setAttribute(ATTR_VERSION, newVersion);
1097: }
1098: }
1099:
1100: /**
1101: * Gets the XML representation of this SQLDefinition.
1102: *
1103: * @return Returns the XML representation of this SQLDefinition.
1104: */
1105: public String toXMLString() throws BaseException {
1106: return toXMLString("");
1107: }
1108:
1109: /**
1110: * Gets the XML representation of this SQLDefinition, using the given String as a
1111: * prefix for individual XML elements.
1112: *
1113: * @param prefix indent string to prefix each element in the xml document.
1114: * @return the XML representation of this SQLDefinition.
1115: */
1116: public String toXMLString(String prefix) throws BaseException {
1117: if (prefix == null) {
1118: prefix = "";
1119: }
1120:
1121: StringBuilder xml = new StringBuilder(500);
1122: xml.append(prefix).append("<").append(getTagName());
1123:
1124: xml.append(" " + ATTR_DISPLAYNAME + "=\"");
1125: if (displayName != null) {
1126: xml.append(displayName.trim());
1127: }
1128: xml.append("\" >\n");
1129:
1130: // write out attributes
1131: xml.append(toXMLAttributeTags(prefix));
1132:
1133: xml.append(toXMLString(prefix, objectMap.values()));
1134: xml.append(toXMLExtra(prefix + "\t"));
1135: xml.append(prefix).append("</").append(getTagName()).append(
1136: ">\n");
1137:
1138: XmlUtil.dumpXMLString(
1139: "Definition_" + getDisplayName() + ".xml", xml
1140: .toString());
1141: return xml.toString();
1142: }
1143:
1144: /**
1145: * validate the definition starting from the target tables.
1146: *
1147: * @return Map of invalid input object as keys and reason as value
1148: */
1149: public List<ValidationInfo> validate() {
1150: // TODO: Need to validate the drivers, file location used for data file
1151: List<ValidationInfo> valInfo = validateDbDrivers();
1152: if (valInfo.size() == 0) { // Found driver errors. don't proceed with other validation.
1153: valInfo.addAll(validateDbSynchronization()); // Validate Database Synchronization
1154: }
1155:
1156: // General eTL Collaboration validation
1157: SQLValidationVisitor vVisitor = new SQLValidationVisitor();
1158: vVisitor.visit(this );
1159: valInfo.addAll(vVisitor.getValidationInfoList());
1160:
1161: // Operator usage validation.
1162: SQLOperatorInfoVisitor opInfo = new SQLOperatorInfoVisitor(true);
1163: opInfo.visit(this );
1164: valInfo.addAll(opInfo.getValidationInfoList());
1165:
1166: // Filter condition validation
1167: valInfo = ConditionBuilderUtil.filterValidations(valInfo);
1168: return valInfo;
1169: }
1170:
1171: /**
1172: * validate the definition starting from the target tables.
1173: *
1174: * @return Map of invalid input object as keys and reason as value
1175: */
1176: public List<ValidationInfo> badgeValidate() {
1177: // TODO: Need to validate the drivers, file location used for data file
1178: List<ValidationInfo> valInfo = validateDbDrivers();
1179:
1180: // General eTL Collaboration validation
1181: SQLValidationVisitor vVisitor = new SQLValidationVisitor();
1182: vVisitor.visit(this );
1183: valInfo.addAll(vVisitor.getValidationInfoList());
1184:
1185: // Operator usage validation.
1186: SQLOperatorInfoVisitor opInfo = new SQLOperatorInfoVisitor(true);
1187: opInfo.visit(this );
1188: valInfo.addAll(opInfo.getValidationInfoList());
1189:
1190: // Filter condition validation
1191: valInfo = ConditionBuilderUtil.filterValidations(valInfo);
1192: return valInfo;
1193: }
1194:
1195: /**
1196: * Validates if the Database drivers required for this SQLDefinition are
1197: * already installed in Database Explorer.
1198: *
1199: * @return Map of invalid object as keys and reason as value
1200: */
1201: public List<ValidationInfo> validateDbDrivers() {
1202: SQLDBDriverValidationVisitor vVisitor = new SQLDBDriverValidationVisitor();
1203: vVisitor.visit(this );
1204: return vVisitor.getValidationInfoList();
1205: }
1206:
1207: /**
1208: * Validate Database synchronization. Identify any eTL Collaboration element which has been
1209: * deleted or modified in Database.
1210: *
1211: * @return Map of invalid object as keys and reason as value
1212: */
1213: public List<ValidationInfo> validateDbSynchronization() {
1214: SQLDBSynchronizationValidationVisitor vVisitor = new SQLDBSynchronizationValidationVisitor();
1215: vVisitor.visit(this );
1216: return vVisitor.getValidationInfoList();
1217: }
1218:
1219: public void visit(SQLVisitor visitor) {
1220: visitor.visit(this );
1221: }
1222:
1223: boolean isIdExists(String id) {
1224: if (id == null) {
1225: return false;
1226: }
1227:
1228: SQLObject existingObj = getObjectFromDBModel(id,
1229: SQLConstants.SOURCE_DBMODEL);
1230: if (existingObj == null) {
1231: existingObj = getObjectFromDBModel(id,
1232: SQLConstants.TARGET_DBMODEL);
1233: }
1234:
1235: // check if object is in runtime model
1236: if (existingObj == null) {
1237: existingObj = getObjectFromDBModel(id,
1238: SQLConstants.RUNTIME_DBMODEL);
1239: }
1240:
1241: if (existingObj != null) {
1242: return true;
1243: }
1244:
1245: Collection ids = objectMap.keySet();
1246: if (ids.contains(id)) {
1247: return true;
1248: }
1249:
1250: return false;
1251: }
1252:
1253: protected void init() {
1254: this .setAttribute(ATTR_VERSION, VERSION);
1255: if (this .getAttributeValue(ATTR_EXECUTION_STRATEGY_CODE) == null) {
1256: setExecutionStrategyCode(new Integer(
1257: EXECUTION_STRATEGY_DEFAULT));
1258: }
1259: }
1260:
1261: protected void setSQLObjectProperties(SQLObject obj) {
1262: if (obj instanceof SourceTable) {
1263: SourceTable sTable = (SourceTable) obj;
1264: sTable.setTemporaryTableName(SQLObjectUtil
1265: .generateTemporaryTableName(sTable.getName()));
1266: } else if (obj instanceof SQLJoinView) {
1267: SQLJoinView joinView = (SQLJoinView) obj;
1268: joinView.setAliasName(generateJoinViewAliasName());
1269: }
1270: }
1271:
1272: /**
1273: * Generates XML elements representing this object's associated attributes.
1274: *
1275: * @param prefix Prefix string to be prepended to each element
1276: * @return String containing XML representation of attributes
1277: */
1278: protected String toXMLAttributeTags(String prefix) {
1279: StringBuilder buf = new StringBuilder(100);
1280: for (Iterator iter = attributes.values().iterator(); iter
1281: .hasNext();) {
1282: Attribute attr = (Attribute) iter.next();
1283: if (attr.getAttributeValue() != null) {
1284: buf.append(attr.toXMLString(prefix + "\t"));
1285: }
1286: }
1287: return buf.toString();
1288: }
1289:
1290: /**
1291: * Provides a way for child classes to write out their own XML elements.
1292: *
1293: * @param prefix - prefix
1294: * @return a string
1295: */
1296: protected String toXMLExtra(String prefix) {
1297: return "";
1298: }
1299:
1300: private void add(SQLObject newObject) throws BaseException {
1301: // Make sure an object added has unique id: first check if id exists if yes
1302: // generate a unique id then add the object
1303: if (newObject.getId() == null) {
1304: newObject.setId(generateId());
1305: }
1306: objectMap.put(newObject.getId(), newObject);
1307: newObject.setParentObject(this );
1308: }
1309:
1310: private void addTable(SQLDBTable table) throws BaseException {
1311: // before adding a table we should create alias name and set it to table
1312: if (table.getAliasName() == null) {
1313: if (table.getObjectType() == SQLConstants.SOURCE_TABLE) {
1314: table.setAliasName(this .generateSourceTableAliasName());
1315: } else if (table.getObjectType() == SQLConstants.TARGET_TABLE) {
1316: table.setAliasName(this .generateTargetTableAliasName());
1317: }
1318: }
1319:
1320: boolean createDBModel = false;
1321: SQLDBModel dbModel = getExistingDatabaseModelFor(table);
1322: if (dbModel != null) {
1323: // Check for duplication; don't add if it's already there.
1324: DBTable existing = dbModel.getTable(dbModel
1325: .getFullyQualifiedTableName(table));
1326: if (existing != null) {
1327: if (table.getObjectType() == SQLConstants.TARGET_TABLE) {
1328: throw new BaseException("Table '"
1329: + dbModel.getFullyQualifiedTableName(table)
1330: + "' already exists on the canvas.");
1331: }
1332: createDBModel = true;
1333: } else {
1334: dbModel.addTable(table);
1335: // Add table first, then call setTableId to ensure IDs are added
1336: // correctly for all elements.
1337: List<SQLDBTable> list = new ArrayList<SQLDBTable>();
1338: list.add(table);
1339: setTableId(list);
1340: return;
1341: }
1342: } else {
1343: createDBModel = true;
1344: }
1345:
1346: if (createDBModel) {
1347: DatabaseModel dbModelParent = null;
1348:
1349: switch (table.getObjectType()) {
1350: case SQLConstants.SOURCE_TABLE:
1351: dbModelParent = table.getParent();
1352: dbModel = SQLModelObjectFactory.getInstance()
1353: .createDBModel(dbModelParent,
1354: SQLConstants.SOURCE_DBMODEL, mParent);
1355: break;
1356: case SQLConstants.TARGET_TABLE:
1357: dbModelParent = table.getParent();
1358: dbModel = SQLModelObjectFactory.getInstance()
1359: .createDBModel(table.getParent(),
1360: SQLConstants.TARGET_DBMODEL, mParent);
1361: break;
1362: case SQLConstants.RUNTIME_INPUT:
1363: case SQLConstants.RUNTIME_OUTPUT:
1364: dbModel = SQLModelObjectFactory.getInstance()
1365: .createRuntimeDatabaseModel();
1366: break;
1367: default:
1368: throw new BaseException("Unknown table type ("
1369: + table.getObjectType() + ")");
1370: }
1371:
1372: // No existing database model found...add the table's parent, after
1373: // clearing all cloned tables then adding back the table in question.
1374: dbModel.setParentObject(this );
1375: dbModel.deleteAllTables();
1376: dbModel.addTable(table);
1377: addObject(dbModel);
1378: }
1379: }
1380:
1381: /**
1382: * Makes a deep copy of the given SQLConnectableObject and adds it to the given
1383: * SQLCondition.
1384: *
1385: * @param object SQLConnectableObject to be deep-copied
1386: * @param condition SQLCondition in which to add <code>object</code>
1387: * @return copy of <code>object</code>
1388: */
1389: private SQLObject copyExpressionObject(SQLConnectableObject object,
1390: SQLCondition condition) throws BaseException {
1391: int objectType = object.getObjectType();
1392: switch (objectType) {
1393: case SQLConstants.VISIBLE_PREDICATE: {
1394: VisibleSQLPredicate visiblePredCopy = null;
1395: if (object instanceof VisibleMatchesPredicateImpl) {
1396: visiblePredCopy = new VisibleMatchesPredicateImpl(
1397: (VisibleMatchesPredicateImpl) object);
1398: } else {
1399: visiblePredCopy = new VisibleSQLPredicateImpl();
1400: ((VisibleSQLPredicateImpl) visiblePredCopy)
1401: .copyFrom((VisibleSQLPredicate) object);
1402: }
1403:
1404: copyNonStaticInputs(visiblePredCopy, condition,
1405: visiblePredCopy.getOperatorXmlInfo());
1406: return visiblePredCopy;
1407: }
1408: case SQLConstants.PREDICATE: {
1409: SQLPredicateImpl predCopy = new VisibleSQLPredicateImpl();
1410: predCopy.copyFrom((VisibleSQLPredicate) object);
1411:
1412: copyNonStaticInputs(predCopy, condition, predCopy
1413: .getOperatorXmlInfo());
1414: return predCopy;
1415: }
1416: case SQLConstants.GENERIC_OPERATOR:
1417: try {
1418: if (object instanceof SQLNormalizeOperatorImpl) {
1419: SQLNormalizeOperatorImpl newOp = new SQLNormalizeOperatorImpl(
1420: (SQLNormalizeOperatorImpl) object);
1421:
1422: copyNonStaticInputs(newOp, condition, newOp
1423: .getOperatorXmlInfo());
1424: return newOp;
1425: } else if (object instanceof SQLStandardizeOperatorImpl) {
1426: SQLStandardizeOperatorImpl newOp = new SQLStandardizeOperatorImpl(
1427: (SQLStandardizeOperatorImpl) object);
1428:
1429: copyNonStaticInputs(newOp, condition, newOp
1430: .getOperatorXmlInfo());
1431: return newOp;
1432: }
1433: } catch (CloneNotSupportedException e) {
1434: throw new BaseException(e);
1435: }
1436:
1437: SQLGenericOperatorImpl newOp = new SQLGenericOperatorImpl(
1438: (SQLGenericOperator) object);
1439: copyNonStaticInputs(newOp, condition, newOp
1440: .getOperatorXmlInfo());
1441: return newOp;
1442: case SQLConstants.CUSTOM_OPERATOR:
1443: SQLCustomOperatorImpl newCustopr = new SQLCustomOperatorImpl(
1444: (SQLCustomOperatorImpl) object);
1445: copyNonStaticInputs(newCustopr, condition, newCustopr
1446: .getOperatorXmlInfo());
1447: return newCustopr;
1448: default:
1449: String typeStr = TagParserUtility
1450: .getDisplayStringFor(objectType);
1451: throw new BaseException(
1452: "Copying of this expression object type ("
1453: + typeStr + ") is not currently supported.");
1454: }
1455: }
1456:
1457: /**
1458: * Copies all non-static inputs of the given SQLConnectableObject into the given
1459: * SQLCondition, depending on the argument information contained in the given
1460: * IOperatorXmlInfo instance.
1461: *
1462: * @param expObj SQLConnectableObject whose inputs are to be evaluated and copied as
1463: * necessary
1464: * @param condition SQLCondition in which non-static inputs of <code>expObj</code>
1465: * will be added
1466: * @param operatorInfo IOperatorXmlInfo containing info on the static or non-static
1467: * nature of input arguments in <code>expObj</code>
1468: * @throws BaseException if error occurs while resolving or copying input objects
1469: */
1470: private void copyNonStaticInputs(SQLConnectableObject expObj,
1471: SQLCondition condition, IOperatorXmlInfo operatorInfo)
1472: throws BaseException {
1473: Map inputObjects = expObj.getInputObjectMap();
1474: for (Iterator iter = inputObjects.values().iterator(); iter
1475: .hasNext();) {
1476: SQLInputObject inputObj = (SQLInputObject) iter.next();
1477: String argName = inputObj.getArgName();
1478: IOperatorField fieldInfo = operatorInfo
1479: .getInputField(argName);
1480: if (fieldInfo != null && !fieldInfo.isStatic()) {
1481: Object input = resolveInputObject(inputObj, condition);
1482: if (expObj instanceof SQLPredicate
1483: && input instanceof SQLPredicate) {
1484: ((SQLPredicate) input)
1485: .setRoot((SQLPredicate) expObj);
1486: }
1487: }
1488: }
1489: }
1490:
1491: private void deleteTable(SQLDBTable table) throws BaseException {
1492: SQLDBModel dbModel = (SQLDBModel) table.getParent();
1493: dbModel.deleteTable(dbModel.getFullyQualifiedTableName(table));
1494: if (dbModel.getTables().size() == 0) {
1495: removeObject(dbModel);
1496: }
1497: }
1498:
1499: private void discoverSourceTables(SQLObject sqlObj,
1500: List<DBTable> tables) {
1501: SQLJoinOperator joinObject = (SQLJoinOperator) sqlObj;
1502: SQLObject left = joinObject.getSQLObject(SQLJoinOperator.LEFT);
1503: SQLObject right = joinObject
1504: .getSQLObject(SQLJoinOperator.RIGHT);
1505:
1506: if (left.getObjectType() == SQLConstants.SOURCE_TABLE) {
1507: tables.add((DBTable) left);
1508: } else {
1509: discoverSourceTables(left, tables);
1510: }
1511:
1512: if (right.getObjectType() == SQLConstants.SOURCE_TABLE) {
1513: tables.add((DBTable) right);
1514: } else {
1515: discoverSourceTables(right, tables);
1516: }
1517: }
1518:
1519: private void doSecondPassParse() throws BaseException {
1520: for (Iterator<SecondParseObjectInfo> it = secondPassList
1521: .iterator(); it.hasNext();) {
1522: SecondParseObjectInfo objInfo = it.next();
1523: objInfo.getSQLObject()
1524: .secondPassParse(objInfo.getElement());
1525: }
1526: secondPassList.clear();
1527: }
1528:
1529: private String generateJoinViewAliasName() {
1530: String aName = J + 0;
1531: for (int cnt = 1; isJoinViewAliasNameExist(aName); cnt++) {
1532: aName = J + cnt;
1533: }
1534: return aName;
1535: }
1536:
1537: private String generateSourceTableAliasName() {
1538: String aName = S + 0;
1539: for (int cnt = 1; isSourceTableAliasNameExist(aName); cnt++) {
1540: aName = S + cnt;
1541: }
1542: return aName;
1543: }
1544:
1545: private String generateTargetTableAliasName() {
1546: String aName = T + 0;
1547: for (int cnt = 1; isTargetTableAliasNameExist(aName); cnt++) {
1548: aName = T + cnt;
1549: }
1550: return aName;
1551: }
1552:
1553: private SQLDBModel getExistingDatabaseModelFor(SQLDBTable table)
1554: throws BaseException {
1555: // if table is RuntimeInput or RuntimeOutput then we want to return runtime db model
1556: if (table.getObjectType() == SQLConstants.RUNTIME_INPUT
1557: || table.getObjectType() == SQLConstants.RUNTIME_OUTPUT) {
1558: return this .getRuntimeDbModel();
1559: }
1560:
1561: // for other tables we need to check if they have a parent db model
1562: DatabaseModel dbModel = table.getParent();
1563: if (dbModel == null) {
1564: return null;
1565: }
1566:
1567: List<SQLDBModel> dbModels;
1568: switch (table.getObjectType()) {
1569: case SQLConstants.SOURCE_TABLE:
1570: dbModels = getSourceDatabaseModels();
1571: break;
1572: case SQLConstants.TARGET_TABLE:
1573: dbModels = getTargetDatabaseModels();
1574: break;
1575: default:
1576: throw new BaseException("Unknown table type ("
1577: + table.getObjectType() + ")");
1578: }
1579:
1580: for (Iterator<SQLDBModel> it = dbModels.iterator(); it
1581: .hasNext();) {
1582: SQLDBModel existingModel = it.next();
1583: if (existingModel.getModelName().equals(
1584: dbModel.getModelName())) {
1585: return existingModel;
1586: }
1587: }
1588: return null;
1589: }
1590:
1591: private SQLObject getObjectFromDBModel(String objectId,
1592: int modelType) {
1593: Collection dbModels = getObjectsOfType(modelType);
1594: for (Iterator it = dbModels.iterator(); it.hasNext();) {
1595: SQLDBModel dbModel = (SQLDBModel) it.next();
1596: SQLObject sqlObj = dbModel.getObject(objectId);
1597: if (sqlObj != null) {
1598: return sqlObj;
1599: }
1600: }
1601: return null;
1602: }
1603:
1604: @SuppressWarnings(value="fallthrough")
1605: private int getVersionInt(String version) {
1606: // starting with 5.0.0.0
1607: int majorVersion = 10000000;
1608: int minorVersion = 100000; // maximum value of minor version number: 99
1609: int pointRelease = 1000; // maximum value of point release number: 99
1610: int internalVersion = 1; // maximum value of internal build number: 999
1611: List versions = StringUtil.createStringListFrom(version, '.');
1612: switch (versions.size()) {
1613: case 4:
1614: internalVersion *= (StringUtil.getInt((String) versions
1615: .get(3)) + 1);
1616: case 3:
1617: pointRelease *= (StringUtil
1618: .getInt((String) versions.get(2)) + 1);
1619: case 2:
1620: minorVersion *= (StringUtil
1621: .getInt((String) versions.get(1)) + 1);
1622: case 1:
1623: majorVersion *= (StringUtil
1624: .getInt((String) versions.get(0)) + 1);
1625: }
1626:
1627: return majorVersion + minorVersion + pointRelease
1628: + internalVersion;
1629: }
1630:
1631: private boolean isJoinViewAliasNameExist(String aName) {
1632: Collection joinViews = this
1633: .getObjectsOfType(SQLConstants.JOIN_VIEW);
1634: for (Iterator it = joinViews.iterator(); it.hasNext();) {
1635: SQLJoinView joinView = (SQLJoinView) it.next();
1636: String sAlias = joinView.getAliasName();
1637: if (sAlias != null && sAlias.equals(aName)) {
1638: return true;
1639: }
1640: }
1641: return false;
1642: }
1643:
1644: private boolean isSourceTableAliasNameExist(String aName) {
1645: for (Iterator it = getSourceTables().iterator(); it.hasNext();) {
1646: SourceTable sTable = (SourceTable) it.next();
1647: String sAlias = sTable.getAliasName();
1648: if (sAlias != null && sAlias.equals(aName)) {
1649: return true;
1650: }
1651: }
1652: return false;
1653: }
1654:
1655: private boolean isTargetTableAliasNameExist(String aName) {
1656: for (Iterator it = getTargetTables().iterator(); it.hasNext();) {
1657: TargetTable tTable = (TargetTable) it.next();
1658: String tAlias = tTable.getAliasName();
1659: if (tAlias != null && tAlias.equals(aName)) {
1660: return true;
1661: }
1662: }
1663: return false;
1664: }
1665:
1666: private Map<String, Attribute> parseAttributeList(NodeList list)
1667: throws BaseException {
1668: Map<String, Attribute> attrMap = new LinkedHashMap<String, Attribute>();
1669: for (int i = 0; i < list.getLength(); i++) {
1670: if (list.item(i).getNodeType() == Node.ELEMENT_NODE) {
1671: Element elem = (Element) list.item(i);
1672: if (elem.getNodeName().equals(Attribute.TAG_ATTR)) {
1673: Attribute attr = new Attribute();
1674: attr.parseXMLString(elem);
1675: attrMap.put(attr.getAttributeName(), attr);
1676: }
1677: }
1678: }
1679: return attrMap;
1680: }
1681:
1682: private void parseDatabaseModels(NodeList list)
1683: throws BaseException {
1684: if (list == null) {
1685: throw new BaseException("Must supply non-null NodeList.");
1686: }
1687:
1688: for (int i = 0; i < list.getLength(); i++) {
1689: Element elem = (Element) list.item(i);
1690: SQLDBModel dbModel = (SQLDBModel) createSQLObject(SQLDBModelImpl.class
1691: .getName());
1692:
1693: dbModel.setParentObject(this );
1694: dbModel.parseXML(elem);
1695: dbModel.setSQLFrameworkParentObject(mParent);
1696: this .addObject(dbModel);
1697: }
1698: }
1699:
1700: private void parseRuntimeDatabaseModels(NodeList list)
1701: throws BaseException {
1702: if (list == null) {
1703: throw new BaseException("Must supply non-null NodeList.");
1704: }
1705:
1706: for (int i = 0; i < list.getLength(); i++) {
1707: Element elem = (Element) list.item(i);
1708: RuntimeDatabaseModel dbModel = (RuntimeDatabaseModel) createSQLObject(RuntimeDatabaseModelImpl.class
1709: .getName());
1710:
1711: dbModel.setParentObject(this );
1712: dbModel.parseXML(elem);
1713: this .addObject(dbModel);
1714: }
1715: }
1716:
1717: private void parseXML(NodeList list) throws BaseException {
1718: for (int i = 0; i < list.getLength(); i++) {
1719: Node node = list.item(i);
1720: if (!node.getNodeName().equals(SQLObject.TAG_SQLOBJECT)) {
1721: continue;
1722: }
1723:
1724: Element opeElem = (Element) node;
1725: SQLObject sqlObj = SQLObjectFactory
1726: .createSQLObjectForElement(this , opeElem);
1727: if (sqlObj != null) {
1728: this .addObject(sqlObj);
1729: } else {
1730: throw new BaseException("Failed to parse " + opeElem);
1731: }
1732: }
1733: }
1734:
1735: /**
1736: * Resolves the given input object, cloning it and adding it to the given SQLCondition
1737: * if necessary.
1738: *
1739: * @param inputObject SQLInputObject to be resolved
1740: * @param condition SQLCondition in which to add the input referenced by
1741: * <code>inputObject</code>
1742: * @return input object that was resolved and added to condition; possibly null
1743: */
1744: private Object resolveInputObject(SQLInputObject inputObject,
1745: SQLCondition condition) throws BaseException {
1746: SQLObject sqlObject = inputObject.getSQLObject();
1747: if (sqlObject != null) {
1748: if (sqlObject.getObjectType() == SQLConstants.SOURCE_COLUMN) {
1749: ColumnRef columnRef = SQLModelObjectFactory
1750: .getInstance().createColumnRef(
1751: (SQLDBColumn) sqlObject);
1752: condition.addObject(columnRef);
1753: inputObject.setSQLObject(columnRef);
1754: } else {
1755: if (sqlObject instanceof SQLConnectableObject) {
1756: sqlObject = copyExpressionObject(
1757: (SQLConnectableObject) sqlObject, condition);
1758: inputObject.setSQLObject(sqlObject);
1759: } else if (sqlObject instanceof VisibleSQLLiteral) {
1760: // Must handle visible flavor before standard one
1761: // Copy VisibleSQLLiteral object into the condition.
1762: VisibleSQLLiteral oldLiteral = (VisibleSQLLiteral) sqlObject;
1763:
1764: VisibleSQLLiteral newLiteral = new VisibleSQLLiteralImpl();
1765: newLiteral.setDisplayName(oldLiteral
1766: .getDisplayName());
1767: newLiteral.setJdbcType(oldLiteral.getJdbcType());
1768: newLiteral.setValue(oldLiteral.getValue());
1769: inputObject.setSQLObject(newLiteral);
1770:
1771: sqlObject = newLiteral;
1772: } else if (sqlObject instanceof SQLLiteral) {
1773: // Copy SQLLiteral object into the condition.
1774: SQLLiteral oldLiteral = (SQLLiteral) sqlObject;
1775:
1776: SQLLiteral newLiteral = new SQLLiteralImpl();
1777: newLiteral.setDisplayName(oldLiteral
1778: .getDisplayName());
1779: newLiteral.setJdbcType(oldLiteral.getJdbcType());
1780: newLiteral.setValue(oldLiteral.getValue());
1781: inputObject.setSQLObject(newLiteral);
1782:
1783: sqlObject = newLiteral;
1784: }
1785:
1786: condition.addObject(sqlObject);
1787: }
1788: }
1789:
1790: return sqlObject;
1791: }
1792:
1793: private void setSQLObjectId(List sqlObjects) throws BaseException {
1794: for (Iterator it = sqlObjects.iterator(); it.hasNext();) {
1795: SQLObject sqlObj = (SQLObject) it.next();
1796: sqlObj.setId(generateId());
1797: }
1798: }
1799:
1800: private void setTableId(List tables) throws BaseException {
1801: for (Iterator it = tables.iterator(); it.hasNext();) {
1802: SQLObject table = (SQLObject) it.next();
1803: if (table.getId() == null) {
1804: table.setId(generateId());
1805: }
1806: setSQLObjectId(((DBTable) table).getColumnList());
1807: }
1808: }
1809:
1810: private String toXMLString(String prefix, Collection sqlObjects)
1811: throws BaseException {
1812: Iterator it = sqlObjects.iterator();
1813: StringBuilder xml = new StringBuilder(" ");
1814:
1815: for (int i = 0; it.hasNext();) {
1816: SQLObject obj = (SQLObject) it.next();
1817: if (obj != null) {
1818: // Add newline between each element, starting after first one.
1819: if (i++ != 0) {
1820: xml.append("\n");
1821: }
1822: xml.append(obj.toXMLString(prefix + "\t"));
1823: }
1824: }
1825: return xml.toString();
1826: }
1827:
1828: public void setExecutionStrategyStr(String text) {
1829: }
1830: }
|