Mercurial > dive4elements > gnv-client
view gnv-artifacts/src/main/java/de/intevation/gnv/state/StateBase.java @ 1109:2b4d197a538c
Fixed the time range validation - introduced an epsilon of one second for valid time ranges (issue286).
gnv-artifacts/trunk@1240 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Ingo Weinzierl <ingo.weinzierl@intevation.de> |
---|---|
date | Tue, 29 Jun 2010 09:07:26 +0000 |
parents | cc4ec127d666 |
children | f953c9a559d8 |
line wrap: on
line source
package de.intevation.gnv.state; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.TreeMap; import javax.xml.xpath.XPathConstants; import net.sf.ehcache.Cache; import org.apache.log4j.Logger; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import de.intevation.artifactdatabase.Config; import de.intevation.artifactdatabase.XMLUtils; import de.intevation.artifacts.ArtifactNamespaceContext; import de.intevation.artifacts.CallContext; import de.intevation.artifacts.CallMeta; import de.intevation.gnv.artifacts.cache.CacheFactory; import de.intevation.gnv.artifacts.ressource.RessourceFactory; import de.intevation.gnv.geobackend.base.Result; import de.intevation.gnv.geobackend.base.query.QueryExecutor; import de.intevation.gnv.geobackend.base.query.QueryExecutorFactory; import de.intevation.gnv.geobackend.base.query.exception.QueryException; import de.intevation.gnv.geobackend.util.DateUtils; import de.intevation.gnv.state.describedata.DefaultKeyValueDescribeData; import de.intevation.gnv.state.describedata.KeyValueDescibeData; import de.intevation.gnv.state.describedata.MinMaxDescribeData; import de.intevation.gnv.state.describedata.NamedArrayList; import de.intevation.gnv.state.describedata.NamedCollection; import de.intevation.gnv.state.describedata.SingleValueDescribeData; import de.intevation.gnv.state.exception.StateException; import de.intevation.gnv.utils.ArtifactXMLUtilities; import de.intevation.gnv.utils.InputValidator; /** * This is the major implementation of <code>State</code>. Nearly every other * state is derived by this class. * * @author <a href="mailto:tim.englich@intevation.de">Tim Englich</a> * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> * @author <a href="mailto:sascha.teichmann@intevation.de">Sascha L. Teichmann</a> */ public abstract class StateBase implements State { /** * The UID of this Class */ private static final long serialVersionUID = 2411169179001645426L; /** * the logger, used to log exceptions and additonaly information */ private static Logger log = Logger.getLogger(StateBase.class); protected final static String MINVALUEFIELDNAME = "minvalue"; protected final static String MAXVALUEFIELDNAME = "maxvalue"; private final static String NODATASELECTIONKEY = "n/n"; public final static String DESCRIBEDATAKEY = "_DESCRIBEDATA"; public final static String XPATH_STATIC_UI = "art:static"; public final static String XPATH_DYNAMIC_UI = "art:dynamic"; public static final String EXCEPTION_NO_INPUT = "no.input.data"; public static final String EXCEPTION_INVALID_INPUT = "input.is.not.valid"; public final static String HASH_ID_SEPARATOR = "#"; /** input value names which should not be rendered from State itself */ public final static String[] BLACKLIST = {"sourceid", "fisname"}; private String id = null; protected String hash; private String description = null; protected String dataName = null; protected String preSettingsName = null; protected boolean dataMultiSelect = false; protected boolean dataNoSelect = false; protected String queryID = null; protected Collection<String> inputValueNames = null; protected Map<String, InputValue> inputValues = null; protected State parent = null; protected Map<String, InputData> inputData = null; protected Map<String, InputData> preSettings = null; /** * The source date format as string. */ public static String srcDateFormat = "yyyy.MM.dd hh:mm:ss"; /** * The source date format used to read string represented strings. */ public static DateFormat srcFormat; static { srcFormat = new SimpleDateFormat(srcDateFormat); } /** * Constructor */ public StateBase() { super(); } public String getID() { return this.id; } public String getDescription() { return this.description; } public Collection<InputValue> getRequiredInputValues() { return this.inputValues.values(); } public void reset(String uuid) { inputData.remove(dataName); } public void setup(Node configuration) { this.id = ((Element)configuration).getAttribute("id"); this.description = ((Element)configuration).getAttribute("description"); log.info("State-ID = " + this.id); NodeList inputValuesNodes = Config.getNodeSetXPath(configuration, "inputvalues/inputvalue"); this.inputValues = new HashMap<String, InputValue>(inputValuesNodes .getLength()); this.inputValueNames = new ArrayList<String>(inputValuesNodes .getLength()); for (int i = 0; i < inputValuesNodes.getLength(); i++) { Element inputValueNode = (Element)inputValuesNodes.item(i); String usedinQueryValue = inputValueNode.getAttribute("usedinquery"); int usedinQuery = 1; if (usedinQueryValue != null) { try { usedinQuery = Integer.parseInt(usedinQueryValue); } catch (NumberFormatException e) { log .warn("Used in Query Value cannot be transformed into a Number"); } } InputValue inputValue = new DefaultInputValue(inputValueNode.getAttribute("name"), inputValueNode.getAttribute("type"), Boolean.parseBoolean(inputValueNode. getAttribute("multiselect")), usedinQuery); this.inputValues.put(inputValue.getName(), inputValue); this.inputValueNames.add(inputValue.getName()); } this.queryID = Config.getStringXPath(configuration, "queryID"); log.info("QueryID ==> " + this.queryID); this.dataName = Config.getStringXPath(configuration, "dataname"); String dataMultiSelectValue = Config.getStringXPath(configuration, "data-multiselect"); if (dataMultiSelectValue != null) { this.dataMultiSelect = Boolean.parseBoolean(dataMultiSelectValue); } String dataNoSelectValue =Config.getStringXPath(configuration, "data-noselect"); if (dataNoSelectValue != null) { this. dataNoSelect = Boolean.parseBoolean(dataNoSelectValue); } this.preSettingsName = Config.getStringXPath(configuration, "presettings-name"); } public State getParent() { return this.parent; } public void setParent(State state) { this.parent = state; } public Document feed( CallContext context, Collection<InputData> inputData, String uuid) throws StateException { RessourceFactory resFactory = RessourceFactory.getInstance(); Locale[] serverLocales = resFactory.getLocales(); Locale locale = context.getMeta().getPreferredLocale( serverLocales); if (inputData != null) { Iterator<InputData> it = inputData.iterator(); InputValidator iv = new InputValidator(); while (it.hasNext()) { InputData tmpItem = it.next(); InputValue inputValue = this.inputValues.get(tmpItem.getName()); if (inputValue != null) { if (this.inputData == null) { this.inputData = new TreeMap<String, InputData>(); } boolean valid = InputValidator.isInputValid(tmpItem.getValue(), inputValue.getType()); if (valid) { if (tmpItem.getName().equals(this.dataName)){ String[] desc = getDescriptionForInputData( tmpItem, context, uuid); tmpItem.setDescription(desc); } this.inputData.put(tmpItem.getName(), tmpItem); } else { String msg = resFactory.getRessource( locale, EXCEPTION_INVALID_INPUT, EXCEPTION_INVALID_INPUT); log.warn(msg); return feedFailure(msg); } } else { String msg = resFactory.getRessource( locale, EXCEPTION_INVALID_INPUT, EXCEPTION_INVALID_INPUT); log.warn(msg); return feedFailure(msg); } } return feedSuccess(); } else { String msg = resFactory.getRessource( locale, EXCEPTION_NO_INPUT, EXCEPTION_NO_INPUT); log.warn(msg); return feedFailure(msg); } } protected Document feedSuccess() { return ArtifactXMLUtilities.createSuccessReport( "Initialize success", XMLUtils.newDocument()); } protected Document feedFailure(String msg) { return ArtifactXMLUtilities.createInputExceptionReport( msg, XMLUtils.newDocument()); } protected String[] getDescriptionForInputData( InputData data, CallContext context, String uuid) { // there is only one element in the list, so take the first Object obj = getDescibeData(uuid).get(0); List descs = new ArrayList(); if (obj instanceof NamedArrayList) { NamedArrayList list = (NamedArrayList) obj; List selected = Arrays.asList(data.splitValue()); int size = list.size(); for (int i = 0; i < size; i++) { KeyValueDescibeData kv = (KeyValueDescibeData) list.get(i); // values are concatinated in InputData, so one InputData object can // contain many input String key = kv.getKey(); int idx = selected.indexOf(key); if (idx >= 0) { descs.add(kv.getValue()); // XXX Workarround: I just wanted to remove the element at // 'idx' from selected, but for any reason this is not // possible (throws an exception) (iw) List tmp = new ArrayList(); for (int j = 0; j < selected.size(); j++) { if (j != idx) tmp.add(selected.get(j)); } selected = tmp; } } } return (String[]) descs.toArray(new String[descs.size()]); } public void putInputData(Collection<InputData> inputData, String uuid) throws StateException { if (inputData != null) { Iterator<InputData> it = inputData.iterator(); InputValidator iv = new InputValidator(); while (it.hasNext()) { InputData tmpItem = it.next(); InputValue inputValue = this.inputValues.get(tmpItem.getName()); if (inputValue != null) { if (this.inputData == null) { this.inputData = new TreeMap<String, InputData>(); } boolean valid = InputValidator.isInputValid(tmpItem.getValue(), inputValue.getType()); if (valid) { if (tmpItem.getName().equals(MINVALUEFIELDNAME)){ String minValue = tmpItem.getValue(); String maxValue = this.getInputValue4ID(inputData, MAXVALUEFIELDNAME); valid = InputValidator.isInputValid(maxValue,inputValue.getType()); if (!valid){ String errMsg = "Wrong input for " + tmpItem.getValue() + " is not an " + inputValue.getType() + " Value."; log.warn(errMsg); throw new StateException(errMsg); } valid = InputValidator.isInputValid(minValue, maxValue, inputValue.getType()); if (!valid){ String errMsg = "MaxValue-Input is less than MinValue-Input "; log.warn(errMsg); throw new StateException(errMsg); } }else if (tmpItem.getName().equals(MAXVALUEFIELDNAME)){ String minValue = this.getInputValue4ID(inputData, MINVALUEFIELDNAME); String maxValue = tmpItem.getValue(); valid = InputValidator.isInputValid(minValue,inputValue.getType()); if (!valid){ String errMsg = "Wrong input for " + tmpItem.getValue() + " is not an " + inputValue.getType() + " Value."; log.warn(errMsg); throw new StateException(errMsg); } valid = InputValidator.isInputValid(minValue, maxValue, inputValue.getType()); if (!valid){ String errMsg = "MaxValue-Input is less than MinValue-Input "; log.warn(errMsg); throw new StateException(errMsg); } } this.inputData.put(tmpItem.getName(), tmpItem); } else { String errMsg = "Wrong input for " + tmpItem.getValue() + " is not an " + inputValue.getType() + " Value."; log.warn(errMsg); throw new StateException(errMsg); } } else { String errMsg = "No Inputvalue given for Inputdata " + tmpItem.getName(); log.warn(errMsg + "Value will be ignored"); } } } else { log.warn("No Inputdata given"); } setHash(uuid); } public void setPreSettings(Map<String, InputData> preSettings) { this.preSettings = preSettings; } public Map<String, InputData> getPreSettings() { return this.preSettings; } protected String getInputValue4ID(Collection<InputData> inputData, String inputName){ Iterator<InputData> it = inputData.iterator(); while (it.hasNext()) { InputData tmpItem = it.next(); if (tmpItem.getName().equals(inputName)){ return tmpItem.getValue(); } } return null; } public void advance(String uuid, CallContext context) throws StateException { } public void initialize(String uuid, CallContext context) throws StateException { } protected String[] generateFilterValuesFromInputData() { List<String> list = new ArrayList<String>(); Iterator<String> it = this.inputValueNames.iterator(); while (it.hasNext()) { String value = it.next(); InputData data = this.inputData.get(value); if (data != null && this.inputValues.containsKey(data.getName())) { int size = this.inputValues.get(data.getName()) .usedInQueries(); String type = this.inputValues.get(data.getName()) .getType(); String requestValue = data.getValue(); if (type.equalsIgnoreCase("string")) { requestValue = this .prepareInputData4DBQuery(requestValue); } else if (type.equalsIgnoreCase("date")) { requestValue = this .prepareInputData4DateDBQuery(requestValue); } else if (type.equalsIgnoreCase("coordinate") || (type.equalsIgnoreCase("geometry") && requestValue.toLowerCase().startsWith("point"))){ requestValue = this .prepareInputData4RegionDBQuery(requestValue); } for (int j = 0; j < size; j++) { list.add(requestValue); } } } String[] filterValues = list.toArray(new String[list.size()]); return filterValues; } protected String prepareInputData4RegionDBQuery(String value){ return value; } private String prepareInputData4DateDBQuery(String value) { if (value != null) { String[] values = value.split(","); String newValue = ""; for (int i = 0; i < values.length; i++) { if (newValue.length() > 0) { newValue = newValue + " , "; } // TODO JUST HACK FIND A BETTER RESOLUTION newValue = newValue + "to_date('" + values[i].trim() + "', 'YYYY.MM.DD HH24:MI:SS')"; } return newValue; } return value; } private String prepareInputData4DBQuery(String value) { if (value != null) { String[] values = value.split(","); String newValue = ""; for (int i = 0; i < values.length; i++) { if (newValue.length() > 0) { newValue = newValue + " , "; } newValue = newValue + "'" + values[i].trim() + "'"; } return newValue; } return value; } protected List<Object> purifyResult(Collection<Result> result, String uuid) { List<Object> describeData = new ArrayList<Object>(); NamedCollection<KeyValueDescibeData> keyValueDescibeData = extractKVP(result, "KEY", "VALUE"); describeData.add(keyValueDescibeData); return describeData; } protected NamedCollection<KeyValueDescibeData> extractKVP(Collection<Result> result, String keyid, String valueid) { Iterator<Result> rit = result.iterator(); int dataSize = (this.dataNoSelect ? result.size()+1 : result.size()); NamedCollection<KeyValueDescibeData> keyValueDescibeData = new NamedArrayList<KeyValueDescibeData>( this.dataName, dataSize); keyValueDescibeData.setMultiSelect(this.dataMultiSelect); if (this.dataNoSelect){ keyValueDescibeData.add(new DefaultKeyValueDescribeData( NODATASELECTIONKEY, "No Selection", getID() )); } boolean initialized = false; int keyPos = 0; int valuePos = 1; String previousKey = null; InputData preSettingsData = (this.preSettings != null && this.preSettingsName != null) ? this.preSettings.get(this.preSettingsName) : null; boolean filterWithPresettings = preSettingsData != null; List<String> preSettingValues = null; if(filterWithPresettings){ preSettingValues = Arrays.asList(preSettingsData.splitValue()); } while (rit.hasNext()) { Result resultValue = rit.next(); if (!initialized){ keyPos = resultValue.getResultDescriptor().getColumnIndex(keyid); valuePos = resultValue.getResultDescriptor().getColumnIndex(valueid); if (valuePos < 0){ valuePos = 1; } initialized = true; } String tmpKey = resultValue.getString(keyPos); // TODO: FIXME: We have to do that because the arcsde does not // support a distinct Query on Layers. if (previousKey == null || !tmpKey.equals(previousKey)){ previousKey = tmpKey; if (!filterWithPresettings || preSettingValues.contains(tmpKey)){ keyValueDescibeData.add( new DefaultKeyValueDescribeData( tmpKey, resultValue.getString(valuePos), getID()) ); } } } return keyValueDescibeData; } public static boolean inBlackList(String key) { int length = BLACKLIST.length; for (int i = 0; i < length; i++) { if (BLACKLIST[i].equals(key)) { return true; } } return false; } public void describe( Document document, Node rootNode, CallContext context, String uuid) { XMLUtils.ElementCreator xCreator = new XMLUtils.ElementCreator( document, XMLUtils.XFORM_URL, XMLUtils.XFORM_PREFIX ); XMLUtils.ElementCreator creator = new XMLUtils.ElementCreator( document, ArtifactNamespaceContext.NAMESPACE_URI, ArtifactNamespaceContext.NAMESPACE_PREFIX ); // append dynamic node Node dynamic = (Node) XMLUtils.xpath( rootNode, XPATH_DYNAMIC_UI, XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE ); describeDynamic( creator, xCreator, document, dynamic, context, uuid); // append static nodes Node staticNode = (Node) XMLUtils.xpath( rootNode, XPATH_STATIC_UI, XPathConstants.NODE, ArtifactNamespaceContext.INSTANCE ); State parent = getParent(); if (parent != null && parent instanceof StateBase) { ((StateBase) parent).describeStatic( creator,xCreator, document, staticNode, context,uuid); } } protected void describeDynamic( XMLUtils.ElementCreator artCreator, XMLUtils.ElementCreator creator, Document document, Node dynamic, CallContext context, String uuid) { CallMeta callMeta = context.getMeta(); if (dataName == null) return; List<Object> descibeData = getDescibeData(uuid); if (descibeData != null) { Iterator<Object> it = descibeData.iterator(); while (it.hasNext()) { Object o = it.next(); if ((!it.hasNext() && dataName != null)) { appendToDynamicNode( artCreator, creator, document, dynamic, callMeta, o); } } } } protected void describeStatic( XMLUtils.ElementCreator artCreator, XMLUtils.ElementCreator creator, Document document, Node staticNode, CallContext context, String uuid) { State parent = getParent(); if (parent instanceof StateBase) { ((StateBase) parent).describeStatic( artCreator, creator, document, staticNode, context, uuid); } CallMeta callMeta = context.getMeta(); appendToStaticNode(artCreator, creator, document, staticNode, callMeta); } protected void appendToStaticNode( XMLUtils.ElementCreator artCreator, XMLUtils.ElementCreator creator, Document document, Node staticNode, CallMeta callMeta ) { InputData data = dataName!= null ? inputData.get(dataName) : null; if (data == null) { return; } Element selectNode = creator.create("select1"); creator.addAttr(selectNode, "ref", dataName); Element lableNode = creator.create("label"); lableNode.setTextContent(RessourceFactory.getInstance() .getRessource(callMeta.getLanguages(), dataName, dataName)); Element choiceNode = creator.create("choices"); artCreator.addAttr( selectNode, "state", getID(), true ); String[] descriptions = data.getDescription(); int size = descriptions.length; for (int i = 0; i < size; i++) { Element itemNode = creator.create("item"); String value = data.getValue(); String desc = descriptions[i]; desc = desc == null ? value : desc; creator.addAttr(itemNode, "selected", "true"); Element choiceLableNode = creator.create("label"); choiceLableNode.setTextContent(desc); itemNode.appendChild(choiceLableNode); Element choiceValueNode = creator.create("value"); choiceValueNode.setTextContent(value); itemNode.appendChild(choiceValueNode); choiceNode.appendChild(itemNode); } selectNode.appendChild(lableNode); selectNode.appendChild(choiceNode); staticNode.appendChild(selectNode); } protected void appendToDynamicNode( XMLUtils.ElementCreator artCreator, XMLUtils.ElementCreator creator, Document document, Node dynamicNode, CallMeta callMeta, Object o ) { if (o instanceof Collection<?>) { String name = null; boolean multiselect = false; if (o instanceof NamedCollection<?>) { NamedCollection<?> nc = ((NamedCollection<?>) o); name = nc.getName(); multiselect = nc.isMultiSelect(); } else { Object[] names = this.inputValueNames.toArray(); name = names[names.length - 1].toString(); } Element selectNode = creator.create(multiselect?"select":"select1"); creator.addAttr(selectNode, "ref", name); Element lableNode = creator.create("label"); lableNode.setTextContent(RessourceFactory.getInstance() .getRessource(callMeta.getLanguages(), name, name)); Element choiceNode = creator.create("choices"); Collection<KeyValueDescibeData> values = (Collection<KeyValueDescibeData>) o; Iterator<KeyValueDescibeData> resultIt = values.iterator(); while (resultIt.hasNext()) { KeyValueDescibeData result = resultIt.next(); Element itemNode = creator.create("item"); if (result.isSelected()) { itemNode.setAttribute("selected", "true"); } Element choiceLableNode = creator.create("label"); choiceLableNode.setTextContent(result.getValue()); itemNode.appendChild(choiceLableNode); Element choicValueNode = creator.create("value"); choicValueNode.setTextContent("" + result.getKey()); itemNode.appendChild(choicValueNode); choiceNode.appendChild(itemNode); } selectNode.appendChild(lableNode); selectNode.appendChild(choiceNode); dynamicNode.appendChild(selectNode); } else if (o instanceof MinMaxDescribeData) { appendMinMaxDescribeData( artCreator, creator, document, dynamicNode, callMeta, o); } else if (o instanceof SingleValueDescribeData) { appendSingleValueDescribeData( artCreator, creator, document, dynamicNode, callMeta, o); } } protected void appendMinMaxDescribeData( XMLUtils.ElementCreator artCreator, XMLUtils.ElementCreator creator, Document document, Node node, CallMeta callMeta, Object o ) { MinMaxDescribeData minMaxDescibeData = (MinMaxDescribeData) o; Object min = minMaxDescibeData.getMinValue(); Object max = minMaxDescibeData.getMaxValue(); if (min instanceof GregorianCalendar) { Date d = ((GregorianCalendar) min).getTime(); min = DateUtils.getPatternedDateAmer(d); } if (max instanceof GregorianCalendar) { Date d = ((GregorianCalendar) max).getTime(); max = DateUtils.getPatternedDateAmer(d); } Element groupNode = creator.create("group"); artCreator.addAttr(groupNode, "state", minMaxDescibeData.getState(), true); creator.addAttr(groupNode, "ref", minMaxDescibeData.getName()); Element groupNodeLableNode = creator.create("label"); groupNodeLableNode.setTextContent(RessourceFactory .getInstance().getRessource( callMeta.getLanguages(), minMaxDescibeData.getName(), minMaxDescibeData.getName())); groupNode.appendChild(groupNodeLableNode); Element inputMinNode = creator.create("input"); creator.addAttr(inputMinNode, "ref", MINVALUEFIELDNAME); Element inputMinLableNode = creator.create("label"); inputMinLableNode.setTextContent(RessourceFactory .getInstance().getRessource( callMeta.getLanguages(), MINVALUEFIELDNAME, MINVALUEFIELDNAME)); inputMinNode.appendChild(inputMinLableNode); Element inputMinValueNode = creator.create("value"); inputMinValueNode.setTextContent(min.toString()); inputMinNode.appendChild(inputMinValueNode); Element inputMaxNode = creator.create("input"); creator.addAttr(inputMaxNode, "ref", MAXVALUEFIELDNAME); Element inputMaxLableNode = creator.create("label"); inputMaxLableNode.setTextContent(RessourceFactory .getInstance().getRessource( callMeta.getLanguages(), MAXVALUEFIELDNAME, MAXVALUEFIELDNAME)); inputMaxNode.appendChild(inputMaxLableNode); Element inputMaxValueNode = creator.create("value"); inputMaxValueNode.setTextContent(max.toString()); inputMaxNode.appendChild(inputMaxValueNode); groupNode.appendChild(inputMinNode); groupNode.appendChild(inputMaxNode); node.appendChild(groupNode); } protected void appendSingleValueDescribeData( XMLUtils.ElementCreator artCreator, XMLUtils.ElementCreator creator, Document document, Node node, CallMeta callMeta, Object o ) { SingleValueDescribeData svdb = (SingleValueDescribeData) o; Element groupNode = creator.create("group"); artCreator.addAttr(groupNode, "state", svdb.getState(), true); creator.addAttr(groupNode, "ref", svdb.getName()); Element groupNodeLableNode = creator.create("label"); groupNodeLableNode.setTextContent(RessourceFactory .getInstance().getRessource( callMeta.getLanguages(), svdb.getName(), svdb.getName())); groupNode.appendChild(groupNodeLableNode); Element inputNode = creator.create("input"); creator.addAttr(inputNode, "ref", svdb.getName()); Element inputLableNode = creator.create("label"); inputLableNode.setTextContent(""); inputNode.appendChild(inputLableNode); Element inputValueNode = creator.create("value"); inputValueNode.setTextContent(svdb.getValue()); inputNode.appendChild(inputValueNode); groupNode.appendChild(inputNode); node.appendChild(groupNode); } protected void setHash(String uuid) { String newHash = uuid + HASH_ID_SEPARATOR + id + HASH_ID_SEPARATOR; Set keys = inputData.keySet(); int nhash = 0; int shift = 0; for (Object o: keys) { nhash ^= inputData.get(o).hashCode() << shift; shift += 2; } log.info("### OLD HASH: " + hash); log.info("### NEW HASH: " + (newHash + nhash)); this.hash = newHash + nhash; } protected String getHash() { return this.hash; } public List<Object> getDescibeData(String uuid) { CacheFactory factory = CacheFactory.getInstance(); if (factory.isInitialized()) { // we use a cache Cache cache = factory.getCache(); String key = getHash(); log.debug("Using cache - key: " + key); net.sf.ehcache.Element value = cache.get(key); if (value != null) { // element already in cache, so return it. log.debug("Found element in cache."); return (List<Object>) (value.getObjectValue()); } else { // element is not in cache yet, so we need to fetch data from // database and put it into cache right now log.debug("Element not in cache, we need to ask the database"); try { String[] filterValues = generateFilterValuesFromInputData(); List<Object> data = queryDatabase(filterValues, uuid); cache.put(new net.sf.ehcache.Element(key, data)); return data; } catch (QueryException qe) { log.error(qe, qe); } } } else { // we don't use a cache, so we have to query the database every // single time log.debug("Not using cache."); String[] filterValues = generateFilterValuesFromInputData(); Collection<Result> result = null; try { return queryDatabase(filterValues, uuid); } catch (RuntimeException e) { log.error(e, e); } catch (QueryException e) { log.error(e, e); } } return null; } protected List<Object> queryDatabase(String[] filterValues, String uuid) throws QueryException { Collection<Result> result = null; if (queryID != null) { QueryExecutor queryExecutor = QueryExecutorFactory.getInstance().getQueryExecutor(); result = queryExecutor.executeQuery(queryID, filterValues); } return purifyResult(result, uuid); } public Map<String, InputData> inputData() { return inputData; } public Collection<InputData> getInputData() throws StateException { return this.inputData != null ? this.inputData.values() : null; } public InputData getInputDataByName(String name) { State state = this; while (state != null) { InputData data = state.inputData().get(name); if (data != null) { return data; } state = state.getParent(); } return null; } public void endOfLife(Object globalContext) { log.debug("end of life of the current state."); CacheFactory factory = CacheFactory.getInstance(); if (factory.isInitialized()) { Cache cache = factory.getCache(); String key = getHash(); if (key != null && cache.remove(key)) { log.info("Removed element from cache - key: " + key); } } } public void cleanup(Object context) { } } // vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :