Implemented the data mining query management for dimension values queries

This commit is contained in:
Lennart Hensler committed 2015-04-30 22:15:50 +02:00
1 parent bbb71b1e31
commit b6b97b0afa
10 files changed
+206 -47

No files matched your search

@@ -13,6 +13,8 @@ public interface Query<AggregatedType> {
public AdditionalQueryData getAdditionalData();
public <T extends AdditionalQueryData> T getSpecificAdditionalData(Class<T> additionalDataType);
public QueryResult<AggregatedType> run();
public QueryResult<AggregatedType> run(long timeout, TimeUnit unit) throws TimeoutException;
@@ -20,8 +20,9 @@ import com.sap.sse.datamining.components.Processor;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.functions.ParameterProvider;
import com.sap.sse.datamining.functions.ParameterizedFunction;
import com.sap.sse.datamining.impl.AdditionalDimensionValuesQueryData;
import com.sap.sse.datamining.impl.AdditionalStandardQueryData;
import com.sap.sse.datamining.impl.ProcessorQuery;
import com.sap.sse.datamining.impl.SimpleAdditionalQueryData;
import com.sap.sse.datamining.impl.components.GroupedDataEntry;
import com.sap.sse.datamining.impl.criterias.AndCompoundFilterCriterion;
import com.sap.sse.datamining.impl.criterias.CompoundFilterCriterion;
@@ -35,7 +36,7 @@ public class QueryFactory {
public <DataSourceType, DataType, ResultType> Query<ResultType> createQuery(DataSourceType dataSource, QueryDefinition<DataSourceType, DataType, ResultType> queryDefinition,
ResourceBundleStringMessages stringMessages, ExecutorService executor) {
return new ProcessorQuery<ResultType, DataSourceType>(dataSource, stringMessages, queryDefinition.getLocale(), new SimpleAdditionalQueryData(QueryType.STATISTIC, queryDefinition.getDataRetrieverChainDefinition().getID())) {
return new ProcessorQuery<ResultType, DataSourceType>(dataSource, stringMessages, queryDefinition.getLocale(), new AdditionalStandardQueryData(QueryType.STATISTIC, queryDefinition.getDataRetrieverChainDefinition().getID())) {
@Override
protected Processor<DataSourceType, ?> createFirstProcessor() {
ProcessorFactory processorFactory = new ProcessorFactory(executor);
@@ -121,7 +122,7 @@ public class QueryFactory {
final DataRetrieverChainDefinition<DataSource, ?> dataRetrieverChainDefinition, final int retrieverLevel,
final Iterable<Function<?>> dimensions, final Map<Integer, Map<Function<?>, Collection<?>>> filterSelection, final Locale locale,
final ResourceBundleStringMessages stringMessages, final ExecutorService executor) {
return new ProcessorQuery<Set<Object>, DataSource>(dataSource, stringMessages, locale, new SimpleAdditionalQueryData(QueryType.DIMENSION_VALUES, dataRetrieverChainDefinition.getID())) {
return new ProcessorQuery<Set<Object>, DataSource>(dataSource, stringMessages, locale, new AdditionalDimensionValuesQueryData(QueryType.DIMENSION_VALUES, dataRetrieverChainDefinition.getID(), dimensions)) {
@Override
protected Processor<DataSource, ?> createFirstProcessor() {
ProcessorFactory processorFactory = new ProcessorFactory(executor);
@@ -0,0 +1,21 @@
package com.sap.sse.datamining.impl;
import java.util.UUID;
import com.sap.sse.datamining.Query.QueryType;
import com.sap.sse.datamining.functions.Function;
public class AdditionalDimensionValuesQueryData extends AdditionalStandardQueryData {
private final Iterable<Function<?>> dimensions;
public AdditionalDimensionValuesQueryData(QueryType type, UUID dataRetrieverChainID, Iterable<Function<?>> dimensions) {
super(type, dataRetrieverChainID);
this.dimensions = dimensions;
}
public Iterable<Function<?>> getDimensions() {
return dimensions;
}
}
@@ -5,12 +5,12 @@ import java.util.UUID;
import com.sap.sse.datamining.AdditionalQueryData;
import com.sap.sse.datamining.Query.QueryType;
public class SimpleAdditionalQueryData implements AdditionalQueryData {
public class AdditionalStandardQueryData implements AdditionalQueryData {
private final QueryType type;
private final UUID dataRetrieverChainID;
public SimpleAdditionalQueryData(QueryType type, UUID dataRetrieverChainID) {
public AdditionalStandardQueryData(QueryType type, UUID dataRetrieverChainID) {
this.type = type;
this.dataRetrieverChainID = dataRetrieverChainID;
}
@@ -83,6 +83,15 @@ public abstract class ProcessorQuery<AggregatedType, DataSourceType> implements
public AdditionalQueryData getAdditionalData() {
return additionalData;
}
@Override
@SuppressWarnings("unchecked")
public <T extends AdditionalQueryData> T getSpecificAdditionalData(Class<T> additionalDataType) {
if (additionalDataType.isAssignableFrom(getAdditionalData().getClass())) {
return (T) getAdditionalData();
}
return null;
}
@Override
public QueryResult<AggregatedType> run() {
@@ -0,0 +1,74 @@
package com.sap.sse.datamining.impl;
import java.util.Collection;
import java.util.HashSet;
import com.sap.sse.datamining.DataMiningQueryManager;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.Query.QueryType;
import com.sap.sse.datamining.functions.Function;
import com.sap.sse.datamining.impl.SingleQueryPerDimensionManager.Key;
import com.sap.sse.datamining.shared.DataMiningSession;
public class SingleQueryPerDimensionManager extends SingleQueryPerKeyManager<Key> {
@Override
protected <ResultType> Iterable<Key> getKeysFor(DataMiningSession session, Query<ResultType> query) {
AdditionalDimensionValuesQueryData additionalData = query.getSpecificAdditionalData(AdditionalDimensionValuesQueryData.class);
if (additionalData == null) {
throw new IllegalArgumentException("This " + DataMiningQueryManager.class.getSimpleName()
+ " can only manage queries of the " + QueryType.class.getSimpleName()
+ " " + QueryType.DIMENSION_VALUES);
}
Collection<Key> keys = new HashSet<>();
for (Function<?> dimension : additionalData.getDimensions()) {
keys.add(new Key(session, dimension));
}
return keys;
}
static class Key {
private DataMiningSession session;
private Function<?> dimension;
public Key(DataMiningSession session, Function<?> dimension) {
this.session = session;
this.dimension = dimension;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((dimension == null) ? 0 : dimension.hashCode());
result = prime * result + ((session == null) ? 0 : session.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Key other = (Key) obj;
if (dimension == null) {
if (other.dimension != null)
return false;
} else if (!dimension.equals(other.dimension))
return false;
if (session == null) {
if (other.session != null)
return false;
} else if (!session.equals(other.session))
return false;
return true;
}
}
}
@@ -0,0 +1,80 @@
package com.sap.sse.datamining.impl;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.sap.sse.datamining.DataMiningQueryManager;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.QueryState;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
public abstract class SingleQueryPerKeyManager<T> implements DataMiningQueryManager {
private final ConcurrentMap<T, Query<?>> queryMap;
public SingleQueryPerKeyManager() {
queryMap = new ConcurrentHashMap<>();
}
@Override
public <ResultType> QueryResult<ResultType> runNewAndAbortPrevious(DataMiningSession session, Query<ResultType> query) {
if (session == null || query == null) {
//Forbidding null Queries ensures the functionality of registerNewQuery
throw new NullPointerException();
}
Iterable<T> keys = getKeysFor(session, query);
validate(keys);
abortPreviousQueries(keys);
registerNewQuery(keys, query);
QueryResult<ResultType> result = query.run();
unregisterQuery(keys, query);
return result;
}
protected abstract <ResultType> Iterable<T> getKeysFor(DataMiningSession session, Query<ResultType> query);
private void validate(Iterable<T> keys) {
int size = 0;
for (T key : keys) {
if (key == null) {
throw new IllegalArgumentException("Null key was created for query.");
}
size++;
}
if (size == 0) {
throw new IllegalArgumentException("Unable to create keys for query.");
}
}
private void abortPreviousQueries(Iterable<T> keys) {
for (T key : keys) {
if (queryMap.containsKey(key)) {
Query<?> previousQuery = queryMap.get(key);
if (previousQuery.getState() == QueryState.RUNNING) {
previousQuery.abort();
}
queryMap.remove(key, previousQuery);
}
}
}
private <ResultType> void registerNewQuery(Iterable<T> keys, Query<ResultType> query) {
for (T key : keys) {
Query<?> previousValue = queryMap.putIfAbsent(key, query);
if (previousValue != null) {
throw new UnsupportedOperationException("There's allready a Query for the session: " + key);
}
}
}
private void unregisterQuery(Iterable<T> keys, Query<?> finishedQuery) {
for (T key : keys) {
queryMap.remove(key, finishedQuery);
}
}
}
@@ -1,52 +1,18 @@
package com.sap.sse.datamining.impl;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.Collection;
import java.util.HashSet;
import com.sap.sse.datamining.DataMiningQueryManager;
import com.sap.sse.datamining.Query;
import com.sap.sse.datamining.shared.DataMiningSession;
import com.sap.sse.datamining.shared.QueryResult;
public class SingleQueryPerSessionManager implements DataMiningQueryManager {
private final ConcurrentMap<DataMiningSession, Query<?>> queryMappedBySession;
public SingleQueryPerSessionManager() {
queryMappedBySession = new ConcurrentHashMap<>();
}
public class SingleQueryPerSessionManager extends SingleQueryPerKeyManager<DataMiningSession> {
@Override
public <ResultType> QueryResult<ResultType> runNewAndAbortPrevious(DataMiningSession session, Query<ResultType> query) {
if (session == null || query == null) {
//Forbidding null Queries ensures the functionality of registerNewQuery
throw new NullPointerException();
}
abortPreviousQueries(session);
registerNewQuery(session, query);
QueryResult<ResultType> result = query.run();
unregisterQuery(session, query);
return result;
}
private void abortPreviousQueries(DataMiningSession session) {
if (queryMappedBySession.containsKey(session)) {
Query<?> previousQuery = queryMappedBySession.get(session);
previousQuery.abort();
queryMappedBySession.remove(session, previousQuery);
}
}
private <ResultType> void registerNewQuery(DataMiningSession session, Query<ResultType> query) {
Query<?> previousValue = queryMappedBySession.putIfAbsent(session, query);
if (previousValue != null) {
throw new UnsupportedOperationException("There's allready a Query for the session: " + session);
}
}
private void unregisterQuery(DataMiningSession session, Query<?> finishedQuery) {
queryMappedBySession.remove(session, finishedQuery);
protected <ResultType> Iterable<DataMiningSession> getKeysFor(DataMiningSession session, Query<ResultType> query) {
Collection<DataMiningSession> keys = new HashSet<>();
keys.add(session);
return keys;
}
}
@@ -16,7 +16,7 @@ public class StrategyPerQueryTypeManager implements DataMiningQueryManager {
public StrategyPerQueryTypeManager() {
managersMappedByQueryType = new HashMap<>();
managersMappedByQueryType.put(QueryType.STATISTIC, new SingleQueryPerSessionManager());
managersMappedByQueryType.put(QueryType.DIMENSION_VALUES, NULL);
managersMappedByQueryType.put(QueryType.DIMENSION_VALUES, new SingleQueryPerDimensionManager());
managersMappedByQueryType.put(QueryType.OTHER, NULL);
}
@@ -22,5 +22,11 @@ public abstract class AbstractFunction<ReturnType> implements Function<ReturnTyp
protected Logger getLogger() {
return LOGGER;
}
//Enforce hash code and equals in all subclasses
@Override
public abstract boolean equals(Object other);
@Override
public abstract int hashCode();
}