view gnv-artifacts/src/main/java/de/intevation/gnv/transition/TransitionBase.java @ 319:251f16a083f8

Added RegionFilter-Support to HorizontalProfile InstantaneousPoint gnv-artifacts/trunk@378 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author Tim Englich <tim.englich@intevation.de>
date Fri, 27 Nov 2009 13:00:00 +0000
parents ce408af0ee57
children 3eff9241ea1e
line wrap: on
line source
/**
 *
 */
package de.intevation.gnv.transition;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.artifacts.CallMeta;
import de.intevation.gnv.artifacts.GNVArtifactBase;
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.transition.describedata.DefaultKeyValueDescribeData;
import de.intevation.gnv.transition.describedata.KeyValueDescibeData;
import de.intevation.gnv.transition.describedata.MinMaxDescribeData;
import de.intevation.gnv.transition.describedata.NamedArrayList;
import de.intevation.gnv.transition.describedata.NamedCollection;
import de.intevation.gnv.transition.describedata.SingleValueDescribeData;
import de.intevation.gnv.transition.exception.TransitionException;
import de.intevation.gnv.utils.ArtifactXMLUtilities;
import de.intevation.gnv.utils.InputValidator;

/**
 * @author Tim Englich <tim.englich@intevation.de>
 * 
 */
public abstract class TransitionBase implements Transition {

    /**
     * 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(GNVArtifactBase.class);
    
    private final static String MINVALUEFIELDNAME = "minvalue";
    private final static String MAXVALUEFIELDNAME = "maxvalue";
    
    private final static String NODATASELECTIONKEY = "n/n";
    
    private final static String DESCRIBEDATAKEY = "_DESCRIBEDATA";

    private String id = null;

    private String description = null;

    protected String dataName = null;

    protected boolean dataMultiSelect = false;
    
    protected boolean dataNoSelect = false;

    protected String queryID = null;

    private Collection<String> reachableTransitions = null;
    
    private Transition alternativeTransition = null;

    protected Collection<String> inputValueNames = null;

    private Map<String, InputValue> inputValues = null;

    private Transition parent = null;

    protected Map<String, InputData> inputData = null;
    

    /**
     * Constructor
     */
    public TransitionBase() {
        super();
    }

    /**
     * @see de.intevation.gnv.transition.Transition#getID()
     */
    public String getID() {
        return this.id;
    }

    /**
     * @see de.intevation.gnv.transition.Transition#getDescription()
     */
    public String getDescription() {
        return this.description;
    }

    /**
     * @see de.intevation.gnv.transition.Transition#reachableTransitions()
     */
    public Collection<String> reachableTransitions() {
        
        if (this.couldAlternativeTransitionUsed()){
            return this.alternativeTransition.reachableTransitions();
        }else{
            return this.reachableTransitions;
        }
        
    }

    /**
     * @return
     */
    private boolean couldAlternativeTransitionUsed() {
     // TODO das muss hier noch etwas freier gestaltet werden.
        Object[] inputValues = this.inputValueNames.toArray();
        String key = (String)inputValues[inputValues.length-1];
        boolean returnValue= this.alternativeTransition != null && 
                            this.inputData != null &&
                            this.inputData.containsKey(key) && 
                            this.inputData.get(key).getValue().
                                                    equals(NODATASELECTIONKEY);
        return returnValue;
    }

    /**
     * @see de.intevation.gnv.transition.Transition#getRequiredInputValues()
     */
    public Collection<InputValue> getRequiredInputValues() {
        return this.inputValues.values();
    }

