Mercurial > dive4elements > gnv-client
diff gnv-artifacts/src/main/java/de/intevation/gnv/state/MeasurementState.java @ 1119:7c4f81f74c47
merged gnv-artifacts
author | Thomas Arendsen Hein <thomas@intevation.de> |
---|---|
date | Fri, 28 Sep 2012 12:14:00 +0200 |
parents | dec4257ad570 |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gnv-artifacts/src/main/java/de/intevation/gnv/state/MeasurementState.java Fri Sep 28 12:14:00 2012 +0200 @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2010 by Intevation GmbH + * + * This program is free software under the LGPL (>=v2.1) + * Read the file LGPL.txt coming with the software for details + * or visit http://www.gnu.org/licenses/ if it does not exist. + */ + +package de.intevation.gnv.state; + +import de.intevation.artifacts.common.utils.XMLUtils; + +import de.intevation.artifacts.CallContext; +import de.intevation.artifacts.CallMeta; + +import de.intevation.gnv.artifacts.ressource.RessourceFactory; + +import de.intevation.gnv.geobackend.base.Result; +import de.intevation.gnv.geobackend.base.ResultDescriptor; + +import de.intevation.gnv.state.describedata.ExtendedKeyValueData; +import de.intevation.gnv.state.describedata.KeyValueDescibeData; +import de.intevation.gnv.state.describedata.NamedArrayList; +import de.intevation.gnv.state.describedata.NamedCollection; + +import de.intevation.gnv.state.exception.StateException; + +import de.intevation.gnv.utils.InputValidator; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.TreeMap; + +import org.apache.log4j.Logger; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * This state handles input of measurements relating to a parameter. The user + * interface description created by this class represents a matrix - each + * parameter in a single row, each measurement in a column. An invalid + * measurement column for a specific parameter is marked as disabled and should + * not be selected. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ +public class MeasurementState +extends DefaultState +{ + private static Logger logger = Logger.getLogger(MeasurementState.class); + + public static final String SQL_KEY_PARAMETERID = "PARAMETERID"; + + public static final String SEPARATOR = ";"; + + + /** + * This class is used to generate the Matrix in <code>MinMaxDateState</code>. + * Parameter and Measurements are stored in separate lists and can be + * requested via different methods. + * + * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> + */ + private class ParameterMatrix { + private final Logger logger = + Logger.getLogger(ParameterMatrix.class); + + private List measurements; + private List mDescriptions; + private List parameters; + private boolean[][] values; + + /** + * Constructs a new matrix. + * + * @param data A collection containing the measurements. + * @param parameter An array of parameters. + */ + public ParameterMatrix(Collection data, String[] parameter) { + measurements = new ArrayList(data.size()); + mDescriptions = new ArrayList(data.size()); + parameters = new ArrayList(parameter.length); + + values = new boolean[data.size()][parameter.length]; + for (int i = 0; i < data.size(); i++) { + Arrays.fill(values[i], false); + } + + initParameters(parameter); + initMeasurements(data); + } + + /** + * Initialize the measurements used in this matrix. + * + * @param data The measurements. + */ + private void initMeasurements(Collection data) { + Iterator iter = data.iterator(); + while (iter.hasNext()) { + ExtendedKeyValueData value = (ExtendedKeyValueData) iter.next(); + String key = value.getKey(); + String val = value.getValue(); + String parameter = value.getParameter(); + + int i = measurements.indexOf(key); + int j = parameters.indexOf(parameter); + int tmp = mDescriptions.indexOf(val); + + if (i < 0) { + measurements.add(key); + i = measurements.indexOf(key); + + mDescriptions.add(val); + tmp = mDescriptions.indexOf(val); + } + + if (j < 0) { + logger.warn("Not a valid parameter: " + parameter); + } + + if (i >= 0 && i < measurements.size() && j >= 0 + && j < parameters.size()) + { + values[i][j] = true; + } + } + } + + /** + * Initialize the parameters used in this matrix. + * + * @param parameter Parameters. + */ + private void initParameters(String[] parameter) { + for (String param: parameter) { + parameters.add(param); + } + } + + /** + * Returns the number of measurements. + * + * @return the number of measurements. + */ + public int measurementSize() { + if (measurements != null) + return measurements.size(); + + return 0; + } + + /** + * Returns the number of parameters. + * + * @return number of parameters. + */ + public int parameterSize() { + if (parameters != null) + return parameters.size(); + + return 0; + } + + /** + * Returns the measurement at idx. + * + * @param idx Index. + * @return the measurement. + */ + public String getMeasurement(int idx) { + if (idx >= 0 && idx < measurements.size()) + return (String) measurements.get(idx); + + logger.warn("Index is out of bounds: " + idx); + return ""; + } + + /** + * Returns the parameter at idx. + * + * @param idx Index + * @return the parameter. + */ + public String getParameter(int idx) { + if (idx >= 0 && idx < parameters.size()) { + return (String) parameters.get(idx); + } + + logger.warn("Index is out of bounds: " + idx); + return ""; + } + + /** + * Returns a description text for a specific measurement. + * + * @param idx Index of a measurement. + * @return measurement's description. + */ + public String getMDescription(int idx) { + if (mDescriptions != null) { + return (String) mDescriptions.get(idx); + } + + return null; + } + + /** + * This method returns true, if a measurement is valid for a specific + * parameter - otherwise false. + * + * @param i Index of a measurement column. + * @param j Index of a parameter row. + * @return true, if valid, else false. + */ + public boolean isValid(int i, int j) { + if (i < 0 || i > measurements.size() + || j < 0 || j > parameters.size()) + { + logger.warn("Index out of bounds: " + i + "|" + j); + return false; + } + + return values[i][j]; + } + } // End of ParameterMatrix + + + public MeasurementState() { + super(); + } + + @Override + protected NamedCollection<KeyValueDescibeData> extractKVP( + Collection<Result> result, + String keyid, + String valueid + ) { + NamedCollection<KeyValueDescibeData> kvdd = + new NamedArrayList<KeyValueDescibeData>(dataName, result.size()); + + kvdd.setMultiSelect(true); + + int keyPos = -1; + int valPos = -1; + int parPos = -1; + + for (Result res: result) { + if (keyPos < 0 || valPos < 0 || parPos < 0) { + ResultDescriptor rd = res.getResultDescriptor(); + + keyPos = rd.getColumnIndex(keyid); + valPos = rd.getColumnIndex(valueid); + parPos = rd.getColumnIndex(SQL_KEY_PARAMETERID); + } + + kvdd.add(new ExtendedKeyValueData( + res.getString(keyPos), + res.getString(valPos), + getID(), + res.getString(parPos))); + } + + return kvdd; + } + + + /** + * This method create the user interface description for measurement and + * parameters as matrix. A row for each parameter, a column for each + * measurement. + */ + @Override + protected void appendToDynamicNode( + XMLUtils.ElementCreator artCreator, + XMLUtils.ElementCreator creator, + Document document, + Node dynamicNode, + CallMeta callMeta, + Object o + ) { + NamedArrayList all = (NamedArrayList) o; + String name = all.getName(); + RessourceFactory factory = RessourceFactory.getInstance(); + + Element matrixNode = creator.create("group"); + Element matrixLabel = creator.create("label"); + matrixLabel.setTextContent(factory.getRessource( + callMeta.getLanguages(), all.getName(), all.getName())); + creator.addAttr(matrixNode, "mode", "matrix"); + matrixNode.appendChild(matrixLabel); + + InputData inputParam = inputData.get("parameterid"); + ParameterMatrix matrix = new ParameterMatrix(all, inputParam.splitValue()); + + int measurements = matrix.measurementSize(); + int parameters = matrix.parameterSize(); + + for (int i = 0; i < parameters; i++) { + Element select = creator.create("select"); + String param = matrix.getParameter(i); + creator.addAttr(select, "label", inputParam.getDescription(param)); + creator.addAttr(select, "ref", name); + + for (int j = 0; j < measurements; j++) { + Element item = creator.create("item"); + Element label = creator.create("label"); + Element value = creator.create("value"); + + creator.addAttr(item, "ref", name); + creator.addAttr( + item, + "parameter", + matrix.getMDescription(j)); + + if (!matrix.isValid(j, i)) { + creator.addAttr(item, "disabled", "true"); + } + else { + creator.addAttr(item, "disabled", "false"); + } + + String tmpValue = matrix.getMeasurement(j) + ";" + param; + label.setTextContent(matrix.getMDescription(j)); + value.setTextContent(tmpValue); + + item.appendChild(label); + item.appendChild(value); + select.appendChild(item); + } + + matrixNode.appendChild(select); + } + + dynamicNode.appendChild(matrixNode); + } + + + /** + * This feed takes some input data storing measurement ids and parameter ids + * and put them into ExtendedInputData objects to save the relation between + * a measurement and the parameter it belongs to. + */ + @Override + public Document feed( + CallContext context, + Collection<InputData> input, + String uuid) + throws StateException + { + RessourceFactory resFactory = RessourceFactory.getInstance(); + Locale[] serverLocales = resFactory.getLocales(); + Locale locale = context.getMeta().getPreferredLocale( + serverLocales); + + if (input == null) { + String msg = resFactory.getRessource( + locale, + EXCEPTION_NO_INPUT, + EXCEPTION_NO_INPUT); + logger.warn(msg); + return feedFailure(msg); + } + + for(InputData item: input) { + String name = item.getName(); + InputValue inputValue = inputValues.get(name); + + String[] tupel = extractValuesAndParams(item.getValue()); + String type = inputValue.getType(); + + if (inputValue == null) { + String msg = resFactory.getRessource( + locale, + EXCEPTION_INVALID_INPUT, + EXCEPTION_INVALID_INPUT); + logger.warn(msg); + return feedFailure(msg); + } + + if (!InputValidator.isInputValid(tupel[0], type)) { + String msg = resFactory.getRessource( + locale, + EXCEPTION_INVALID_INPUT, + EXCEPTION_INVALID_INPUT); + logger.warn(msg); + return feedFailure(msg); + } + + if (inputData == null) { + inputData = new TreeMap<String, InputData>(); + } + + ExtendedInputData extended = new ExtendedInputData( + name, + tupel[0], + item.getObject(), + tupel[1]); + + if (name.equals(dataName)) { + String[] desc = getDescriptionForInputData( + extended, context, uuid); + extended.setDescription(desc); + } + + inputData.put(name, extended); + } + + return feedSuccess(); + } + + + /** + * Extract parameter ids and measurement ids from DefaultInputData objects + * and return an array. In the first position of this array, the measurement + * ids are placed, in the second position the parameter ids - all separated + * by a character. + * + * @param tmp String containing measurement ids and parameter ids. + * @return An array with separated measurements and parameters. + */ + protected String[] extractValuesAndParams(String tmp) { + String[] array = tmp.split(DefaultInputData.VALUE_SEPARATOR); + + String[] extracted = new String[2]; + for (String item: array) { + String[] tupel = item.split(ExtendedInputData.SEPARATOR); + + if (extracted[0] == null) { + extracted[0] = tupel[0]; + } + else { + extracted[0] += + DefaultInputData.VALUE_SEPARATOR + tupel[0]; + } + + if (extracted[1] == null) { + extracted[1] = tupel[1]; + } + else { + extracted[1] += DefaultInputData.VALUE_SEPARATOR + tupel[1]; + } + } + + logger.debug("VALUES RESULT: " + extracted[0]); + logger.debug("PARAMS RESULT: " + extracted[1]); + + return extracted; + } +} +// vim:set ts=4 sw=4 si et sta sts=4 fenc=utf8 :