I have read several dozen articles on the xs:Choice XSD element but cant wrap my head around how we are supposed to use the resulting class. Here is the XSD element and the class conversion from Xsd2Code++:
<xs:element name="VariantRoads">
<xs:complexType>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="Variant" minOccurs="0"/>
<xs:element ref="DepVariant"/>
<xs:element ref="ArrVariant"/>
</xs:choice>
</xs:complexType>
</xs:element>
[XmlArrayItemAttribute("ArrVariant", typeof(ArrVariantType), IsNullable = false)]
[XmlArrayItemAttribute("DepVariant", typeof(DepVariantType), IsNullable = false)]
[XmlArrayItemAttribute("Variant", typeof(VariantType), IsNullable = false)]
public object[] VariantRoads
{
get
{
return _variantRoads;
}
set
{
_variantRoads = value;
}
}
So that compiles and now I am ready to start populating my main class.
BaseRoadType brd = new BaseRoadType();
brd.VariantRoads = = new object[3]; // not sure how to initialize
brd.VariantRoads[0] = ??? // how do I assign my property
I am just really lost on how I should populate the VariantRoads class and then read it later and determine what choice was made.
The XmlArrayItemAttribute attributes at the top of the public object[] VariantRoads declaration gives you type hints that are acceptable element values of the array.
An xs:choice is meant to model just one of multiple possibilities - but there's also the maxOccurs="unbounded" attribute set on the choice definition, which turns the type declaration to an object array object[].
The choice definition reads in plain English as basically 'zero or many choices of ("ArrVariant", "DepVariant", "Variant") elements'
So this is acceptable:
BaseRoadType brd = new BaseRoadType();
brd.VariantRoads = new object[1] {
new ArrVariant()
};
Andt this is too:
brd.VariantRoads = new object[3] {
new Variant(), new ArrVariant(), new DepVariant(),
};
And also multiple instances of the same type:
brd.VariantRoads = new object[2] {
new ArrVariant(), new ArrVariant(),
};
Because each element in the array represents your 'choice' of the possible 3, the maxOccurs="unbounded" also means you can have more than one choice (hence the array).
To take it further, if the choice definition didn't have the maxOccurs="unbounded", the generated code would probably look like this:
[XmlArrayItemAttribute("ArrVariant", typeof(ArrVariantType), IsNullable = false)]
[XmlArrayItemAttribute("DepVariant", typeof(DepVariantType), IsNullable = false)]
[XmlArrayItemAttribute("Variant", typeof(VariantType), IsNullable = false)]
public object VariantRoad { get; set; }
Meaning you could only have one choice.
Related
Hope you are fine.
Can you please help me to resolve my below problem. I have an xml element with attribute named as “value” which can have one value E.g. (1) below , but there can be another case which i can have it as a child element named as “value” with multiple values E.g. (2) below.
E.g. 1
<variable id="123" value="Adam"/>
E.g. 2
<variable id="123">
<value>Adam</value>
<value>Philip</value>
... ...
</variable>
Can you please tell me how would i map this in Xstream serializer in same java class?
if i configure as below it gives me duplicate error
#XStreamAlias(“variable”)
public class Variable {
#XStreamAsAttribute
private String id;
#XStreamAsAttribute
private String value;
#XStreamImplicit
private List<String> value = new ArrayList<String>();
I'm struggling with a mapping in Dozer. The basic structure of my classes is this:
class Foo {
private String someString;
public String getSomeString() {
return someString;
}
public void setSomeString(String someString) {
this.someString = someString;
}
}
and the interesting part:
class Bar {
// note that no field is declared
public String[0] getSomeBarString() {
// This returns an array where the acctually desired string is a index 0
}
public void setSomeBarString(String someString) {
// stores the string otherwise
}
}
Compensating the absence of a field and the differently named getter/setter methods was quite easy:
<mapping>
<class-a>Foo</class-a>
<class-b>Bar</class-b>
<field>
<a>someString</a>
<b get-method="getSomeBarString" set-method="setSomeBarString">someBarString</b>
</field>
</mapping>
From my understanding I could even omitt get-method and set-method as there is no field access by default.
My problem is that the getter is indexed and the setter isn't. I've already read about indexed property mapping but it does it both ways. Is there a way to make only one direction indexed? E.g. would get-method="getSomeBarString[0]" work?
After a night of sleep I got an idea myself. I just define two one way mappings and make one of them indexed. It also turns out indexing is defined the same way (after the property name) even if you declare a different get-method or set-method.
<mapping type="one-way">
<class-a>Foo</class-a>
<class-b>Bar</class-b>
<field>
<a>someString</a>
<b set-method="setSomeBarString">someBarString</b>
</field>
</mapping>
<mapping type="one-way">
<class-a>Bar</class-a>
<class-b>Foo</class-b>
<field>
<a get-method="getSomeBarString">someBarString[0]</a>
<b>someString</b>
</field>
</mapping>
I am creating a portable MockGeoLocationWatcher that one can substitute in place of the concrete implementations of IMvxGeoLocationWatcher until one has an actual device. This should facilitate development and testing of applications that require geo location.
The PluginLoader class for this plugin currently looks like this:
namespace Pidac.MvvmCross.Plugins.Location
{
public class PluginLoader : IMvxConfigurablePluginLoader
{
private bool _loaded;
public static readonly PluginLoader Instance = new PluginLoader();
public void EnsureLoaded()
{
if (_loaded)
return;
_loaded = true;
var locationWatcher = new MockGeoLocationWatcher();
var data = #"<?xml version='1.0' encoding='utf-8'?>
<WindowsPhoneEmulator xmlns='http://schemas.microsoft.com/WindowsPhoneEmulator/2009/08/SensorData'>
<SensorData>
<Header version='1' />
<GpsData latitude='48.619934106826' longitude='-84.5247359841114' />
<GpsData latitude='48.6852544862377' longitude='-83.9864059059864' />
<GpsData latitude='48.8445703681025' longitude='-83.7337203591114' />
<GpsData latitude='48.8662561090809' longitude='-83.2393355934864' />
<GpsData latitude='49.0825970371386' longitude='-83.0415816872364' />
<GpsData latitude='49.2621642999055' longitude='-82.7229781716114' />
<GpsData latitude='49.2621642999055' longitude='-82.6021285622364' />
<GpsData latitude='49.2047736379815' longitude='-82.3054977028614' />
</SensorData>
</WindowsPhoneEmulator>";
locationWatcher.SensorLocationData = data;
Mvx.RegisterSingleton(typeof(IMvxGeoLocationWatcher), locationWatcher);
}
public void Configure(IMvxPluginConfiguration configuration)
{
}
}
public class MockLocationWatcherConfiguration : IMvxPluginConfiguration
{
public static readonly MockLocationWatcherConfiguration Default = new MockLocationWatcherConfiguration();
// ideally, we should use this property to point to a file or string containing location data
// this should be configurable outside of code base.
public string SensorLocationData { get; set; }
}
}
I will like to pass the sensor data, currently hardcoded into the variable called "data" through an instance of MockLocationWatcherConfiguration but do not know where the MvvmCross framework is expecting to load the configuration for this plugin before IMvxConfigurablePluginLoader.Configure(configuration) is invoked. Ideally, I should specify this through configuration.
I looked at the Json plugin's implementation of PluginLoaded but still could not figure out where the configuration was retrieved before a cast was attempted in IMvxConfigurablePluginLoader.Configure.
Any ideas or pointers will be greatly appreciated.
TIA.
This is covered in the draft wiki page https://github.com/slodge/MvvmCross/wiki/MvvmCross-plugins - see "writing a configurable plugin"
I've written the following Apex class as a part of a suite of custom webservices. All have the same problem but this one is the easiest example; if I can solve it for this, I can solve it for the other webservices.
global class WebServiceA4S {
global class returngetEnquiries {
public String status {get;set;}
public String error {get;set;}
public List<Enquiry__c> results {get;set;}
}
Webservice static returngetEnquiries getEnquiries() {
returngetEnquiries rtnError = new returngetEnquiries();
rtnError.status='success';
rtnError.error = '';
rtnError.results = new List<Enquiry__c>();
// id en name
try {
list<Enquiry__c> tmp = [Select id,name From Enquiry__c];
rtnError.results = tmp;
}
catch(Exception e) {
rtnError.status='error';
rtnError.error = String.valueof(e);
}
return rtnError;
}
}
Now if I debug the rtnError returned, just before the 'return rtnError', it does show a list of Enquiries so the code works.
The problem is that if I call the Webservice (via PHP or SOAPUI) the result is empty.
I use the wsdl from the class, created by salesforce of course.
I also looked at the wsdl and it looks like this:
...
<xsd:complexType name="returngetEnquiries">
<xsd:sequence/>
</xsd:complexType>
<xsd:element name="getEnquiries">
<xsd:complexType>
<xsd:sequence/>
</xsd:complexType>
</xsd:element>
<xsd:element name="getEnquiriesResponse">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="result" type="tns:returngetEnquiries" nillable="true"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
...
It looks like the returngetEnquiries is not defined. I tried to edit it and add the fields as defined in the class, but that doesn't help.
After some investigating I found the solution. It is in the returnclass. The parameters should be webservice instead of public:
global class returngetEnquiries {
webservice String status {get;set;}
webservice String error {get;set;}
webservice List<Enquiry__c> results {get;set;}
}
I have following UI part on JSF - it's simple search form with input field and submit:
<h:form>
<h:commandButton action="#{operation.found}" value="#{msg.search}" />
<h:inputText name="searchParam"/>
</h:form>
And correspondingly, on backend, i attempt to get value of input field next way:
public List<Store> getFound() {
String name = (String) FacesContext.getCurrentInstance()
.getExternalContext().getRequestParameterMap().get(
"searchParam");
SessionFactory sessionFactory = new Configuration().configure()
.buildSessionFactory();
HibernateTemplate hbt = new HibernateTemplate();
hbt.setSessionFactory(sessionFactory);
foundStores = hbt.find(BEAN_PATH + " WHERE name = ?",
new Object[] { name });
return foundStores;
}
And null name is passed to backend.
It seems that problem in .jsf part, but from first glance looks ok...
You must point the <h:inputText> to a managed-bean property:
<h:inputText name="searchParam" value="#{searchBean.searchParam}" />
and define in your bean:
private String searchParam;
public String getSearchParam() {..}
public void setSearchParam(String searchParam) {..}
and then use the searchParam in your getFound() method;
Of course, you need to have the bean defined as managed bean, but I assume you have done it:
<managed-bean>
<managed-bean-name>searchBean</managed-bean-name>
<managed-bean-class>mypackage.SearchBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
You can check a JSF tutorial (like this, for example)