    /**
     * @see de.intevation.gnv.transition.Transition#setup(org.w3c.dom.Node)
     */
    public void setup(Node configuration) {
        log.debug("TransitionBase.setup");
        this.id = ((Element)configuration).getAttribute("id");
        this.description = ((Element)configuration).getAttribute("description");

        log.info("Transition-ID = " + this.id);
        NodeList nodes = Config.getNodeSetXPath(configuration,
                "reachableTransitions/transition");
        this.reachableTransitions = new ArrayList<String>(nodes.getLength());
        for (int i = 0; i < nodes.getLength(); i++) {
            String reachableTransition = nodes.item(i).getTextContent();
            log.info("ReachableTransition ==> " + reachableTransition);
            this.reachableTransitions.add(reachableTransition);

        }
        
        Node alternativeTransitionNode = Config.getNodeXPath(configuration,
                                                     "alternativeTransition/transition");
        if (alternativeTransitionNode != null){
            this.alternativeTransition = TransitionFactory.getInstance()
                                        .createTransition(alternativeTransitionNode);
        }
        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);
            log.debug(inputValue.toString());
            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);
        }
        
    }

    /**
     * @see de.intevation.gnv.transition.Transition#getParent()
     */
    public Transition getParent() {
        return this.parent;
    }

    /**
     * @see de.intevation.gnv.transition.Transition#setParent(de.intevation.gnv.transition.Transition)
     */
    public void setParent(Transition transition) {
        this.parent = transition;
    }

    /**
     * @see de.intevation.gnv.transition.Transition#putInputData(java.util.Collection)
     */
    public void putInputData(Collection<InputData> inputData, String uuid)
                                                                          throws TransitionException {
        log.debug("TransitionBase.putInputData");
        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 HashMap<String, InputData>(
                                inputData.size());
                    }
                    
                    boolean valid = iv.isInputValid(tmpItem.getValue(),
                            inputValue.getType());
                    if (valid) {
                        if (tmpItem.getName().equals(MINVALUEFIELDNAME)){
                            String minValue = tmpItem.getValue();
                            String maxValue = this.getInputValue4ID(inputData, MAXVALUEFIELDNAME);
                            valid = iv.isInputValid(maxValue,inputValue.getType());
                            if (!valid){
                                String errMsg = "Wrong input for " + tmpItem.getValue()
                                                + " is not an " + inputValue.getType()
                                                + " Value.";
                                log.warn(errMsg);
                                throw new TransitionException(errMsg);
                            }
                            
                            valid = iv.isInputValid(minValue, 
                                    maxValue,
                                    inputValue.getType());
                            if (!valid){
                                String errMsg = "MaxValue-Input is less than MinValue-Input ";
                                log.warn(errMsg);
                                throw new TransitionException(errMsg);
                            }
                        }else if (tmpItem.getName().equals(MAXVALUEFIELDNAME)){
                            String minValue = this.getInputValue4ID(inputData, MINVALUEFIELDNAME);
                            String maxValue = tmpItem.getValue();
                            valid = iv.isInputValid(minValue,inputValue.getType());
                            if (!valid){
                                String errMsg = "Wrong input for " + tmpItem.getValue()
                                                + " is not an " + inputValue.getType()
                                                + " Value.";
                                log.warn(errMsg);
                                throw new TransitionException(errMsg);
                            }
                            
                            valid = iv.isInputValid(minValue, 
                                                    maxValue,
                                                    inputValue.getType());
                            if (!valid){
                                String errMsg = "MaxValue-Input is less than MinValue-Input ";
                                log.warn(errMsg);
                                throw new TransitionException(errMsg);
                            }
                        }
                        this.setSelection(tmpItem, uuid);
                        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 TransitionException(errMsg);
                    }

                } else {
                    String errMsg = "No Inputvalue given for Inputdata "
                                    + tmpItem.getName();
                    log.warn(errMsg + "Value will be ignored");

                }
            }
        } else {
            log.warn("No Inputdata given");
        }
    }
    
    private 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;
    }

    private void setSelection(InputData inputData, String uuid) {
        log.debug("TransitionBase.setSelection");

        Object o = this.getDescribeData(inputData.getName(),uuid);
        if (o != null) {
            if (o instanceof Collection<?>) {
                Collection<KeyValueDescibeData> values = (Collection<KeyValueDescibeData>) o;

                String value = inputData.getValue();
                String[] selectedValues = value.split(",");
                Set<String> selectedItems = new HashSet<String>(
                        selectedValues.length);
                for (int i = 0; i < selectedValues.length; i++) {
                    selectedItems.add(selectedValues[i].trim());
                }
                // Selektion umsetzen
                Iterator<KeyValueDescibeData> it = values.iterator();
                while (it.hasNext()) {
                    KeyValueDescibeData data = it.next();
                    String key = "" + data.getKey();
                    boolean selected = selectedItems.contains(key);
                    data.setSelected(selected);
                }
            } else if (o instanceof MinMaxDescribeData) {
                MinMaxDescribeData data = (MinMaxDescribeData) o;
                if (inputData.getName().equals(MINVALUEFIELDNAME)) {
                    data.setMinValue(inputData.getValue());
                }
                if (inputData.getName().equals(MAXVALUEFIELDNAME)) {
                    data.setMaxValue(inputData.getValue());
                }
            } else if (o instanceof SingleValueDescribeData) {
                ((SingleValueDescribeData)o).setValue(inputData.getValue());
            }
        }
    }

    private Object getDescribeData(String name, String uuid) {
        log.debug("TransitionBase.getDescribeData");
        Collection<Object> descibeData = this.getDescibeData(uuid);
        if (descibeData != null) {
            Iterator<Object> it = descibeData.iterator();
            while (it.hasNext()) {
                Object o = it.next();
                if (o instanceof NamedCollection<?>) {
                    if (name.equals(((NamedCollection<?>) o).getName())) {
                        return o;
                    }
                } else if (o instanceof MinMaxDescribeData) {
                    if (name.equals(((MinMaxDescribeData) o).getMinName())) {
                        return o;
                    }
                    if (name.equals(((MinMaxDescribeData) o).getMaxName())) {
                        return o;
                    }
                }else if (o instanceof SingleValueDescribeData) {
                    if (name.equals(((SingleValueDescribeData)o).getName())){
                        return o;
                    }
                }
            }
        }
        return null;

    }

    /**
     * @see de.intevation.gnv.transition.Transition#isTransitionReachable(java.lang.String)
     */
    public boolean isTransitionReachable(String transitionID) {
        log.debug("TransitionBase.isTransitionReachable");
        boolean returnValue = false;
        if (this.couldAlternativeTransitionUsed()){
            return alternativeTransition.isTransitionReachable(transitionID);
        }else{
            Iterator<String> transitions = reachableTransitions.iterator();
            while (transitions.hasNext()) {
                if (transitions.next().equals(transitionID)) {
                    log.debug("Transition " + transitionID + " wird unterst�tzt.");
                    returnValue = true;
                    break;
                }
            }
        }
        return returnValue;
    }

    /**
     * @see de.intevation.gnv.transition.Transition#advance(java.lang.String,
     *      de.intevation.artifacts.CallMeta)
     */
    public void advance(String uuid, CallMeta callMeta)
                                                       throws TransitionException {
        log.debug("TransitionBase.advance");
        
        if (this.couldAlternativeTransitionUsed()){
            this.alternativeTransition.setParent(this.getParent());
            this.alternativeTransition.putInputData(this.inputData != null ? 
                                                    this.inputData.values() : 
                                                    null,uuid);
            this.alternativeTransition.advance(uuid, callMeta);
        }else{
            try {
                String[] filterValues = this.generateFilterValuesFromInputData();
                Collection<Result> result = null;
                try {
                    if (this.queryID != null) {
                        QueryExecutor queryExecutor = QueryExecutorFactory
                                .getInstance().getQueryExecutor();
                        result = queryExecutor.executeQuery(this.queryID,
                                filterValues);
                    }
                    this.purifyResult(result, uuid);
                } catch (RuntimeException e) {
                    log.error(e, e);
                }
            } catch (QueryException e) {
                log.error(e, e);
                throw new TransitionException(e);
            }
        }
    }

    /**
     * @return
     */
    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")){
                    requestValue = this
                    .prepareInputData4RegionDBQuery(requestValue);
                }
                for (int j = 0; j < size; j++) {
                    list.add(requestValue);
                }
            }
        }
        String[] filterValues = list.toArray(new String[0]);
        return filterValues;
    }
    
    protected String prepareInputData4RegionDBQuery(String value){
        return value;
    }

    private String prepareInputData4DateDBQuery(String value) {
        log.debug("TransitionBase.prepareInputData4DateDBQuery");
        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) {
        log.debug("TransitionBase.prepareInputData4DBQuery");
        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;

    }

    /**
     * @param result
     */
    protected void purifyResult(Collection<Result> result, String uuid) {
        log.debug("TransitionBase.purifyResult");
        Collection<Object> describeData = this.getDescibeData(uuid);
        if (describeData == null) {
            describeData = new ArrayList<Object>();
        }
        NamedCollection<KeyValueDescibeData> keyValueDescibeData = extractKVP(result, "KEY", "VALUE");
        describeData.add(keyValueDescibeData); 
        this.setDescibeData(uuid, describeData);
    }

    /**
     * @param result
     * @return
     */
    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"));
        }
        boolean initialized = false;
        int keyPos= 0;
        int valuePos = 1;
        String previousKey = null;
        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: HACK da die ARCSDE kein DISTINCT auf r�umlichen Anfragen unterst�tzt.
            if (previousKey == null || !tmpKey.equals(previousKey)){
                previousKey = tmpKey;
                keyValueDescibeData.add(new DefaultKeyValueDescribeData(tmpKey, resultValue.getString(valuePos)));
            }
        }
        return keyValueDescibeData;
    }

    /**
     * @see de.intevation.gnv.transition.Transition#describe(org.w3c.dom.Document,
     *      org.w3c.dom.Node, de.intevation.artifacts.CallMeta,
     *      java.lang.String)
     */
    public void describe(Document document, Node rootNode, CallMeta callMeta,String uuid) {
        log.debug("TransitionBase.describe");
        Collection<Object> descibeData = this.getDescibeData(uuid);
        if (descibeData != null) {
            ArtifactXMLUtilities xmlutilities = new ArtifactXMLUtilities();
            Iterator<Object> it = descibeData.iterator();
            Node staticNode = xmlutilities.createArtifactElement(document,
                    "static");
            Node dynamic = xmlutilities.createArtifactElement(document,
                    "dynamic");
            rootNode.appendChild(staticNode);
            rootNode.appendChild(dynamic);
            while (it.hasNext()) {

                Object o = it.next();
                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 = xmlutilities.createXFormElement(
                            document, multiselect ? "select" : "select1");
                    selectNode.setAttribute("ref", name);

                    Element lableNode = xmlutilities.createXFormElement(
                            document, "label");
                    lableNode.setTextContent(RessourceFactory.getInstance()
                            .getRessource(callMeta.getLanguages(), name, name));
                    Element choiceNode = xmlutilities.createXFormElement(
                            document, "choices");

                    Collection<KeyValueDescibeData> values = (Collection<KeyValueDescibeData>) o;
                    Iterator<KeyValueDescibeData> resultIt = values.iterator();
                    while (resultIt.hasNext()) {
                        KeyValueDescibeData result = resultIt.next();
                        Element itemNode = xmlutilities.createXFormElement(
                                document, "item");

                        if (result.isSelected()) {
                            itemNode.setAttribute("selected", "true");
                        }

                        Element choiceLableNode = xmlutilities
                                .createXFormElement(document, "label");
                        choiceLableNode.setTextContent(result.getValue());
                        itemNode.appendChild(choiceLableNode);

                        Element choicValueNode = xmlutilities
                                .createXFormElement(document, "value");
                        choicValueNode.setTextContent("" + result.getKey());
                        itemNode.appendChild(choicValueNode);
                        choiceNode.appendChild(itemNode);
                    }
                    selectNode.appendChild(lableNode);
                    selectNode.appendChild(choiceNode);

                    if (!it.hasNext()) {
                        dynamic.appendChild(selectNode);
                    } else {
                        staticNode.appendChild(selectNode);
                    }

                } else if (o instanceof MinMaxDescribeData) {
                    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 = xmlutilities.createXFormElement(
                            document, "group");
                    groupNode.setAttribute("ref", minMaxDescibeData.getName());
                    Element groupNodeLableNode = xmlutilities
                            .createXFormElement(document, "label");
                    groupNodeLableNode.setTextContent(RessourceFactory
                            .getInstance().getRessource(
                                    callMeta.getLanguages(),
                                    minMaxDescibeData.getName(),
                                    minMaxDescibeData.getName()));
                    groupNode.appendChild(groupNodeLableNode);

                    Element inputMinNode = xmlutilities.createXFormElement(
                            document, "input");
                    inputMinNode.setAttribute("ref", MINVALUEFIELDNAME);
                    Element inputMinLableNode = xmlutilities
                            .createXFormElement(document, "label");
                    inputMinLableNode.setTextContent(RessourceFactory
                            .getInstance().getRessource(
                                    callMeta.getLanguages(), MINVALUEFIELDNAME,
                                    MINVALUEFIELDNAME));
                    inputMinNode.appendChild(inputMinLableNode);

                    Element inputMinValueNode = xmlutilities
                            .createXFormElement(document, "value");
                    inputMinValueNode.setTextContent(min.toString());
                    inputMinNode.appendChild(inputMinValueNode);

                    Element inputMaxNode = xmlutilities.createXFormElement(
                            document, "input");
                    inputMaxNode.setAttribute("ref", MAXVALUEFIELDNAME);
                    Element inputMaxLableNode = xmlutilities
                            .createXFormElement(document, "label");
                    inputMaxLableNode.setTextContent(RessourceFactory
                            .getInstance().getRessource(
                                    callMeta.getLanguages(), MAXVALUEFIELDNAME,
                                    MAXVALUEFIELDNAME));
                    inputMaxNode.appendChild(inputMaxLableNode);

                    Element inputMaxValueNode = xmlutilities
                            .createXFormElement(document, "value");
                    inputMaxValueNode.setTextContent(max.toString());
                    inputMaxNode.appendChild(inputMaxValueNode);

                    groupNode.appendChild(inputMinNode);
                    groupNode.appendChild(inputMaxNode);
                    
                    if (!it.hasNext()) {
                        dynamic.appendChild(groupNode);
                    } else {
                        staticNode.appendChild(groupNode);
                    }
                } else if (o instanceof SingleValueDescribeData) {

                    SingleValueDescribeData svdb = (SingleValueDescribeData) o;
                    
                    Element groupNode = xmlutilities.createXFormElement(
                            document, "group");
                    groupNode.setAttribute("ref",  svdb.getName());
                    Element groupNodeLableNode = xmlutilities
                            .createXFormElement(document, "label");
                    groupNodeLableNode.setTextContent(RessourceFactory
                            .getInstance().getRessource(
                                    callMeta.getLanguages(),
                                    svdb.getName(),
                                    svdb.getName()));
                    groupNode.appendChild(groupNodeLableNode);

                    Element inputNode = xmlutilities.createXFormElement(
                            document, "input");
                    inputNode.setAttribute("ref", svdb.getName());

                    Element inputLableNode = xmlutilities.createXFormElement(
                            document, "label");
                    inputLableNode.setTextContent("");
                    inputNode.appendChild(inputLableNode);

                    Element inputValueNode = xmlutilities.createXFormElement(
                            document, "value");
                    inputValueNode.setTextContent(svdb.getValue());
                    inputNode.appendChild(inputValueNode);

                    groupNode.appendChild(inputNode);
                    if (!it.hasNext()) {
                        dynamic.appendChild(groupNode);
                    } else {
                        staticNode.appendChild(groupNode);
                    }
                }

            }
        }
    }

    /**
     * @see de.intevation.gnv.transition.Transition#getDescibeData()
     */
    protected Collection<Object> getDescibeData(String uuid) {
        if (CacheFactory.getInstance().isInitialized()) {
            String key = uuid + DESCRIBEDATAKEY;
            log.debug("Hash for Queryelements: " + key);
            net.sf.ehcache.Element value = CacheFactory.getInstance().getCache().get(key);
            if (value != null) {
                return (Collection<Object>) (value.getObjectValue());
            }
        }
        return null;
    }
    
    /**
     * @see de.intevation.gnv.transition.Transition#getDescibeData()
     */
    protected void setDescibeData(String uuid, Collection<Object> describeData) {
        
        if (CacheFactory.getInstance().isInitialized()) {
            String key = uuid + DESCRIBEDATAKEY;
            log.debug("Hash for Queryelements: " + key);
            CacheFactory.getInstance().getCache().put(new net.sf.ehcache.Element(key, describeData));
        }
    }

    /**
     * @see de.intevation.gnv.transition.Transition#getInputData()
     */
    public Collection<InputData> getInputData() throws TransitionException {
        if (this.couldAlternativeTransitionUsed()){
            return this.alternativeTransition.getInputData();
        }else{
            return this.inputData != null ? this.inputData.values() : null;
        }
    }
}

http://dive4elements.wald.intevation.org