/*
* Copyright: (c) 2004-2011 Mayo Foundation for Medical Education and
* Research (MFMER). All rights reserved. MAYO, MAYO CLINIC, and the
* triple-shield Mayo logo are trademarks and service marks of MFMER.
*
* Except as contained in the copyright notice above, or as used to identify
* MFMER as the author of this software, the trade names, trademarks, service
* marks, or product names of the copyright holder shall not be used in
* advertising, promotion or otherwise in connection with this software without
* prior written authorization of the copyright holder.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package edu.mayo.cts2.framework.filter.directory;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import edu.mayo.cts2.framework.filter.match.StateAdjustingComponentReference;
import edu.mayo.cts2.framework.model.command.ResolvedFilter;
import edu.mayo.cts2.framework.model.core.MatchAlgorithmReference;
import edu.mayo.cts2.framework.model.directory.DirectoryResult;
import edu.mayo.cts2.framework.model.service.core.Query;
/**
* A {@link DirectoryBuilder} implementation based on incrementally building some "state"
* object and ultimately resolving it.
*
* Use this as opposed to {@link AbstractRemovingDirectoryBuilder} when the result set
* is too large to keep in memory, or if you are interacting with some sort of other query
* interface, such as JDBC or Lucene.
*
* @param <S> the generic type
* @param <T> the generic type
* @author <a href="mailto:kevin.peterson@mayo.edu">Kevin Peterson</a>
*/
public abstract class AbstractStateBuildingDirectoryBuilder<S,T> extends AbstractDirectoryBuilder<T> {
/** The match algorithm references. */
private Set<MatchAlgorithmReference> matchAlgorithmReferences =
new HashSet<MatchAlgorithmReference>();
private Set<StateAdjustingComponentReference<S>> stateAdjustingPropertyReference =
new HashSet<StateAdjustingComponentReference<S>>();
private Callback<S,T> callback;
private S initialState;
private List<StateBuildingRestriction<S>> restrictions = new ArrayList<StateBuildingRestriction<S>>();
/**
* Instantiates a new abstract state building directory builder.
*
* @param initialState the initial state
* @param callback the callback
*/
public AbstractStateBuildingDirectoryBuilder(S initialState, Callback<S,T> callback){
this(initialState, callback, null, null);
}
/**
* Instantiates a new abstract state building directory builder.
*
* @param initialState the initial state
* @param callback the callback
* @param matchAlgorithmReferences the match algorithm references
* @param modelAttributeReferences the model attribute references
*/
public AbstractStateBuildingDirectoryBuilder(
S initialState,
Callback<S,T> callback,
Set<MatchAlgorithmReference> matchAlgorithmReferences,
Set<StateAdjustingComponentReference<S>> stateAdjustingPropertyReferences
){
super();
this.initialState = initialState;
this.callback = callback;
this.matchAlgorithmReferences = matchAlgorithmReferences;
this.stateAdjustingPropertyReference = stateAdjustingPropertyReferences;
}
/**
* Adds the supported model attribute reference.
*
* @param reference the reference
* @return the directory builder
*/
public DirectoryBuilder<T> addStateAdjustingPropertyReference(
StateAdjustingComponentReference<S> reference){
this.stateAdjustingPropertyReference.add(reference);
return this;
}
/*
* (non-Javadoc)
*
* @see
* org.cts2.internal.model.uri.restrict.ListBasedResolvingRestrictionHandler
* #restrict(java.util.List, org.cts2.core.Filter)
*/
public DirectoryResult<T> resolve() {
return this.callback.execute(computeState(), getStart(), getMaxToReturn());
}
/* (non-Javadoc)
* @see edu.mayo.cts2.framework.filter.directory.DirectoryBuilder#count()
*/
public int count() {
return this.callback.executeCount(computeState());
}
/**
* Compute state.
*
* @return the s
*/
private S computeState() {
S state = this.initialState;
for (final ResolvedFilter filter : this.getFilterComponents()) {
if(filter == null){
continue;
}
MatchAlgorithmReference matchAlgorithmReference =
this.getMatchAlgorithm(filter.getMatchAlgorithmReference(), matchAlgorithmReferences);
String queryString = filter.getMatchValue();
StateAdjustingComponentReference<S> modelAttributeReference =
this.getComponentReference(
filter.getComponentReference(),
this.stateAdjustingPropertyReference);
state = modelAttributeReference.updateState(
state,
matchAlgorithmReference,
queryString);
}
for(StateBuildingRestriction<S> restriction : this.getRestrictions()){
state = restriction.restrict(state);
}
return state;
}
/**
* Process query.
*
* @param query the query
*/
protected void processQuery(Query query){
//
}
/**
* Update state directly. Clients can use this for state changes that aren't
* necessarily a result of filtering, such as restrictions.
*
* @param state the new state
*/
protected void updateState(S state){
this.initialState = state;
}
/**
* Gets the current state. In general, this should only be called if needing
* a current state reference when using the {@link #updateState(Object)} method.
*
* @return the current state
*/
protected S getState(){
return this.initialState;
}
/**
* The Interface Callback.
*
* @param <S> the generic type
* @param <T> the generic type
* @author <a href="mailto:kevin.peterson@mayo.edu">Kevin Peterson</a>
*/
public static interface Callback<S,T> {
/**
* Execute.
*
* @param state the state
* @param start the start
* @param maxResults the max results
* @return the directory result
*/
public DirectoryResult<T> execute(
S state,
int start,
int maxResults);
/**
* Execute count.
*
* @param state the state
* @return the int
*/
public int executeCount(
S state);
}
/**
* The Interface StateBuildingRestriction.
*
* @param <S> the generic type
* @author <a href="mailto:kevin.peterson@mayo.edu">Kevin Peterson</a>
*/
public static interface StateBuildingRestriction<S> {
/**
* Restrict.
*
* @param state the state
* @return the s
*/
public S restrict(S state);
}
protected List<StateBuildingRestriction<S>> getRestrictions() {
return restrictions;
}
protected void setRestrictions(List<StateBuildingRestriction<S>> restrictions) {
this.restrictions = restrictions;
}
}