Reputation: 591
I'm trying to upgrade the code quality of a part of my app which can display data within dynamic Form
that are configured via an XML string translated into an object. Until now, I was doing parsing and serializing with custom methods only, nearly writing each line of XML myself. That's obviously the wrong approach and I fully understand it now that I'm very familiar with Codename One.
So I rewrote my objects to use the PropertyBusinessObject
interface and here are the resulting classes :
public class CForm implements PropertyBusinessObject
{
Property<String, CForm> type = new Property<>("type");
Property<String, CForm> label = new Property<>("label");
IntProperty<CForm> currentStep = new IntProperty<>("currentstep");
IntProperty<CForm> maxsteps = new IntProperty<>("maxsteps");
ListProperty<CFormField, CForm> fields = new ListProperty<>("fields", CFormField.class);
ListProperty<CFormStep, CForm> steps = new ListProperty<>("steps", CFormStep.class);
public CForm()
{
}
PropertyIndex index;
@Override
public PropertyIndex getPropertyIndex()
{
if(index == null)
index = new PropertyIndex(this, "CForm",
new PropertyBase[] {type, label, currentStep, maxsteps, fields, steps});
return index;
}
}
This class is the main one, describing the general structure of the process. Type and label are used internally to identify the model used and the job to do at the customer place. Fields are the dynamic fields that will be shown at each step, these are global fields, like remarks or so. The steps are the differents dynamic Form
s that will be shown to the user. maxSteps
and currentStep
are used to know where the user is in the process.
public class CFormStep implements PropertyBusinessObject
{
Property<String, CFormStep> name = new Property<String, CFormStep>("name");
Property<String, CFormStep> label = new Property<String, CFormStep>("label");
IntProperty<CFormStep> value = new IntProperty<CFormStep>("value");
ListProperty<CFormField, CFormStep> fields = new ListProperty<>("fields", CFormField.class);
public CFormStep() {}
PropertyIndex index;
@Override
public PropertyIndex getPropertyIndex()
{
if(index == null)
index = new PropertyIndex(this, "CFormStep",
new PropertyBase[] { label, name, value, fields});
return index;
}
}
Each step is described with an unique name, a label used as the title of the dynamic form and a value to order the steps within the CForm
. Like it's CForm
parent, it has a set of fields.
public class CFormField implements PropertyBusinessObject
{
Property<String, CFormField> label = new Property<String, CFormField>("label");
Property<String, CFormField> name = new Property<String, CFormField>("name");
Property<String, CFormField> type = new Property<String, CFormField>("type");
Property<String, CFormField> value = new Property<String, CFormField>("value");
Property<String, CFormField> parent = new Property<String, CFormField>("parent");
public CFormField() {}
PropertyIndex index;
@Override
public PropertyIndex getPropertyIndex()
{
if(index == null)
index = new PropertyIndex(this, "CFormField",
new Property[] { label, name, type, value, parent });
return index;
}
}
The fields are composed of a label, an unique name, a type used to define which component will be used to render it, the value selected by the user formatted as a String and finally it's optionnal parent name.
The old implementation was fonctionnal but laggy and hard to evolve, which is why I came to write this new one.
But I'm stuck with one problem : I already rewroted the PropertyIndex.fromXML(Element e)
since it was creating NPE's when calling
public void fromXml(Element e) {
Hashtable atts = e.getAttributes();
for(Object a : atts.keySet()) { <--- NPE there if no attributes
and was not supporting ListProperties
.
Reading my CForm
from XML works fine but when I try to serialize it back to XML I just got a <CForm><CForm/>
and don't fully understand how the PropertyXMLElement
works... I've already debugged the process and the PropertyBusinessObject
is not empty at all. Any idea on how to fill the XML with those values ?
Here is an example of XML used :
<CForm>
<type>delivery-install</type>
<label>Intervention Test</label>
<currentstep/>
<maxsteps>3</maxsteps>
<fields>
<CFormField>
<label>Remarques</label>
<name>globalTEXTAREA6</name>
<type>TEXTAREA</type>
<value/>
</CFormField>
</fields>
<steps>
<CFormStep>
<name>step1</name>
<label>Arrivée sur place</label>
<value>1</value>
<fields>
<CFormField>
<label>Heure d'arrivée</label>
<name>step1TIME3</name>
<type>TIME</type>
<value/>
</CFormField>
</fields>
</CFormStep>
<CFormStep>
<name>step2</name>
<label>Sur place</label>
<value>2</value>
<fields>
<CFormField>
<label>Produits livrés / utilisés</label>
<name>step2PRODUCTTABLE7</name>
<type>PRODUCTTABLE</type>
<value/>
</CFormField>
</fields>
</CFormStep>
<CFormStep>
<name>step3</name>
<label>Départ</label>
<value>3</value>
<fields>
<CFormField>
<label>Heure de départ</label>
<name>step3TIME4</name>
<type>TIME</type>
<value/>
</CFormField>
<CFormField>
<label>Signature client</label>
<name>step3SIGN5</name>
<type>SIGN</type>
<value/>
</CFormField>
</fields>
</CFormStep>
</steps>
</CForm>
Upvotes: 1
Views: 39
Reputation: 52770
The XML support in property business object is still a work in progress which is why I didn't blog about it. I fixed the NPE issue and added support for list properties to fix the two issues raised. Notice I only did this for reading so there might be issues writing these objects as we didn't have time to do QA on this feature.
Upvotes: 1