From 254ee6f47eebfc00462c10756a92066e82cc1a96 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Tue, 21 Jun 2011 15:46:02 +0200 Subject: Initial commit --- .../gui/tabs/outcome/form/OutcomeStructure.java | 283 +++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100755 source/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java (limited to 'source/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java') diff --git a/source/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java b/source/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java new file mode 100755 index 0000000..9333bf8 --- /dev/null +++ b/source/com/c2kernel/gui/tabs/outcome/form/OutcomeStructure.java @@ -0,0 +1,283 @@ +package com.c2kernel.gui.tabs.outcome.form; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Iterator; + +import javax.swing.ImageIcon; +import javax.swing.JPanel; + +import org.exolab.castor.types.AnyNode; +import org.exolab.castor.xml.schema.Annotated; +import org.exolab.castor.xml.schema.Annotation; +import org.exolab.castor.xml.schema.ComplexType; +import org.exolab.castor.xml.schema.ContentModelGroup; +import org.exolab.castor.xml.schema.Documentation; +import org.exolab.castor.xml.schema.ElementDecl; +import org.exolab.castor.xml.schema.Group; +import org.exolab.castor.xml.schema.ModelGroup; +import org.exolab.castor.xml.schema.Order; +import org.exolab.castor.xml.schema.Particle; +import org.exolab.castor.xml.schema.SimpleType; +import org.exolab.castor.xml.schema.SimpleTypesFactory; +import org.exolab.castor.xml.schema.XMLType; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.c2kernel.gui.tabs.outcome.OutcomeException; +import com.c2kernel.utils.Language; +import com.c2kernel.utils.Logger; + +// contains child outcome elements - creates new ones +public abstract class OutcomeStructure extends JPanel { + + ElementDecl model; + Element myElement = null; + boolean readOnly; + HashMap subStructure = new HashMap(); + ArrayList order = new ArrayList(); + String help = ""+Language.translate("No help is available for this element")+""; + HelpPane helpPane; + boolean deferChild = false; + + public OutcomeStructure(ElementDecl model, boolean readOnly , HelpPane helpPane) { + this.model = model; + this.readOnly = readOnly; + this.helpPane = helpPane; + subStructure = new HashMap(); + Logger.msg(8, "Creating " + model.getName() + " structure as " + + this.getClass().getName().substring(this.getClass().getName().lastIndexOf('.') + 1)); + + String doc = extractHelp(model); + if (doc.length() > 0) help = doc; + } + + public boolean getReadOnly() { + return readOnly; + } + /** Contains the rules for deciding which OutcomeStructure will represent a chosen Element Declaration. + * In this order + *
    + *
  1. if maxOccurs>1 then Dimension + *
  2. SimpleTypes are Fields + *
  3. No element children is a Field + *
  4. Everything else is a DataRecord + *
