/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.mappingsmodel.query.relational;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Vector;
import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel;
import org.eclipse.persistence.tools.workbench.mappingsmodel.TopLinkOption;
import org.eclipse.persistence.tools.workbench.mappingsmodel.TopLinkOptionSet;
import org.eclipse.persistence.tools.workbench.mappingsmodel.query.MWAbstractReadQuery;
import org.eclipse.persistence.tools.workbench.mappingsmodel.query.MWQueryParameter;
import org.eclipse.persistence.tools.workbench.mappingsmodel.query.MWQueryable;
import org.eclipse.persistence.tools.workbench.mappingsmodel.query.MWReadQuery;
import org.eclipse.persistence.tools.workbench.utility.TriStateBoolean;
import org.eclipse.persistence.tools.workbench.utility.iterators.CloneListIterator;
import org.eclipse.persistence.tools.workbench.utility.node.Node;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.mappings.DirectToFieldMapping;
import org.eclipse.persistence.mappings.TransformationMapping;
import org.eclipse.persistence.mappings.converters.ObjectTypeConverter;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLCompositeObjectMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.sessions.Record;
public abstract class MWAbstractRelationalReadQuery
extends MWAbstractReadQuery
implements MWRelationalReadQuery {
/**
* Allow for the cache usage to be specified to enable in-memory querying.
*/
private volatile CacheUsageModel cacheUsage;
private static TopLinkOptionSet cacheUsageOptions;
/** Used to determine behavior of indirection in InMemoryQuerying */
private volatile InMemoryQueryIndirectionPolicyModel inMemoryQueryIndirectionPolicy;
private static TopLinkOptionSet inMemoryQueryIndirectionPolicyOptions;
private volatile MWRelationalSpecificQueryOptions relationalOptions;
private List joinedItems;
public static final String JOINED_ITEMS_LIST = "joinedItems";
//joining
public static class CacheUsageModel extends TopLinkOption {
public CacheUsageModel(String mwModelString, String externalString, int topLinkModelOption) {
super(mwModelString, externalString, new Integer(topLinkModelOption));
}
public void setMWOptionOnTopLinkObject(Object query) {
((ObjectLevelReadQuery) query).setCacheUsage(((Integer) getTopLinkModelOption()).intValue());
}
}
public static class InMemoryQueryIndirectionPolicyModel extends TopLinkOption {
public InMemoryQueryIndirectionPolicyModel(String mwModelString, String externalString, int topLinkModelOption) {
super(mwModelString, externalString, new Integer(topLinkModelOption));
}
public void setMWOptionOnTopLinkObject(Object query) {
((ObjectLevelReadQuery) query).getInMemoryQueryIndirectionPolicy().setPolicy(((Integer) getTopLinkModelOption()).intValue());
}
}
public synchronized static TopLinkOptionSet cacheUsageOptions() {
if (cacheUsageOptions == null) {
List list = new ArrayList();
list.add(new CacheUsageModel(UNDEFINED_CACHE_USAGE, "UNDEFINED_CACHE_USAGE_OPTION", ObjectLevelReadQuery.UseDescriptorSetting));
list.add(new CacheUsageModel(DO_NOT_CHECK_CACHE, "DO_NOT_CHECK_CACHE_OPTION", ObjectLevelReadQuery.DoNotCheckCache));
list.add(new CacheUsageModel(CHECK_CACHE_BY_EXACT_PRIMARY_KEY, "CHECK_CACHE_BY_EXACT_PRIMARY_KEY_OPTION", ObjectLevelReadQuery.CheckCacheByExactPrimaryKey));
list.add(new CacheUsageModel(CHECK_CACHE_BY_PRIMARY_KEY, "CHECK_CACHE_BY_PRIMARY_KEY_OPTION", ObjectLevelReadQuery.CheckCacheByPrimaryKey));
list.add(new CacheUsageModel(CHECK_CACHE_THEN_DATABASE, "CHECK_CACHE_THEN_DATABASE_OPTION",ObjectLevelReadQuery.CheckCacheThenDatabase));
list.add(new CacheUsageModel(CHECK_CACHE_ONLY, "CHECK_CACHE_ONLY_OPTION", ObjectLevelReadQuery.CheckCacheOnly));
list.add(new CacheUsageModel(CONFORM_RESULTS_IN_UNIT_OF_WORK, "CONFORM_RESULTS_IN_UNIT_OF_WORK_OPTION", ObjectLevelReadQuery.ConformResultsInUnitOfWork));
cacheUsageOptions = new TopLinkOptionSet(list);
}
return cacheUsageOptions;
}
public synchronized static TopLinkOptionSet inMemoryQueryIndirectionPolicyOptions() {
if (inMemoryQueryIndirectionPolicyOptions == null) {
List list = new ArrayList();
list.add(new InMemoryQueryIndirectionPolicyModel(THROW_INDIRECTION_EXCEPTION, "THROW_INDIRECTION_EXCEPTION_OPTION", ObjectLevelReadQuery.DoNotCheckCache));
list.add(new InMemoryQueryIndirectionPolicyModel(TRIGGER_INDIRECTION, "TRIGGER_INDIRECTION_OPTION", ObjectLevelReadQuery.CheckCacheByExactPrimaryKey));
list.add(new InMemoryQueryIndirectionPolicyModel(IGNORE_EXCEPTION_RETURN_CONFORMED, "IGNORE_EXCEPTION_RETURN_CONFORMED_OPTION", ObjectLevelReadQuery.CheckCacheByPrimaryKey));
list.add(new InMemoryQueryIndirectionPolicyModel(IGNORE_EXCEPTION_RETURN_NOT_CONFORMED, "IGNORE_EXCEPTION_RETURN_NOT_CONFORMED_OPTION", ObjectLevelReadQuery.CheckCacheThenDatabase));
inMemoryQueryIndirectionPolicyOptions = new TopLinkOptionSet(list);
}
return inMemoryQueryIndirectionPolicyOptions;
}
public static XMLDescriptor buildDescriptor() {
XMLDescriptor descriptor = new XMLDescriptor();
descriptor.setJavaClass(MWAbstractRelationalReadQuery.class);
descriptor.getInheritancePolicy().setParentClass(MWAbstractReadQuery.class);
//object type mapping - cacheUsage
XMLDirectMapping cacheUsage = new XMLDirectMapping();
cacheUsage.setAttributeName("cacheUsage");
cacheUsage.setXPath("cache-usage/text()");
ObjectTypeConverter cacheUsageConverter = new ObjectTypeConverter();
cacheUsageOptions().addConversionValuesForTopLinkTo(cacheUsageConverter);
cacheUsage.setConverter(cacheUsageConverter);
cacheUsage.setNullValue(cacheUsageOptions().topLinkOptionForMWModelOption(UNDEFINED_CACHE_USAGE));
descriptor.addMapping(cacheUsage);
//object type mapping - inMemoryQueryIndirectionPolicy
XMLDirectMapping inMemoryQueryIndirectionPolicyMapping = new XMLDirectMapping();
inMemoryQueryIndirectionPolicyMapping.setAttributeName("inMemoryQueryIndirectionPolicy");
inMemoryQueryIndirectionPolicyMapping.setXPath("in-memory-query-indirection-policy/text()");
ObjectTypeConverter inMemoryQueryIndirectionPolicyConverter = new ObjectTypeConverter();
inMemoryQueryIndirectionPolicyOptions().addConversionValuesForTopLinkTo(inMemoryQueryIndirectionPolicyConverter);
inMemoryQueryIndirectionPolicyMapping.setConverter(inMemoryQueryIndirectionPolicyConverter);
inMemoryQueryIndirectionPolicyMapping.setNullValue(inMemoryQueryIndirectionPolicyOptions().topLinkOptionForMWModelOption(THROW_INDIRECTION_EXCEPTION));
descriptor.addMapping(inMemoryQueryIndirectionPolicyMapping);
XMLCompositeObjectMapping relationalOptionsMaping = new XMLCompositeObjectMapping();
relationalOptionsMaping.setAttributeName("relationalOptions");
relationalOptionsMaping.setReferenceClass(MWRelationalSpecificQueryOptions.class);
relationalOptionsMaping.setXPath("relational-options");
descriptor.addMapping(relationalOptionsMaping);
XMLCompositeCollectionMapping joinedItemsMapping = new XMLCompositeCollectionMapping();
joinedItemsMapping.setAttributeName("joinedItems");
joinedItemsMapping.setReferenceClass(MWOrderingItem.class);
joinedItemsMapping.setXPath("joins/joined-item");
descriptor.addMapping(joinedItemsMapping);
return descriptor;
}
/** Default constructor - for TopLink use only. */
MWAbstractRelationalReadQuery() {
super();
}
MWAbstractRelationalReadQuery(MWRelationalQueryManager queryManager, String name) {
super(queryManager, name);
}
protected void initialize(Node parent) {
super.initialize(parent);
inMemoryQueryIndirectionPolicy = (InMemoryQueryIndirectionPolicyModel) inMemoryQueryIndirectionPolicyOptions().topLinkOptionForMWModelOption(THROW_INDIRECTION_EXCEPTION);
this.joinedItems = new Vector();
cacheUsage = (CacheUsageModel) cacheUsageOptions().topLinkOptionForMWModelOption(UNDEFINED_CACHE_USAGE);
}
protected void initialize(String name) {
super.initialize(name);
this.relationalOptions = new MWRelationalSpecificQueryOptions(this);
setDefaultQueryFormat();
}
private void setDefaultQueryFormat() {
if (isTopLinkReservedFinder()) {
this.relationalOptions.setQueryFormatToAutoGenerated();
}
}
protected void addChildrenTo(List children) {
super.addChildrenTo(children);
children.add(this.relationalOptions);
synchronized (this.joinedItems) { children.addAll(this.joinedItems); }
}
// ************ Morphing ************
public void initializeFrom(MWRelationalQuery query) {
super.initializeFrom(query);
getRelationalOptions().initializeFrom(query.getRelationalOptions());
}
public void initializeFrom(MWReadQuery query) {
super.initializeFrom(query);
initializeFrom((MWRelationalQuery) query);
}
// ************ accessors ************
public MWRelationalSpecificQueryOptions getRelationalOptions() {
return this.relationalOptions;
}
// ************ Cache Usage ************
public CacheUsageModel getCacheUsage() {
return this.cacheUsage;
}
private CacheUsageModel getCacheUsageFromTopLinkModelOption(int topLinkCacheUsage) {
Iterator cacheUsageModels = cacheUsageOptions().toplinkOptions();
while (cacheUsageModels.hasNext()) {
CacheUsageModel model = (CacheUsageModel) cacheUsageModels.next();
if (((Integer) model.getTopLinkModelOption()).intValue() == topLinkCacheUsage) {
return model;
}
}
return null;
}
public void setCacheUsage(CacheUsageModel model) {
CacheUsageModel oldCacheUsage = this.cacheUsage;
this.cacheUsage = model;
firePropertyChanged(CACHE_USAGE_PROPERTY, oldCacheUsage, this.cacheUsage);
}
public void setCacheUsage(String cacheUsage) {
setCacheUsage((CacheUsageModel) cacheUsageOptions().topLinkOptionForMWModelOption(cacheUsage));
}
private void setCacheUsage(ObjectLevelReadQuery runtimeQuery) {
setCacheUsage(getCacheUsageFromTopLinkModelOption(runtimeQuery.getCacheUsage()));
}
// ************ In memory query indirection ************
public InMemoryQueryIndirectionPolicyModel getInMemoryQueryIndirectionPolicy() {
return this.inMemoryQueryIndirectionPolicy;
}
public void setInMemoryQueryIndirectionPolicy(InMemoryQueryIndirectionPolicyModel inMemoryQueryIndirectionPolicyModel) {
InMemoryQueryIndirectionPolicyModel oldQueryPolicy = this.inMemoryQueryIndirectionPolicy;
this.inMemoryQueryIndirectionPolicy = inMemoryQueryIndirectionPolicyModel;
firePropertyChanged(IN_MEMORY_QUERY_INDIRECTION_PROPERTY, oldQueryPolicy, this.inMemoryQueryIndirectionPolicy);
}
public void setInMemoryQueryIndirectionPolicy(String inMemoryQueryIndirectionPolicyModel) {
setInMemoryQueryIndirectionPolicy((InMemoryQueryIndirectionPolicyModel) inMemoryQueryIndirectionPolicyOptions().topLinkOptionForMWModelOption(inMemoryQueryIndirectionPolicyModel));
}
private void setInMemoryQueryIndirectionPolicy(ObjectLevelReadQuery runtimeQuery) {
int inMemoryQueryIndirectionPolicy = runtimeQuery.getInMemoryQueryIndirectionPolicy().getPolicy();
Iterator inMemoryQueryIndirectionPolicyOptions = inMemoryQueryIndirectionPolicyOptions().toplinkOptions();
while (inMemoryQueryIndirectionPolicyOptions.hasNext()) {
InMemoryQueryIndirectionPolicyModel model = (InMemoryQueryIndirectionPolicyModel) inMemoryQueryIndirectionPolicyOptions.next();
if (((Integer)model.getTopLinkModelOption()).intValue() == inMemoryQueryIndirectionPolicy) {
setInMemoryQueryIndirectionPolicy(model);
}
}
}
// ********** joinedItems **********
public MWJoinedItem addJoinedItem(MWQueryable queryable) {
if (queryable == null) {
throw new NullPointerException();
}
MWJoinedItem item = new MWJoinedItem(this, queryable);
addJoinedItem(item);
return item;
}
public MWJoinedItem addJoinedItem(Iterator queryables) {
MWJoinedItem item = new MWJoinedItem(this, queryables);
addJoinedItem(item);
return item;
}
public MWJoinedItem addJoinedItem(Iterator queryables, Iterator allowsNull) {
MWJoinedItem item = new MWJoinedItem(this, queryables, allowsNull);
addJoinedItem(item);
return item;
}
public MWJoinedItem addJoinedItem(int index, Iterator queryables, Iterator allowsNull) {
MWJoinedItem item = new MWJoinedItem(this, queryables, allowsNull);
addJoinedItem(index, item);
return item;
}
private void addJoinedItem(MWJoinedItem item) {
addJoinedItem(joinedItemsSize(), item);
}
private void addJoinedItem(int index, MWJoinedItem item) {
addItemToList(index, item, this.joinedItems, JOINED_ITEMS_LIST);
}
public void removeJoinedItem(MWJoinedItem joinedItem) {
removeJoinedItem(this.joinedItems.indexOf(joinedItem));
}
public void removeJoinedItem(int index) {
removeItemFromList(index, this.joinedItems, JOINED_ITEMS_LIST);
}
public ListIterator joinedItems() {
return new CloneListIterator(this.joinedItems);
}
public int joinedItemsSize() {
return this.joinedItems.size();
}
public int indexOfJoinedItem(MWJoinedItem item) {
return this.joinedItems.indexOf(item);
}
public void moveJoinedItemUp(MWJoinedItem item) {
int index = indexOfJoinedItem(item);
removeJoinedItem(index);
addJoinedItem(index - 1, item);
}
public void moveJoinedItemDown(MWJoinedItem item) {
int index = indexOfJoinedItem(item);
removeJoinedItem(index);
addJoinedItem(index + 1, item);
}
// ********** queryFormat **********
public String getQueryFormatType() {
return this.relationalOptions.getQueryFormatType();
}
public void setQueryFormatType(String type) {
this.relationalOptions.setQueryFormatType(type);
}
public MWQueryFormat getQueryFormat() {
return this.relationalOptions.getQueryFormat();
}
public TriStateBoolean isCacheStatement() {
return this.relationalOptions.isCacheStatement();
}
public void setCacheStatement(TriStateBoolean cacheStatement) {
this.relationalOptions.setCacheStatement(cacheStatement);
}
public TriStateBoolean isBindAllParameters() {
return this.relationalOptions.isBindAllParameters();
}
public void setBindAllParameters(TriStateBoolean bindAllParameters) {
this.relationalOptions.setBindAllParameters(bindAllParameters);
}
public boolean isPrepare() {
return this.relationalOptions.isPrepare();
}
public void setPrepare(boolean bindAllParameters) {
this.relationalOptions.setPrepare(bindAllParameters);
}
public void notifyExpressionsToRecalculateQueryables() {
this.relationalOptions.notifyExpressionsToRecalculateQueryables();
}
// ************ runtime conversion **************
public DatabaseQuery runtimeQuery() {
ObjectLevelReadQuery runtimeQuery = (ObjectLevelReadQuery) super.runtimeQuery();
getCacheUsage().setMWOptionOnTopLinkObject(runtimeQuery);
getInMemoryQueryIndirectionPolicy().setMWOptionOnTopLinkObject(runtimeQuery);
getRelationalOptions().adjustRuntimeQuery(runtimeQuery);
for (Iterator i = joinedItems(); i.hasNext(); ) {
((MWJoinedItem) i.next()).adjustRuntimeQuery(runtimeQuery);
}
return runtimeQuery;
}
public void adjustFromRuntime(ObjectLevelReadQuery runtimeQuery) {
super.adjustFromRuntime(runtimeQuery);
setCacheUsage(runtimeQuery);
setInMemoryQueryIndirectionPolicy(runtimeQuery);
getRelationalOptions().adjustFromRuntime(runtimeQuery);
}
}