Java tutorial
/* * Copyright (c) 2004-2012 The YAWL Foundation. All rights reserved. * The YAWL Foundation is a collaboration of individuals and * organisations who are committed to improving workflow technology. * * This file is part of YAWL. YAWL is free software: you can * redistribute it and/or modify it under the terms of the GNU Lesser * General Public License as published by the Free Software Foundation. * * YAWL is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General * Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with YAWL. If not, see <http://www.gnu.org/licenses/>. */ package org.yawlfoundation.yawl.resourcing.jsf.dynform; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.Namespace; import org.yawlfoundation.yawl.elements.YAttributeMap; import org.yawlfoundation.yawl.util.JDOMUtil; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Author: Michael Adams * Creation Date: 5/07/2008 */ public class DynFormFieldAssembler { private String _formName = ""; private Map<String, FormParameter> _params; // top level I/O params private FormParameter _currentParam; private List<DynFormField> _fieldList; private int _uniqueSuffix = 0; private DynFormFieldAssembler() { } public DynFormFieldAssembler(String schemaStr, String dataStr, Map<String, FormParameter> params) throws DynFormException { _params = params; buildMap(schemaStr, dataStr); } private void buildMap(String schemaStr, String dataStr) throws DynFormException { Element data = JDOMUtil.stringToElement(dataStr); Document doc = JDOMUtil.stringToDocument(schemaStr); Element root = doc.getRootElement(); // schema Namespace ns = root.getNamespace(); Element element = root.getChild("element", ns); _formName = element.getAttributeValue("name"); // name of case/task _fieldList = createFieldList(element, data, ns, -1); } private List<DynFormField> createFieldList(Element schema, Element data, Namespace ns, int level) throws DynFormException { List<DynFormField> fieldList = null; Element next; // increment nested depth level & get next contents ++level; if (schema.getName().equals("choice")) { fieldList = createChoice(schema, data, ns, level); } else { ns = schema.getNamespace(); Element complex = schema.getChild("complexType", ns); if (complex == null) { throw new DynFormException( "Malformed data schema, at element: " + JDOMUtil.elementToString(schema)); } next = complex.getChild("sequence", ns); if (next == null) next = complex.getChild("all", ns); if (next != null) { fieldList = createSequence(next, data, ns, level); } else { next = complex.getChild("choice", ns); if (next != null) { fieldList = createChoice(next, data, ns, level); } } } return fieldList; } private List<DynFormField> createSequence(Element sequence, Element data, Namespace ns, int level) throws DynFormException { List<DynFormField> fieldList = new ArrayList<DynFormField>(); for (Element eField : sequence.getChildren()) { List<DynFormField> result = createField(eField, data, ns, level); setOrderForListItems(result, fieldList.size()); fieldList.addAll(result); } return fieldList; } private List<DynFormField> createChoice(Element parent, Element data, Namespace ns, int level) throws DynFormException { List<DynFormField> fieldList = new ArrayList<DynFormField>(); List<DynFormField> result; String choiceID = getNextChoiceID(); for (Element eField : parent.getChildren()) { String eName = eField.getName(); if (eName.equals("sequence") || eName.equals("all")) { List<DynFormField> subList = createSequence(eField, data, ns, level + 1); DynFormField field = addField("choicePanel", subList, null, null, level); field.setGroupID(getNextGroupID()); fieldList.add(field); } else { result = createField(eField, data, ns, level); fieldList.addAll(result); } } for (DynFormField field : fieldList) { field.setChoiceID(choiceID); } return fieldList; } /** * * @param eField * @param data * @param ns * @param level * @return a list of 'DynFormField' */ private List<DynFormField> createField(Element eField, Element data, Namespace ns, int level) throws DynFormException { DynFormField field; List<DynFormField> result = new ArrayList<DynFormField>(); // get eField element's attributes String minOccurs = eField.getAttributeValue("minOccurs"); String maxOccurs = eField.getAttributeValue("maxOccurs"); String name = eField.getAttributeValue("name"); String type = getElementDataType(eField, ns); if (level == 0) _currentParam = _params.get(name); if (type == null) { // check for a simpleType definition Element simple = eField.getChild("simpleType", ns); if (simple != null) { field = addField(name, null, data, minOccurs, maxOccurs, level); applySimpleTypeFacets(simple, ns, field); result.add(field); } else { // check for empty complex type (flag defn) Element complex = eField.getChild("complexType", ns); if ((complex != null) && complex.getContentSize() == 0) { field = addField(name, null, data, minOccurs, maxOccurs, level); field.setEmptyComplexTypeFlag(true); if ((data != null) && (data.getChild(name) != null)) { field.setValue("true"); } result.add(field); } else { // new populated complex type - recurse in a new field list String groupID = getNextGroupID(); List<Element> dataList = (data != null) ? data.getChildren(name) : null; if ((dataList != null) && (!dataList.isEmpty())) { for (Element var : dataList) { field = addGroupField(name, eField, ns, var, minOccurs, maxOccurs, level); field.setGroupID(groupID); result.add(field); } } else { field = addGroupField(name, eField, ns, null, minOccurs, maxOccurs, level); field.setGroupID(groupID); result.add(field); } } } } else { // a plain element result.addAll(addElementField(name, type, data, minOccurs, maxOccurs, level)); } return result; } private String getElementDataType(Element eField, Namespace ns) { String type = eField.getAttributeValue("type"); if (type == null && eField.getChildren().isEmpty()) { type = ns.getPrefix() + ":string"; // default type for element } return type; } private DynFormField addGroupField(String name, Element eField, Namespace ns, Element data, String minOccurs, String maxOccurs, int level) throws DynFormException { DynFormField field; List<DynFormField> simpleContents = new ArrayList<DynFormField>(); int instances = getInitialInstanceCount(minOccurs, data, name); if (instances == 1) { field = addField(name, createFieldList(eField, data, ns, level), minOccurs, maxOccurs, level); } else { field = addContainingField(name, minOccurs, maxOccurs, level); String subGroupID = getNextGroupID(); for (int i = 0; i < instances; i++) { Element data4Inst = getIteratedContent(data, i, name); List<DynFormField> subFieldList = createFieldList(eField, data4Inst, ns, level); DynFormField subField = subFieldList.get(0); // the multi-inst field subField.setGroupID(subGroupID); field.addSubField(subField); simpleContents = addSimpleContents(simpleContents, subFieldList); } } field.setOccursCount(instances); field.addSubFieldList(simpleContents); return field; } private List<DynFormField> addElementField(String name, String type, Element data, String minOccurs, String maxOccurs, int level) { List<DynFormField> result = new ArrayList<DynFormField>(); DynFormField field; String groupID = null; boolean cloneable = isCloneableField(minOccurs, maxOccurs); if (cloneable) groupID = getNextGroupID(); int instances = getInitialInstanceCount(minOccurs, data, name); for (int i = 0; i < instances; i++) { Element data4Inst = (instances > 1) ? getIteratedContent(data, i, name) : data; field = addField(name, type, data4Inst, minOccurs, maxOccurs, level); field.setGroupID(groupID); field.setOccursCount(instances); result.add(field); } return result; } private DynFormField addField(String name, String type, Element data, String minOccurs, String maxOccurs, int level) { String value = (data != null) ? data.getChildText(name) : ""; DynFormField input = new DynFormField(name, type, value); populateField(input, name, minOccurs, maxOccurs, level); return input; } private DynFormField addField(String name, List<DynFormField> subFieldList, String minOccurs, String maxOccurs, int level) { if (name == null) name = "choice"; DynFormField input = new DynFormField(name, subFieldList); populateField(input, name, minOccurs, maxOccurs, level); return input; } private void populateField(DynFormField input, String name, String minOccurs, String maxOccurs, int level) { input.setMinoccurs(minOccurs); input.setMaxoccurs(maxOccurs); input.setParam(_currentParam); input.setLevel(level); DynFormUserAttributes attributes = new DynFormUserAttributes(); if (level == 0) { attributes.set(getAttributeMap(name)); } input.setAttributes(attributes); } private DynFormField addContainingField(String name, String minOccurs, String maxOccurs, int level) { if (name == null) name = "choice"; DynFormField input = new DynFormField(name, null); input.setMinoccurs(minOccurs); input.setMaxoccurs(maxOccurs); input.setParam(_currentParam); input.setLevel(level); return input; } private void applySimpleTypeFacets(Element simple, Namespace ns, DynFormField field) { Element restriction = simple.getChild("restriction", ns); if (restriction != null) { DynFormFieldRestriction restrict = new DynFormFieldRestriction(restriction, ns); field.setDatatype(restrict.getBaseType()); field.setRestriction(restrict); } Element union = simple.getChild("union", ns); if (union != null) { DynFormFieldUnion fieldUnion = new DynFormFieldUnion(union, ns); field.setDatatype(fieldUnion.getBaseType()); field.setUnion(fieldUnion); } Element list = simple.getChild("list", ns); if (list != null) { DynFormFieldListFacet fieldList = new DynFormFieldListFacet(list); field.setDatatype(fieldList.getItemType()); field.setListType(fieldList); } } private List<DynFormField> addSimpleContents(List<DynFormField> simpleContents, List<DynFormField> subFieldList) { if (subFieldList == null) return simpleContents; boolean contains = false; for (int i = 1; i < subFieldList.size(); i++) { DynFormField field = subFieldList.get(i); for (DynFormField simple : simpleContents) { contains = simple.equals(field); if (contains) break; } if (!contains) simpleContents.add(field); } return simpleContents; } private int getInitialInstanceCount(String min, Element data, String dataName) { int dataCount = 1; int minOccurs = Math.max(SubPanelController.convertOccurs(min), 1); if ((data != null) && (data.getContentSize() > 1)) { dataCount = data.getChildren(dataName).size(); } return Math.max(minOccurs, dataCount); } private Element getIteratedContent(Element data, int index, String name) { Element result = null; if ((data != null) && (index < data.getContentSize())) { List<Element> relevantChildren = data.getChildren(name); result = new Element(data.getName()); Element iteratedContent = relevantChildren.get(index); result.addContent(iteratedContent.clone()); } return result; } private void setOrderForListItems(List<DynFormField> list, int order) { for (DynFormField field : list) { field.setOrder(order++); } } private boolean isCloneableField(String minoccurs, String maxoccurs) { int min = SubPanelController.convertOccurs(minoccurs); int max = SubPanelController.convertOccurs(maxoccurs); return (max > 1) && (max > min); } private String getNextGroupID() { return "group" + _uniqueSuffix++; } private String getNextChoiceID() { return "choice" + _uniqueSuffix++; } private YAttributeMap getAttributeMap(String name) { YAttributeMap map = new YAttributeMap(); FormParameter param = _params.get(name); if (param != null) map.set(param.getAttributes()); return map; } public String getFormName() { return _formName; } public List<DynFormField> getFieldList() { return _fieldList; } }