+ */ + public OutcomeStructure createStructure(ElementDecl model, boolean readOnly, HelpPane help) throws OutcomeException { + XMLType elementType = model.getType(); + ComplexType elementComplexType; + + if (model.getMaxOccurs() == 0) return null; + + // if more than one can occur - dimension + if (model.getMaxOccurs() > 1 + || model.getMaxOccurs() == Particle.UNBOUNDED + || model.getMinOccurs() == 0) + return new Dimension(model, readOnly, help); + + // must have a type from now on + if (elementType == null) + throw new StructuralException("Element "+model.getName()+" is elementary yet has no type."); + // simple types will be fields + if (elementType instanceof SimpleType) return new Field(model, readOnly, help); + + // otherwise is a complex type + try { + elementComplexType = (ComplexType)elementType; + } + catch (ClassCastException e) { + throw new StructuralException("Unknown XMLType for element " + model.getName()); + } + + //when no element children - field + if (elementComplexType.getParticleCount() == 0) return new Field(model, readOnly, help); + + //everything else is a data record + return new DataRecord(model, readOnly, help, deferChild); + } + + /** Extracts child Element declarations from a content group and recursively from any group + * (not Element) of that group. calls createStructure() to find the corresponding OutcomeStructure + * then adds it to this structure. + */ + public void enumerateElements(ContentModelGroup group) throws OutcomeException { + + // process base types first if complex type + //HACK: castor does not include elements from basetype, so we do it manually. if they fix it, this will duplicate child elements. + if (group instanceof ComplexType) { + XMLType base = ((ComplexType)group).getBaseType(); + if (base instanceof ComplexType) + enumerateElements((ComplexType)base); + } + + for (Enumeration elements = group.enumerate(); elements.hasMoreElements(); ) { + Particle thisParticle = (Particle)elements.nextElement(); + if (thisParticle instanceof Group) { + Group thisGroup = (Group)thisParticle; + if (thisGroup instanceof ModelGroup) { + // HACK: Castor strangeness - model groups don't seem to resolve their own references. If fixed, this will still work + ModelGroup thisModel = (ModelGroup)thisGroup; + if (thisModel.hasReference()) thisGroup = thisModel.getReference(); + } + Order thisOrder = thisGroup.getOrder(); + if (thisOrder == Order.sequence || thisOrder == Order.all) enumerateElements(thisGroup); + else // we only support sequences in data structures such as these + throw new StructuralException("The '"+thisGroup.getOrder()+"' group is not supported"); + } + else if (thisParticle instanceof ElementDecl) { + ElementDecl thisElement = (ElementDecl)thisParticle; + addStructure(createStructure(thisElement, readOnly, helpPane)); + } + else throw new StructuralException("Particle " + thisParticle.getClass() + " not implemented"); + } + } + + /** Adds a generated OutcomeStructure as a child of this one. A separate structure as is often overridden. + */ + public void addStructure(OutcomeStructure newElement) throws OutcomeException { + if (newElement == null) return; + subStructure.put(newElement.getName(), newElement); + order.add(newElement.getName()); + } + + /** After schema processing, addInstance() propogates the XML instance document down the layout. + * Most OutcomeStructures will throw an exception if called more than once, except Dimension, which is the only + * Outcome Structure to support maxOccurs>1 + */ + public abstract void addInstance(Element myElement, Document parentDoc) throws OutcomeException; + + public Element getElement() { + return myElement; + } + + public String getName() { + if (model == null) return null; + return model.getName(); + } + + public ElementDecl getModel() { + return model; + } + + public String getHelp() { + return help; + } + + public String validateStructure() { + StringBuffer errors = new StringBuffer(); + for (Iterator iter = subStructure.values().iterator(); iter.hasNext();) { + OutcomeStructure element = (OutcomeStructure)iter.next(); + errors.append(element.validateStructure()); + } + return errors.toString(); + } + + public abstract Element initNew(Document parent); + + public static String extractHelp(Annotated model) { + Enumeration e = model.getAnnotations(); + StringBuffer doc = new StringBuffer(); + if (e.hasMoreElements()) { // look for HTML + Annotation note = (Annotation)e.nextElement(); + for (Enumeration g = note.getDocumentation(); g.hasMoreElements();) { + Documentation thisDoc = (Documentation)g.nextElement(); + for (Enumeration h = thisDoc.getObjects(); h.hasMoreElements();) { + AnyNode node = (AnyNode)h.nextElement(); + String line = node.toString(); + if (line.length() == 0) + line = node.getStringValue(); + if (line.length() > 0) { + doc.append(line).append("\n"); + } + } + } + } + + return doc.toString(); + } + + public abstract void grabFocus(); + + public static Class getJavaClass(int typeCode) { + switch (typeCode) { + + // boolean + case SimpleTypesFactory.BOOLEAN_TYPE: + return Boolean.class; + + // integers + case SimpleTypesFactory.INTEGER_TYPE: + case SimpleTypesFactory.NON_POSITIVE_INTEGER_TYPE: + case SimpleTypesFactory.NEGATIVE_INTEGER_TYPE: + case SimpleTypesFactory.NON_NEGATIVE_INTEGER_TYPE: + case SimpleTypesFactory.POSITIVE_INTEGER_TYPE: + case SimpleTypesFactory.INT_TYPE: + case SimpleTypesFactory.UNSIGNED_INT_TYPE: + case SimpleTypesFactory.SHORT_TYPE: + case SimpleTypesFactory.UNSIGNED_SHORT_TYPE: + case SimpleTypesFactory.LONG_TYPE: + case SimpleTypesFactory.UNSIGNED_LONG_TYPE: + case SimpleTypesFactory.BYTE_TYPE: + case SimpleTypesFactory.UNSIGNED_BYTE_TYPE: + return BigInteger.class; + // floats + case SimpleTypesFactory.FLOAT_TYPE: + case SimpleTypesFactory.DOUBLE_TYPE: + case SimpleTypesFactory.DECIMAL_TYPE: + return BigDecimal.class; + + // images + case SimpleTypesFactory.BASE64BINARY_TYPE: + case SimpleTypesFactory.HEXBINARY_TYPE: + return ImageIcon.class; + + // everything else is a string for now + default: + return String.class; + } + } + + public static Object getTypedValue(String value, Class type) { + try { + if (type.equals(Boolean.class)) + if (value == null || value.equals("")) + return Boolean.FALSE; + else + return Boolean.valueOf(value); + else if (type.equals(BigInteger.class)) + if (value == null || value.equals("")) + return new BigInteger("0"); + else + return new BigInteger(value); + else if (type.equals(BigDecimal.class)) + if (value == null || value.equals("")) + return new BigDecimal(0); + else + return new BigDecimal(value); + } catch (Exception ex) { + Logger.error("Cannot convert value '"+value+"' to a "+type.getName()); + } + return value==null?"":value; + } + + public static boolean isEmpty(Object value) { + if (value == null) return true; + + if (value instanceof String) { + if (((String)value).length() == 0) return true; + } + else if (value instanceof Boolean) { + if (((Boolean)value).booleanValue() == false) return true; + } + else if (value instanceof BigInteger) { + if (((BigInteger)value).intValue() == 0) return true; + } + else if (value instanceof BigDecimal) { + if (((BigDecimal)value).floatValue() == 0.0) return true; + } + return false; + } +} -- cgit v1.2.3