/*******************************************************************************
* 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;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import org.eclipse.persistence.tools.workbench.mappingsmodel.MWModel;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWAbstractTransactionalPolicy;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWMappingDescriptor;
import org.eclipse.persistence.tools.workbench.mappingsmodel.descriptor.MWTransactionalPolicy;
import org.eclipse.persistence.tools.workbench.mappingsmodel.meta.MWClass;
import org.eclipse.persistence.tools.workbench.mappingsmodel.query.relational.MWRelationalQueryManager;
import org.eclipse.persistence.tools.workbench.mappingsmodel.query.xml.MWEisQueryManager;
import org.eclipse.persistence.tools.workbench.mappingsmodel.query.xml.MWOXQueryManager;
import org.eclipse.persistence.tools.workbench.utility.CollectionTools;
import org.eclipse.persistence.tools.workbench.utility.iterators.CloneIterator;
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.DescriptorQueryManager;
import org.eclipse.persistence.descriptors.InheritancePolicy;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.mappings.XMLCompositeCollectionMapping;
import org.eclipse.persistence.oxm.mappings.XMLDirectMapping;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ObjectLevelReadQuery;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadObjectQuery;
/**
* This class is used to maintain the collection of queries for a particular descriptor.
* It also holds the descriptor alias and any custom sql the user has created.
* Each descriptor has a query manager
*/
public abstract class MWQueryManager extends MWModel {
private Collection queries;
//property change
public static final String QUERY_COLLECTION = "queries";
/**
* 0 means no timeout
* -1 means default timeout. This will defer to the parent descriptor's setting. The runtime takes care of this situation
*/
//TODO This really should be 2 separate variables. One would be the queryTimeOutType, the
//other would be the queryTimeout if the queryTimeOutType is set to QUERY_TIMEOUT_TIMEOUT.
//The queryTimeout could be stored as an int and queryTimeOutType could be a useful String instead
//of an Integer. See MWQuery, it as the same problem
private volatile Integer queryTimeout;
public final static String QUERY_TIMEOUT_PROPERTY = "queryTimeout";
public final static Integer DEFAULT_QUERY_TIMEOUT = new Integer(-1);
public final static Integer QUERY_TIMEOUT_NO_TIMEOUT = new Integer(0);
public final static Integer QUERY_TIMEOUT_TIMEOUT = new Integer(1);
/**
* Default constructor - for TopLink use only.
*/
protected MWQueryManager() {
super();
}
protected MWQueryManager(MWAbstractTransactionalPolicy descriptor) {
super(descriptor);
}
protected void addChildrenTo(List children) {
super.addChildrenTo(children);
synchronized (this.queries) { children.addAll(this.queries); }
}
protected void initialize(Node parent) {
super.initialize(parent);
this.queries = new Vector();
this.queryTimeout = DEFAULT_QUERY_TIMEOUT; // default value
}
public MWMappingDescriptor getOwningDescriptor() {
return (MWMappingDescriptor) ((MWTransactionalPolicy)this.getParent()).getParent();
}
private void adjustParametersForToplinkReservedFinder(MWQuery query) {
MWClass objectClass = this.typeFor(Object.class);
MWClass stringClass = this.typeFor(String.class);
MWClass vectorClass = this.typeFor(Vector.class);
if (query.getName().equals("findByPrimaryKey" )) {
query.addParameter(objectClass).setName("primaryKey");
} else if (query.getName().equals("findAll" )) {
//no parameters
} else if (query.getName().equals("findOneBySql" )) {
query.addParameter(stringClass).setName("1");
query.addParameter(vectorClass).setName("2");
} else if (query.getName().equals("findManyBySql" )) {
query.addParameter(stringClass).setName("1");
query.addParameter(vectorClass).setName("2");
} else if (query.getName().equals("findOneByEjbql" )) {
query.addParameter(stringClass).setName("1");
query.addParameter(vectorClass).setName("2");
} else if (query.getName().equals("findManyByEjbql" )) {
query.addParameter(stringClass).setName("1");
query.addParameter(vectorClass).setName("2");
} else if (query.getName().equals("findOneByQuery" )) {
query.addParameter(this.typeFor(ReadObjectQuery.class)).setName("1");
query.addParameter(vectorClass).setName("2");
} else if (query.getName().equals("findManyByQuery" )) {
query.addParameter(this.typeFor(ReadAllQuery.class)).setName("1");
query.addParameter(vectorClass).setName("2");
}
else {
throw new IllegalArgumentException();
}
}
public MWReadObjectQuery addReadObjectQuery(String queryName) {
return (MWReadObjectQuery) this.addQuery(buildReadObjectQuery(queryName));
}
public MWReadAllQuery addReadAllQuery(String queryName) {
return (MWReadAllQuery) this.addQuery(buildReadAllQuery(queryName));
}
public abstract boolean supportsReportQueries();
public abstract MWReadObjectQuery buildReadObjectQuery(String queryName);
public abstract MWReadAllQuery buildReadAllQuery(String queryName);
protected MWQuery addQuery(MWQuery query) {
this.queries.add(query);
fireItemAdded(QUERY_COLLECTION, query);
return query;
}
public void removeQuery(MWQuery query) {
removeItemFromCollection(query,this.queries, QUERY_COLLECTION);
}
public Iterator queries()
{
return new CloneIterator(this.queries);
}
public int queriesSize()
{
return this.queries.size();
}
public MWQuery queryWithSignature(String querySignature) {
for (Iterator queries = queries(); queries.hasNext(); ) {
MWQuery query = (MWQuery) queries.next();
if (query.signature().equals(querySignature)) {
return query;
}
}
return null;
}
public Integer getQueryTimeout()
{
return this.queryTimeout;
}
/**
* sort the queries for TopLink
*/
private Collection getQueriesForTopLink() {
return CollectionTools.sort((List) this.queries);
}
private void setQueriesForTopLink(Collection queries) {
this.queries = queries;
}
public void setQueryTimeout(Integer queryTimeout)
{
Integer oldQueryTimeout = getQueryTimeout();
this.queryTimeout = queryTimeout;
firePropertyChanged(QUERY_TIMEOUT_PROPERTY, oldQueryTimeout, queryTimeout);
}
public static Vector topLinkReservedFinderNames()
{
Vector finderNames = new Vector();
finderNames.add("findByPrimaryKey");
finderNames.add("findAll");
finderNames.add("findOneBySql");
finderNames.add("findManyBySql");
finderNames.add("findOneByEjbql");
finderNames.add("findManyByEjbql");
finderNames.addAll(topLinkReservedFindByQueryFinderNames());
return finderNames;
}
public static Vector topLinkReservedFindByQueryFinderNames()
{
Vector finderNames = new Vector();
finderNames.add("findOneByQuery");
finderNames.add("findManyByQuery");
return finderNames;
}
//Problems methods
//Persistence
public static XMLDescriptor buildDescriptor()
{
XMLDescriptor descriptor = new XMLDescriptor();
descriptor.setJavaClass(MWQueryManager.class);
InheritancePolicy ip = (InheritancePolicy)descriptor.getInheritancePolicy();
ip.setClassIndicatorFieldName("@type");
ip.addClassIndicator(MWRelationalQueryManager.class, "relational");
ip.addClassIndicator(MWEisQueryManager.class, "eis");
ip.addClassIndicator(MWOXQueryManager.class, "ox");
// DTFs
XMLDirectMapping queryTimeoutMapping = new XMLDirectMapping();
queryTimeoutMapping.setAttributeName("queryTimeout");
queryTimeoutMapping.setXPath("query-timeout/text()");
queryTimeoutMapping.setGetMethodName("getQueryTimeoutForTopLink");
queryTimeoutMapping.setSetMethodName("setQueryTimeoutForTopLink");
queryTimeoutMapping.setNullValue(DEFAULT_QUERY_TIMEOUT);
descriptor.addMapping(queryTimeoutMapping);
// Aggregate collection - queries
XMLCompositeCollectionMapping queriesMapping = new XMLCompositeCollectionMapping();
queriesMapping.setAttributeName("queries");
queriesMapping.setGetMethodName("getQueriesForTopLink");
queriesMapping.setSetMethodName("setQueriesForTopLink");
queriesMapping.setReferenceClass(MWAbstractQuery.class);
queriesMapping.setXPath("query-list/query");
descriptor.addMapping(queriesMapping);
return descriptor;
}
private Integer getQueryTimeoutForTopLink() {
return this.queryTimeout;
}
private void setQueryTimeoutForTopLink(Integer queryTimeout) {
if (queryTimeout.equals(QUERY_TIMEOUT_NO_TIMEOUT)) {
this.queryTimeout = QUERY_TIMEOUT_NO_TIMEOUT;
}
else if (queryTimeout.equals(DEFAULT_QUERY_TIMEOUT)) {
this.queryTimeout = DEFAULT_QUERY_TIMEOUT;
}
else {
this.queryTimeout = queryTimeout;
}
}
// ************* runtime conversion ************
public void adjustRuntimeDescriptor(ClassDescriptor runtimeDescriptor) {
DescriptorQueryManager rtQueryManager = (DescriptorQueryManager) runtimeDescriptor.getQueryManager();
rtQueryManager.setQueryTimeout(getQueryTimeout().intValue());
for (Iterator i = queries(); i.hasNext(); ) {
rtQueryManager.addQuery(((MWQuery) i.next()).runtimeQuery());
}
}
public void adjustFromRuntime(ClassDescriptor runtimeDescriptor) {
DescriptorQueryManager rtQueryManager = (DescriptorQueryManager) runtimeDescriptor.getQueryManager();
// queries
this.queries.clear();
//Iterating twice because there can be more than 1 query with the same name just different parameters
for (Iterator queryVectorIt = rtQueryManager.getQueries().values().iterator(); queryVectorIt.hasNext();)
{
Iterator queriesIterator = ((Vector) queryVectorIt.next()).iterator();
while(queriesIterator.hasNext())
{
DatabaseQuery query = (DatabaseQuery) queriesIterator.next();
MWQuery mwQuery;
if (query instanceof ReadObjectQuery) {
mwQuery = addReadObjectQuery(query.getName());
}
else if (query instanceof ReadAllQuery){
mwQuery = addReadAllQuery(query.getName());
}
else {
continue;
}
mwQuery.adjustFromRuntime((ObjectLevelReadQuery) query);
}
}
}
}