0001: /**
0002: * Objective Database Abstraction Layer (ODAL)
0003: * Copyright (c) 2004, The ODAL Development Group
0004: * All rights reserved.
0005: * For definition of the ODAL Development Group please refer to LICENCE.txt file
0006: *
0007: * Distributable under LGPL license.
0008: * See terms of license at gnu.org.
0009: */package com.completex.objective.components.persistency.core.impl.query;
0010:
0011: import com.completex.objective.components.persistency.AbstractParameters;
0012: import com.completex.objective.components.persistency.BasicQuery;
0013: import com.completex.objective.components.persistency.Cloneable;
0014: import com.completex.objective.components.persistency.CompoundColumnFilter;
0015: import com.completex.objective.components.persistency.Link;
0016: import com.completex.objective.components.persistency.LockType;
0017: import com.completex.objective.components.persistency.OdalRuntimePersistencyException;
0018: import com.completex.objective.components.persistency.Parameter;
0019: import com.completex.objective.components.persistency.ParentBase;
0020: import com.completex.objective.components.persistency.PersistentObject;
0021: import com.completex.objective.components.persistency.PersistentObjectFactory;
0022: import com.completex.objective.components.persistency.Query;
0023: import com.completex.objective.components.persistency.QueryDefinition;
0024: import com.completex.objective.components.persistency.SelectQueryBuilder;
0025: import com.completex.objective.components.persistency.Mappable;
0026: import com.completex.objective.components.persistency.core.DatabasePolicy;
0027: import com.completex.objective.components.persistency.core.Join;
0028: import com.completex.objective.components.persistency.core.Union;
0029: import com.completex.objective.components.persistency.core.UnionMode;
0030: import com.completex.objective.components.persistency.core.impl.JoinImpl;
0031: import com.completex.objective.components.persistency.core.impl.SelectQueryBuilderImpl;
0032: import com.completex.objective.components.persistency.type.AbstractListCollectionFactory;
0033: import com.completex.objective.components.persistency.type.ArrayListCollectionFactory;
0034: import com.completex.objective.components.persistency.type.CollectionFactory;
0035: import com.completex.objective.util.ArrayUtil;
0036: import com.completex.objective.util.PropertyMap;
0037:
0038: import java.io.Serializable;
0039: import java.util.ArrayList;
0040: import java.util.Collection;
0041: import java.util.Collections;
0042: import java.util.List;
0043: import java.util.Set;
0044: import java.util.Map;
0045: import java.util.LinkedHashMap;
0046: import java.util.Arrays;
0047:
0048: /**
0049: * Class to keep query meta data
0050: *
0051: * @author Gennady Krizhevsky
0052: */
0053: public class QueryDefinitionImpl implements QueryDefinition, Cloneable,
0054: Serializable, Mappable {
0055: static final long serialVersionUID = 1L;
0056: private static final AbstractListCollectionFactory DEFAULT_MULTIPLE_RESULT_FACTORY = ArrayListCollectionFactory
0057: .factory();
0058: private transient SelectQueryBuilder queryBuilder = new SelectQueryBuilderImpl();
0059: private transient PersistentObjectFactory singularResultFactory;
0060: private transient CollectionFactory multipleResultFactory = DEFAULT_MULTIPLE_RESULT_FACTORY;
0061:
0062: private List select;
0063: private List from;
0064: private StringBuffer where;
0065: private List orderBy;
0066: private List groupBy;
0067: private StringBuffer having;
0068: private boolean distinct;
0069: private int limitMin;
0070: private int limitMax;
0071: private LockType locked = LockType.NONE;
0072: private String[] forUpdateOf;
0073: private String sql;
0074: private String key;
0075: private CompoundColumnFilter columnFilter = CompoundColumnFilter.NULL_COLUMN_FILTER;
0076: private boolean useColumnNames;
0077: private boolean useSelectStar;
0078: private long timeout;
0079: private boolean disconnectedPageQuery;
0080: private JoinImpl join;
0081: private UnionImpl union;
0082: private boolean compiled;
0083: private ArrayList chainedColumns; // List <ChainedColumn>
0084: private transient Set usedTableAliases = Collections.EMPTY_SET; // aliases provided for combined inline query used by the parent inline query.
0085: private transient boolean combinedInline;
0086:
0087: private transient DatabasePolicy databasePolicy;
0088:
0089: //
0090: // Call related:
0091: //
0092: private boolean call;
0093: private String callBody;
0094: private boolean function;
0095: private boolean externalSetSql;
0096: //
0097: // Constants
0098: //
0099: public static final ChainedColumn[] EMPTY_CHAINED_COLUMN_ARRAY = new ChainedColumn[0];
0100: private static final String TAG_SELECT = "select";
0101: private static final String TAG_FROM = "from";
0102: private static final String TAG_WHERE = "where";
0103: private static final String TAG_ORDER_BY = "orderBy";
0104: private static final String TAG_GROUP_BY = "groupBy";
0105: private static final String TAG_HAVING = "having";
0106: private static final String TAG_DISTINCT = "distinct";
0107: private static final String TAG_LIMIT_MIN = "limitMin";
0108: private static final String TAG_LIMIT_MAX = "limitMax";
0109: private static final String TAG_LOCKED = "locked";
0110: private static final String TAG_SQL = "sql";
0111: private static final String TAG_KEY = "key";
0112: private static final String TAG_COLUMN_FILTER = "columnFilter";
0113: private static final String TAG_USE_COLUMN_NAMES = "useColumnNames";
0114: private static final String TAG_USE_SELECT_STAR = "useSelectStar";
0115: private static final String TAG_TIMEOUT = "timeout";
0116: private static final String TAG_DISCONNECTED_PAGE_QUERY = "disconnectedPageQuery";
0117: private static final String TAG_JOIN = "join";
0118: private static final String TAG_UNION = "union";
0119: private static final String TAG_COMPILED = "compiled";
0120: private static final String TAG_CHAINED_COLUMNS = "chainedColumns";
0121: private static final String TAG_FOR_UPDATE_OF = "forUpdateOf";
0122: public static final String TAG_SINGULAR_RESULT_FACTORY = "singularResultFactory";
0123: public static final String TAG_MULTIPLE_RESULT_FACTORY = "multipleResultFactory";
0124: public static final String TAG_CALL = "call";
0125:
0126: QueryDefinitionImpl() {
0127: }
0128:
0129: public QueryDefinitionImpl(Map map) {
0130: fromMap(map);
0131: }
0132:
0133: public void setSingularResultFactory(
0134: PersistentObjectFactory singularResultFactory) {
0135: this .singularResultFactory = singularResultFactory;
0136: }
0137:
0138: public Link toLink() {
0139: return null;
0140: }
0141:
0142: public String getSql() {
0143: return sql;
0144: }
0145:
0146: public QueryDefinition setSql(String sql) {
0147: ensureImmutable();
0148: this .sql = sql;
0149: this .externalSetSql = true;
0150: return this ;
0151: }
0152:
0153: public boolean isExternallySetSql() {
0154: return externalSetSql;
0155: }
0156:
0157: public void setSqlInternal(String sql) {
0158: this .sql = sql;
0159: }
0160:
0161: public boolean isResultCompound() {
0162: return this .singularResultFactory != null
0163: && this .singularResultFactory.compound();
0164: }
0165:
0166: public void nullifySingularResultFactory() {
0167: this .singularResultFactory = null;
0168: }
0169:
0170: public PersistentObjectFactory getSingularResultFactory() {
0171: return singularResultFactory;
0172: }
0173:
0174: public boolean isDisconnectedPageQuery() {
0175: return disconnectedPageQuery;
0176: }
0177:
0178: public void setDisconnectedPageQuery(boolean disconnectedPageQuery) {
0179: ensureImmutable();
0180: this .disconnectedPageQuery = disconnectedPageQuery;
0181: }
0182:
0183: public Collection newMultipleResult() {
0184: try {
0185: return getMultipleResultFactory().newCollection();
0186: } catch (Exception e) {
0187: new RuntimeException(
0188: "Cannot get newQuery of MultipleResult", e);
0189: }
0190: return null;
0191: }
0192:
0193: public CollectionFactory getMultipleResultFactory() {
0194: return multipleResultFactory;
0195: }
0196:
0197: public void setMultipleResultFactory(
0198: CollectionFactory multipleResultFactory) {
0199: ensureImmutable();
0200: if (multipleResultFactory != null) {
0201: this .multipleResultFactory = multipleResultFactory;
0202: } else {
0203: throw new NullPointerException(
0204: "multipleResultFactory may not be null");
0205: }
0206: }
0207:
0208: public QueryDefinition addToOrderBy(String columnExpression) {
0209: return addToOrderBy(columnExpression, null);
0210: }
0211:
0212: public QueryDefinition addToOrderBy(String columnExpression,
0213: BasicQuery.OrderDirection direction) {
0214: ensureImmutable();
0215: if (columnExpression == null || columnExpression.length() == 0) {
0216: return this ;
0217: }
0218: if (direction == Query.ORDER_DESC) {
0219: columnExpression = columnExpression + BasicQuery.DESC;
0220: }
0221: if (orderBy == null) {
0222: orderBy = new ArrayList();
0223: }
0224: orderBy.add(columnExpression);
0225: return this ;
0226: }
0227:
0228: public String[] getOrderBy() {
0229: return (String[]) (orderBy == null ? null : orderBy
0230: .toArray(new String[orderBy.size()]));
0231: }
0232:
0233: public QueryDefinition setOrderBy(String[] orderBy) {
0234: ensureImmutable();
0235: this .orderBy = ArrayUtil.asList(orderBy);
0236: return this ;
0237: }
0238:
0239: public QueryDefinition setOrderBy(List orderBy) {
0240: ensureImmutable();
0241: this .orderBy = orderBy;
0242: return this ;
0243: }
0244:
0245: public QueryDefinition addToWhere(String sql) {
0246: ensureImmutable();
0247: if (sql == null || sql.trim().length() == 0) {
0248: return this ;
0249: }
0250: if (where == null) {
0251: where = new StringBuffer();
0252: }
0253: where.append(sql);
0254: return this ;
0255: }
0256:
0257: public QueryDefinition andToWhere(String sql) {
0258: if (sql != null && sql.length() > 0) {
0259: if (where == null) {
0260: return addToWhere(sql);
0261: } else {
0262: return addToWhere(Query.AND).addToWhere(sql);
0263: }
0264: }
0265: return this ;
0266: }
0267:
0268: public QueryDefinition orToWhere(String sql) {
0269: if (sql != null && sql.length() > 0) {
0270: if (where == null) {
0271: return addToWhere(sql);
0272: } else {
0273: return addToWhere(Query.OR).addToWhere(sql);
0274: }
0275: }
0276: return this ;
0277: }
0278:
0279: public QueryDefinition addToWhere(PersistentObject persistentObject) {
0280: if (persistentObject != null) {
0281: addToWhere(SelectQueryBuilderImpl
0282: .whereByPersistentObject(persistentObject));
0283: }
0284: return this ;
0285: }
0286:
0287: public QueryDefinition andToWhere(PersistentObject persistentObject) {
0288: if (persistentObject != null) {
0289: andToWhere(SelectQueryBuilderImpl
0290: .whereByPersistentObject(persistentObject));
0291: }
0292: return this ;
0293: }
0294:
0295: public QueryDefinition orToWhere(PersistentObject persistentObject) {
0296: if (persistentObject != null) {
0297: andToWhere(SelectQueryBuilderImpl
0298: .whereByPersistentObject(persistentObject));
0299: }
0300: return this ;
0301: }
0302:
0303: public QueryDefinition setWhere(String sql) {
0304: ensureImmutable();
0305: if (sql == null || sql.trim().length() == 0) {
0306: return this ;
0307: }
0308: if (where == null) {
0309: where = new StringBuffer();
0310: }
0311: where.append(sql);
0312: return this ;
0313: }
0314:
0315: public String getWhere() {
0316: return ParentBase.buffer2string(where);
0317: }
0318:
0319: public String[] getSelect() {
0320: ensureImmutable();
0321: return (String[]) (select == null ? null : select
0322: .toArray(new String[select.size()]));
0323: }
0324:
0325: public QueryDefinition setSelect(String[] select) {
0326: ensureImmutable();
0327: this .select = ArrayUtil.asList(select);
0328: return this ;
0329: }
0330:
0331: public QueryDefinition setSelect(List select) {
0332: ensureImmutable();
0333: this .select = select;
0334: return this ;
0335: }
0336:
0337: public QueryDefinition addToSelect(String columnExpression) {
0338: ensureImmutable();
0339: if (columnExpression == null || columnExpression.length() == 0) {
0340: return this ;
0341: }
0342: lazySelect();
0343: select.add(columnExpression);
0344: return this ;
0345: }
0346:
0347: public QueryDefinition addToSelect(
0348: PersistentObjectFactory persistent) {
0349: ensureImmutable();
0350: String sqlPersistent = queryBuilder
0351: .getSelectSqlFragment(persistent);
0352: lazySelect().add(sqlPersistent);
0353: return this ;
0354: }
0355:
0356: private List lazySelect() {
0357: if (select == null) {
0358: select = new ArrayList();
0359: }
0360: return select;
0361: }
0362:
0363: public void addToChainedColumns(int columnIndex, String tableName,
0364: String columnName) {
0365: lazyChainedColumns().add(
0366: new ChainedColumn(columnIndex, tableName, columnName));
0367: }
0368:
0369: public boolean hasChainedColumns() {
0370: return chainedColumns != null && !chainedColumns.isEmpty();
0371: }
0372:
0373: public ChainedColumn[] getChainedColumns() {
0374: if (chainedColumns == null) {
0375: return EMPTY_CHAINED_COLUMN_ARRAY;
0376: } else {
0377: return (ChainedColumn[]) chainedColumns
0378: .toArray(new ChainedColumn[chainedColumns.size()]);
0379: }
0380: }
0381:
0382: public void clearChainedColumns() {
0383: if (chainedColumns != null) {
0384: chainedColumns.clear();
0385: chainedColumns = null;
0386: }
0387: }
0388:
0389: private List lazyChainedColumns() {
0390: if (chainedColumns == null) {
0391: chainedColumns = new ArrayList();
0392: }
0393: return chainedColumns;
0394: }
0395:
0396: public QueryDefinition addToFrom(String columnExpression) {
0397: ensureImmutable();
0398: if (columnExpression == null || columnExpression.length() == 0) {
0399: return this ;
0400: }
0401: lazyFrom().add(columnExpression);
0402: return this ;
0403: }
0404:
0405: private List lazyFrom() {
0406: if (from == null) {
0407: from = new ArrayList();
0408: }
0409: return from;
0410: }
0411:
0412: public List getFromAsList() {
0413: return from;
0414: }
0415:
0416: public String[] getFrom() {
0417: return (String[]) (from == null ? null : from
0418: .toArray(new String[from.size()]));
0419: }
0420:
0421: public QueryDefinition setFrom(String[] from) {
0422: ensureImmutable();
0423: if (join != null) {
0424: throw new RuntimeException(
0425: "Cannot set 'from' since 'join' is already set");
0426: }
0427: this .from = ArrayUtil.asList(from);
0428: return this ;
0429: }
0430:
0431: public Join newJoin(String firstTableName) {
0432: return new JoinImpl(firstTableName);
0433: }
0434:
0435: public Join addJoin(String firstTableName) {
0436: ensureImmutable();
0437: if (join != null) {
0438: throw new OdalRuntimePersistencyException(
0439: "There is alredy not null join in this query object");
0440: }
0441: join = new JoinImpl(firstTableName);
0442: return join;
0443: }
0444:
0445: public Join getJoin() {
0446: return join;
0447: }
0448:
0449: public QueryDefinition setJoin(Join join) {
0450: ensureImmutable();
0451: if (from != null && join != null) {
0452: throw new RuntimeException(
0453: "Cannot set 'join' since 'from' is already set");
0454: }
0455: this .join = ((JoinImpl) join);
0456: return this ;
0457: }
0458:
0459: public QueryDefinition addToGroupBy(String columnExpression) {
0460: ensureImmutable();
0461: if (columnExpression == null || columnExpression.length() == 0) {
0462: return this ;
0463: }
0464: if (groupBy == null) {
0465: groupBy = new ArrayList();
0466: }
0467: groupBy.add(columnExpression);
0468: return this ;
0469: }
0470:
0471: public String[] getGroupBy() {
0472: return (String[]) (groupBy == null ? null : groupBy
0473: .toArray(new String[groupBy.size()]));
0474: }
0475:
0476: public QueryDefinition setGroupBy(String[] groupBy) {
0477: ensureImmutable();
0478: this .groupBy = ArrayUtil.asList(groupBy);
0479: return this ;
0480: }
0481:
0482: public QueryDefinition setHaving(String sql) {
0483: ensureImmutable();
0484: if (sql == null || sql.trim().length() == 0) {
0485: return this ;
0486: }
0487: if (having == null) {
0488: having = new StringBuffer();
0489: }
0490: having.append(Query.HAVING).append(sql);
0491: return this ;
0492: }
0493:
0494: public String getHaving() {
0495: return ParentBase.buffer2string(having);
0496: }
0497:
0498: public QueryDefinition addToHaving(String sql) {
0499: ensureImmutable();
0500: if (sql == null || sql.trim().length() == 0) {
0501: return this ;
0502: }
0503: if (having == null) {
0504: having = new StringBuffer(Query.HAVING);
0505: }
0506: having.append(sql);
0507: return this ;
0508: }
0509:
0510: public QueryDefinition andToHaving(String sql) {
0511: if (sql != null && sql.length() > 0) {
0512: return addToHaving(Query.AND).addToHaving(sql);
0513: }
0514: return this ;
0515: }
0516:
0517: public QueryDefinition orToHaving(String sql) {
0518: if (sql != null && sql.length() > 0) {
0519: return addToHaving(Query.OR).addToHaving(sql);
0520: }
0521: return this ;
0522: }
0523:
0524: public boolean isDistinct() {
0525: return distinct;
0526: }
0527:
0528: public QueryDefinition setDistinct(boolean distinct) {
0529: ensureImmutable();
0530: this .distinct = distinct;
0531: return this ;
0532: }
0533:
0534: public int getLimitMin() {
0535: return limitMin;
0536: }
0537:
0538: public QueryDefinition setLimit(int max) {
0539: ensureImmutable();
0540: this .limitMax = max;
0541: return this ;
0542: }
0543:
0544: public int getLimitMax() {
0545: return limitMax;
0546: }
0547:
0548: public QueryDefinition setLimit(int min, int max) {
0549: ensureImmutable();
0550: if (min > max) {
0551: throw new OdalRuntimePersistencyException("min " + min
0552: + " > max " + max);
0553: }
0554: limitMin = min;
0555: limitMax = max;
0556: return this ;
0557: }
0558:
0559: public boolean isLocked() {
0560: return locked != LockType.NONE;
0561: }
0562:
0563: public QueryDefinition setLocked(LockType locked) {
0564: ensureImmutable();
0565: if (locked != null) {
0566: this .locked = locked;
0567: }
0568: return this ;
0569: }
0570:
0571: public QueryDefinition setLocked(LockType locked,
0572: String[] forUpdateOf) {
0573: ensureImmutable();
0574: if (locked != null) {
0575: this .locked = locked;
0576: this .forUpdateOf = forUpdateOf;
0577: }
0578: return this ;
0579: }
0580:
0581: public String[] getForUpdateOf() {
0582: return forUpdateOf;
0583: }
0584:
0585: public boolean isAdHoc() {
0586: return sql != null && join == null && from == null
0587: && singularResultFactory == null;
0588: }
0589:
0590: public DatabasePolicy getDatabasePolicy() {
0591: return databasePolicy;
0592: }
0593:
0594: public void setDatabasePolicy(DatabasePolicy databasePolicy) {
0595: setDatabasePolicy(databasePolicy, true);
0596: }
0597:
0598: protected void setDatabasePolicy(DatabasePolicy databasePolicy,
0599: boolean validate) {
0600: if (validate) {
0601: ensureImmutable();
0602: }
0603: if (this .databasePolicy == null
0604: || this .databasePolicy == DatabasePolicy.NULL_DATABASE_POLICY) {
0605: this .databasePolicy = databasePolicy;
0606: } else {
0607: if (validate
0608: && this .databasePolicy.getClass() != databasePolicy
0609: .getClass()) {
0610: throw new OdalRuntimePersistencyException(
0611: "Attempt to re-assign different database policy: "
0612: + "old : "
0613: + this .databasePolicy.getClass()
0614: + "; new : "
0615: + databasePolicy.getClass());
0616: }
0617: }
0618: }
0619:
0620: public boolean isWait() {
0621: return LockType.isWait(this .locked);
0622: }
0623:
0624: protected String getKey() {
0625: return key;
0626: }
0627:
0628: protected void setKey(String key) {
0629: this .key = key;
0630: }
0631:
0632: public SelectQueryBuilder getQueryBuilder() {
0633: return queryBuilder;
0634: }
0635:
0636: // public void setQueryBuilder(SelectQueryBuilder queryBuilder) {
0637: // ensureImmutable();
0638: // this.queryBuilder = queryBuilder;
0639: // }
0640:
0641: public void setExcludedFields(Set excludedFields) {
0642: ensureImmutable();
0643: if (excludedFields != null) {
0644: this .columnFilter = new CompoundColumnFilterImpl(
0645: excludedFields);
0646: }
0647: }
0648:
0649: public CompoundColumnFilter getCompoundColumnFilter() {
0650: return columnFilter;
0651: }
0652:
0653: public CompoundColumnFilter columnFilters() {
0654: if (columnFilter == null
0655: || columnFilter == CompoundColumnFilter.NULL_COLUMN_FILTER) {
0656: setCompoundColumnFilter(new CompoundColumnFilterImpl());
0657: }
0658: return getCompoundColumnFilter();
0659: }
0660:
0661: public void setCompoundColumnFilter(
0662: CompoundColumnFilter columnFilter) {
0663: if (columnFilter != null) {
0664: ensureImmutable();
0665: this .columnFilter = columnFilter;
0666: }
0667: }
0668:
0669: public boolean isColumnFiltersEmpty() {
0670: return columnFilter.isEmpty();
0671: }
0672:
0673: public boolean isUseColumnNames() {
0674: return useColumnNames;
0675: }
0676:
0677: public void setUseColumnNames(boolean useColumnNames) {
0678: ensureImmutable();
0679: this .useColumnNames = useColumnNames;
0680: }
0681:
0682: public boolean isUseSelectStar() {
0683: return useSelectStar;
0684: }
0685:
0686: public void setUseSelectStar(boolean useSelectStar) {
0687: ensureImmutable();
0688: this .useSelectStar = useSelectStar;
0689: }
0690:
0691: public long getTimeout() {
0692: return timeout;
0693: }
0694:
0695: public void setTimeout(long timeout) {
0696: ensureImmutable();
0697: this .timeout = timeout;
0698: }
0699:
0700: public void useStarAndColumnNames() {
0701: setUseSelectStar(true);
0702: setUseColumnNames(true);
0703: }
0704:
0705: public void unuseStarAndColumnNames() {
0706: setUseSelectStar(false);
0707: setUseColumnNames(false);
0708: }
0709:
0710: public String getCallBody() {
0711: return callBody;
0712: }
0713:
0714: public void setCallBody(String callBody) {
0715: ensureImmutable();
0716: this .callBody = callBody;
0717: }
0718:
0719: public boolean isFunction() {
0720: return function;
0721: }
0722:
0723: public void setFunction(boolean function) {
0724: ensureImmutable();
0725: this .function = function;
0726: }
0727:
0728: public synchronized QueryDefinition compile() {
0729: return compile(getDatabasePolicy());
0730: }
0731:
0732: public synchronized QueryDefinition compile(
0733: DatabasePolicy databasePolicy) {
0734: return compile(databasePolicy, null);
0735: }
0736:
0737: public synchronized QueryDefinition compile(
0738: DatabasePolicy databasePolicy, Set usedTableAliases) {
0739: if (!compiled) {
0740: if (databasePolicy == null) {
0741: throw new OdalRuntimePersistencyException(
0742: "databasePolicy == null");
0743: }
0744: setUsedTableAliases(usedTableAliases);
0745: sql = this .queryBuilder.getSqlSelect(this , databasePolicy);
0746: compiled = true;
0747: }
0748: return this ;
0749: }
0750:
0751: public synchronized QueryDefinition compileCall() {
0752: return compileCall(getDatabasePolicy());
0753: }
0754:
0755: public synchronized QueryDefinition compileCall(
0756: DatabasePolicy databasePolicy) {
0757: if (!compiled) {
0758: if (databasePolicy == null) {
0759: throw new OdalRuntimePersistencyException(
0760: "databasePolicy == null");
0761: }
0762: sql = queryBuilder.getSqlCall(this , databasePolicy);
0763: compiled = true;
0764: }
0765: return this ;
0766: }
0767:
0768: public boolean isCompiled() {
0769: return compiled;
0770: }
0771:
0772: private void ensureImmutable() {
0773: if (compiled) {
0774: throw new OdalRuntimePersistencyException(
0775: "Cannot modify compiled query");
0776: }
0777: }
0778:
0779: public synchronized void decompile() {
0780: sql = null;
0781: compiled = false;
0782: externalSetSql = false;
0783: if (join != null) {
0784: join.decompile();
0785: }
0786: if (union != null) {
0787: union.decompile();
0788: }
0789: }
0790:
0791: public Object clone() {
0792: QueryDefinitionImpl queryDefinition;
0793: try {
0794: queryDefinition = (QueryDefinitionImpl) super .clone();
0795: } catch (CloneNotSupportedException e) {
0796: throw new OdalRuntimePersistencyException(
0797: "cannot clone query def ", e);
0798: }
0799: if (join != null) {
0800: queryDefinition.join = (JoinImpl) join.clone();
0801: }
0802: if (union != null) {
0803: queryDefinition.union = (UnionImpl) union.clone();
0804: }
0805: if (chainedColumns != null) {
0806: queryDefinition.chainedColumns = (ArrayList) chainedColumns
0807: .clone();
0808: }
0809: return queryDefinition;
0810: }
0811:
0812: public String getName() {
0813: throw new UnsupportedOperationException();
0814: }
0815:
0816: public void setName(String name) {
0817: throw new UnsupportedOperationException(
0818: "QueryDefinitionImpl::setName");
0819: }
0820:
0821: public BasicQuery setParameters(Parameter[] parameters) {
0822: throw new UnsupportedOperationException(
0823: "QueryDefinitionImpl::setParameters");
0824: }
0825:
0826: public Union union(QueryDefinition queryDefinition) {
0827: ensureImmutable();
0828: return lazyUnion().union(queryDefinition);
0829: }
0830:
0831: public Union unionAll(QueryDefinition queryDefinition) {
0832: ensureImmutable();
0833: return lazyUnion().unionAll(queryDefinition);
0834: }
0835:
0836: public Union union(QueryDefinition queryDefinition, UnionMode mode) {
0837: ensureImmutable();
0838: return lazyUnion().union(queryDefinition, mode);
0839: }
0840:
0841: public boolean isUnion() {
0842: return unionSize() > 0;
0843: }
0844:
0845: public int unionSize() {
0846: return union == null ? 0 : union.unionSize();
0847: }
0848:
0849: protected Union lazyUnion() {
0850: if (union == null) {
0851: union = new UnionImpl();
0852: }
0853: return union;
0854: }
0855:
0856: public Union getUnion() {
0857: return union;
0858: }
0859:
0860: public AbstractParameters getBaseParameters() {
0861: throw new UnsupportedOperationException();
0862: }
0863:
0864: public Set getUsedTableAliases() {
0865: return usedTableAliases;
0866: }
0867:
0868: public void setUsedTableAliases(Set usedTableAliases) {
0869: if (usedTableAliases != null) {
0870: this .usedTableAliases = usedTableAliases;
0871: }
0872: }
0873:
0874: public boolean isCombinedInline() {
0875: return combinedInline;
0876: }
0877:
0878: public void setCombinedInline() {
0879: this .combinedInline = true;
0880: }
0881:
0882: public String[] extractNonUsedTableAliases() {
0883: if (combinedInline && join != null) {
0884: ArrayList aliases = new ArrayList(join.size());
0885: for (Join.TableIterator it = join.iterator(); it.hasNext();) {
0886: Join.Table table = it.next();
0887: String tableAlias = table.getJoinedTableAlias();
0888: if (table.getJoinedTableAlias() != null
0889: && !usedTableAliases.contains(tableAlias)) {
0890: aliases.add(table.getJoinedTableAlias());
0891: }
0892: }
0893: return (String[]) aliases
0894: .toArray(new String[aliases.size()]);
0895: } else {
0896: return null;
0897: }
0898: }
0899:
0900: public Map toMap() {
0901: LinkedHashMap map = new LinkedHashMap();
0902: map.put(TAG_SELECT, select);
0903: map.put(TAG_FROM, from);
0904: if (where != null) {
0905: putIfNotNull(map, TAG_WHERE, String.valueOf(where));
0906: }
0907: putIfNotNull(map, TAG_ORDER_BY, orderBy);
0908: putIfNotNull(map, TAG_GROUP_BY, groupBy);
0909: if (having != null) {
0910: putIfNotNull(map, TAG_HAVING, String.valueOf(having));
0911: }
0912: putIfTrue(map, TAG_DISTINCT, distinct);
0913: putIfGtZero(map, TAG_LIMIT_MIN, limitMin);
0914: putIfGtZero(map, TAG_LIMIT_MAX, limitMax);
0915: map.put(TAG_LOCKED, locked.getName());
0916: if (forUpdateOf != null) {
0917: map.put(TAG_FOR_UPDATE_OF, Arrays.asList(forUpdateOf));
0918: }
0919: putIfNotNull(map, TAG_SQL, sql);
0920: putIfNotNull(map, TAG_KEY, key);
0921: if (columnFilter != CompoundColumnFilter.NULL_COLUMN_FILTER
0922: && columnFilter != null) {
0923: map.put(TAG_COLUMN_FILTER,
0924: ((CompoundColumnFilterImpl) columnFilter).toMap());
0925: }
0926: putIfTrue(map, TAG_USE_COLUMN_NAMES, useColumnNames);
0927: putIfTrue(map, TAG_USE_SELECT_STAR, useSelectStar);
0928: putIfGtZero(map, TAG_TIMEOUT, timeout);
0929: putIfTrue(map, TAG_DISCONNECTED_PAGE_QUERY,
0930: disconnectedPageQuery);
0931: if (join != null) {
0932: map.put(TAG_JOIN, join.toMap());
0933: }
0934: if (union != null) {
0935: map.put(TAG_UNION, union.toMap());
0936: }
0937: putIfTrue(map, TAG_COMPILED, compiled);
0938: if (chainedColumns != null) {
0939: ArrayList list = new ArrayList(chainedColumns.size());
0940: for (int i = 0; i < chainedColumns.size(); i++) {
0941: ChainedColumn value = (ChainedColumn) chainedColumns
0942: .get(i);
0943: list.add(value.toMap());
0944: }
0945: map.put(TAG_CHAINED_COLUMNS, list);
0946: }
0947:
0948: if (singularResultFactory != null) {
0949: map.put(TAG_SINGULAR_RESULT_FACTORY, singularResultFactory
0950: .getClass().getName());
0951: }
0952:
0953: if (multipleResultFactory != null) {
0954: map.put(TAG_MULTIPLE_RESULT_FACTORY, multipleResultFactory
0955: .getClass().getName());
0956: }
0957:
0958: putIfTrue(map, TAG_CALL, call);
0959:
0960: return map;
0961: }
0962:
0963: public void fromMap(Map map) {
0964: PropertyMap propertyMap = PropertyMap.toPropertyMap(map, true);
0965: select = propertyMap.getList(TAG_SELECT);
0966: from = propertyMap.getList(TAG_FROM);
0967: where = propertyMap.getPropertyStringBuffer(TAG_WHERE);
0968: orderBy = propertyMap.getList(TAG_ORDER_BY);
0969: groupBy = propertyMap.getList(TAG_GROUP_BY);
0970: having = propertyMap.getPropertyStringBuffer(TAG_HAVING);
0971: distinct = propertyMap.getBoolean(TAG_DISTINCT);
0972: limitMin = propertyMap.getInt(TAG_LIMIT_MIN);
0973: limitMax = propertyMap.getInt(TAG_LIMIT_MAX);
0974: String lockedName = propertyMap.getProperty(TAG_LOCKED);
0975: locked = LockType.name2type(lockedName);
0976: List forUpdateOfList = propertyMap.getList(TAG_FOR_UPDATE_OF);
0977: if (forUpdateOfList != null) {
0978: forUpdateOf = (String[]) forUpdateOfList
0979: .toArray(new String[forUpdateOfList.size()]);
0980: }
0981: sql = propertyMap.getProperty(TAG_SQL);
0982: key = propertyMap.getProperty(TAG_KEY);
0983: Map columnFilterMap = propertyMap.getMap(TAG_COLUMN_FILTER);
0984: if (columnFilterMap != null) {
0985: columnFilter = new CompoundColumnFilterImpl(map);
0986: }
0987: useColumnNames = propertyMap.getBoolean(TAG_USE_COLUMN_NAMES);
0988: useSelectStar = propertyMap.getBoolean(TAG_USE_SELECT_STAR);
0989: timeout = propertyMap.getInt(TAG_TIMEOUT);
0990: disconnectedPageQuery = propertyMap
0991: .getBoolean(TAG_DISCONNECTED_PAGE_QUERY);
0992: Map joinMap = propertyMap.getMap(TAG_JOIN);
0993: if (joinMap != null) {
0994: join = new JoinImpl(joinMap);
0995: }
0996: Map unionMap = propertyMap.getMap(TAG_UNION);
0997: if (unionMap != null) {
0998: union = new UnionImpl(unionMap);
0999: }
1000: compiled = propertyMap.getBoolean(TAG_COMPILED);
1001: List chainedColumnsList = propertyMap
1002: .getList(TAG_CHAINED_COLUMNS);
1003: if (chainedColumnsList != null && !chainedColumnsList.isEmpty()) {
1004: chainedColumns = new ArrayList(chainedColumnsList.size());
1005: for (int i = 0; i < chainedColumnsList.size(); i++) {
1006: Map value = (Map) chainedColumnsList.get(i);
1007: chainedColumns.add(new ChainedColumn(value));
1008: }
1009: }
1010:
1011: String singularResultFactoryClassName = propertyMap
1012: .getProperty(TAG_SINGULAR_RESULT_FACTORY);
1013: if (singularResultFactoryClassName != null) {
1014: singularResultFactory = (PersistentObjectFactory) instanceForName(singularResultFactoryClassName);
1015: }
1016:
1017: String multipleResultFactoryClassName = propertyMap
1018: .getProperty(TAG_MULTIPLE_RESULT_FACTORY);
1019: if (multipleResultFactoryClassName != null) {
1020: multipleResultFactory = (CollectionFactory) instanceForName(multipleResultFactoryClassName);
1021: }
1022:
1023: call = propertyMap.getBoolean(TAG_CALL);
1024:
1025: }
1026:
1027: private Object instanceForName(String className) {
1028: try {
1029: return Class.forName(className).newInstance();
1030: } catch (Exception e) {
1031: throw new OdalRuntimePersistencyException(
1032: "Cannot instantiate class " + className, e);
1033: }
1034: }
1035:
1036: protected void putIfNotNull(Map map, Object key, Object value) {
1037: if (value != null) {
1038: map.put(key, value);
1039: }
1040: }
1041:
1042: protected void putIfGtZero(Map map, Object key, long value) {
1043: if (value > 0) {
1044: map.put(key, String.valueOf(value));
1045: }
1046: }
1047:
1048: protected void putIfTrue(Map map, Object key, boolean value) {
1049: if (value) {
1050: map.put(key, Boolean.valueOf(value));
1051: }
1052: }
1053:
1054: public boolean isCall() {
1055: return call;
1056: }
1057:
1058: public void setCall(boolean call) {
1059: this.call = call;
1060: }
1061:
1062: }
|