Castor XML Mapping and java.util.Map - java

I've been using Castor these past couple of days to try to get a little serialization going between my Java program and XML in a readable way. Though it has a few faults, Castor's automatic xml generation via reflection is actually very functional. Unfortunately, one thing that seems to be fairly well left out of the examples is dealing with generics. It seems the reflection API does a wonderful job as it is, but as it is inadvertently grabbing a lot of redundant data just because methods start with get___(), I wanted to write my own mapping file to stave this off.
Firstly, it seems altogether fair that in the attributes to a "field" element, one should define "type". However, it does not specify what should be done if this type is abstract or simply an interface. What should I put as the type then?
Secondly, most "collection" type objects specified in Castor (List, Vector, Collection, Set, etc) only require 1 generic type, so specifying "type" as what's inside and "collection="true"" are enough. However, it does not specify what I should do in the case of a collection like a Map, where 2 types are necessary. How can I specify both the key type and value type?
Any help at all would be greatly appreciated!

For the second of my questions:
When specifying something with a Map or a Table, you need to redefine org.exolab.castor.mapping.MapItem within the bind-xml element within your field element. Example taken from here
<class name="some.example.Clazz">
<field name="a-map" get-method="getAMap" set-method="setAMap">
<bind-xml ...>
<class name="org.exolab.castor.mapping.MapItem">
<field name="key" type="java.lang.String">
<bind-xml name="id"/>
</field>
<field name="value" type="com.acme.Foo"/>
</class>
</bind-xml>
</field>
</class>
Also, omit the type attribute from the parent field element.

For my first question, the trick is to NOT specify the type in the field element and allow Castor to infer it by itself. If you have definitions for the classes that could appear there, then it will automatically use those. For example:
<class name="some.example.Clazz">
<!-- can contain condition1 or condition2 elements -->
<field name="condition" collection="arraylist" required="true">
<bind-xml name="condition" node="element" />
</field>
</class>
<class name="some.example.condition1">
<field name="oneField" >
<xml-bind name="fieldOne" />
</field>
</class>
<class name="some.example.condition2">
<field name="anotherField />
<xml-bind name="fieldTwo" />
</field>
</class>
The output of into XML by Castor would use condition1 and condition2 style XML into the "condition" field of Clazz while still referring to its proper instantiation type.

Related

finding node values DOM with in Java

How can I get the value of specific nodes in Java from XML.
I have structure like what you see bellow and I want to get the values of userFileds(2,N.A. for the first one and 1 for the last one(it is part of real xml data. the number of elements are more):
<element class="AufOrgKombination" hash="AOK_1414931143186_52">
<field name="layer">4</field><field name="name">Function </field>
<field name="description">des</field>
<userField hash="USERFIELD_1415779871581_0">2.0</userField>
<userField hash="USERFIELD_1415386348389_3">N.A.</userField>
</element>
<element class="AufOrgKombination" hash="AOK_1414931143186_23">
<field name="layer">4</field><field name="name">Function 2 </field>
<field name="description">des</field>
<userField hash="USERFIELD_1415779871581_0">1</userField>
</element>
You should consider not to use the XPath API, but a library that handles it for you (Disclosure: I'm affiliated with that project). You probably want to reflect the XML structure somehow to your object structure. There are some difficulties to overcome (Namespaces, default namespaces, type conversion, mapping to Java objects, ...).
One possible solution using the suggested library:
public class Demo {
public interface Projection {
interface Element {
#XBRead("./userField")
List<String> getUserFieldValues();
}
#XBRead("//element")
List<Projection.Element> getElements();
}
public static void main(final String[] args) throws IOException {
Projection projection = new XBProjector().io().url("resource://data.xml").read(Projection.class);
for (Projection.Element element : projection.getElements()) {
for (String userField : element.getUserFieldValues()) {
System.out.println(userField);
}
}
}
}
This program prints out:
2.0
N.A.
1
You can use the query language XPath. It was designed exactly for that purpose.
Java 7 comes with a bunch of classes for working with XPath. See documentation and examples here.
Note that your xml is not well formed because it does not have exactly one root element.
For the modified and well formed version of your xml document
<root>
<element class="AufOrgKombination" hash="AOK_1414931143186_52">
<field name="layer">4</field><field name="name">Function </field>
<field name="description">des</field>
<userField hash="USERFIELD_1415779871581_0">2.0</userField>
<userField hash="USERFIELD_1415386348389_3">N.A.</userField>
</element>
<element class="AufOrgKombination" hash="AOK_1414931143186_23">
<field name="layer">4</field><field name="name">Function 2 </field>
<field name="description">des</field>
<userField hash="USERFIELD_1415779871581_0">1</userField>
</element>
</root>
your XPath query would look like
/root/element/userField/text()
The result for the query (Testet with www.freeformatter.com/xpath-tester.html) looks like this:
Text='2.0'
Text='N.A.'
Text='1'
You can use the Java classes mentioned above to make that kind of queries.

Retrieving attribute values depending on the value of another attribute using xpath

I have the following xml doc:
<database>
<order>
<data>
<field name="time" value="10:10:10" />
</data>
<data>
<field name="product" value="product_type_1">
<field name="attributeA" value="Foo" />
<field name="attributeB" value="Bar" />
</field>
<field name="attributeC" value="Jeam" />
<field name="attributeD" value="Beam" />
<field name="attributeE" value="Deam" />
</data>
</order>
<order>
<data>
<field name="time" value="10:10:11" />
</data>
<data>
<field name="product" value="product_type_2">
<field name="attributeF" value="Bravo" />
<field name="attributeG" value="Echo" />
</field>
<field name="attributeC" value="Jeam2" />
<field name="attributeD" value="Beam2" />
<field name="attributeJ" value="Charlie" />
<field name="attributeK" value="Tango" />
<field name="attributeL" value="Zulu" />
</data>
</order>
It is a set of "order" elements but the "field" (both on quantity and type) depend on the value of the element whose name is "product". I am interested in extracting info depending on the value of the product. More specifically, I would end up with something like this table:
Time Product AttributeA AttributeB AttributeC AttributeD
10:10:10 product_type_1 Foo Bar Jeam Beam
10:10:11 product_type_2 Jeam2 Beam2
In other words I am trying to "cut" unesessary info depending on the value of child element of "order". I am trying to achive this by using xpath (in java) but I am stuck. It is impossible for me to emulate the "if" condition described above.
I am thinking of using and xpath query to retrieve one order element at a time, then query for the product type and then choose the apropriate xpath to retieve the coresponding attributes, but that sounds really inneficient and slow.
Is it possible to do it more efficiently? Is xpath not the right answer here?
Thanks in advance.
P.S: The alignment and organization of the data you see above doesn't really matter as long as I retrieve the correct data then I am sure I'll be able to print them somehow.
If you want to use XPath, you will need at least XPath 3.0 or XQuery (this code is valid in both of them). Have a look at XQuery engines if you want to use this in Java, for example Saxon, BaseX, eXist DB, ...
for $order in /database/order
return string-join((
$order//field[#name='time']/#value,
$order//field[#name='product']/#value,
($order//field[#name='attributeA']/#value, '')[1],
($order//field[#name='attributeB']/#value, '')[1],
($order//field[#name='attributeC']/#value, '')[1],
($order//field[#name='attributeD']/#value, '')[1]),
' ')
The pattern used for the attributes makes sure that empty values do not break the table layout (so for the second product type, attributes C and D do not get attributes A and B). is the tab character.
If you want to use Java for further processing the output, I'd go with this: Fetch all orders (/database/order) and loop over them. Then, for each order, use DOM (or XPath again) to fetch the nodes you need. Yet it seems that the question you asked is not your actual problem, it might be that using XQuery could lead to a cleaner solution.

Using Field value in a Parameter DefaultValueExpression

I have to use JasperReports but i'm struggling with getting the data out.
Here is my Java side declaration:
Map<String, List<TransactionBean>> shCredits = new HashMap<String, List<TransactionBean>>();
In the declared HashMap, I store clients, who have transactions.
I passed this HashMap to the report for listing the transactions group by clients.
Here is the JR side:
<parameter name="shareHolderCreditBeans" class="java.util.HashMap">
<defaultValueExpression><![CDATA[$P{REPORT_PARAMETERS_MAP}.get("shCreditBeans")]]></defaultValueExpression>
</parameter>
<parameter name="credits" class="java.util.List">
<defaultValueExpression><![CDATA[$P{shareHolderCreditBeans}.get("12")]]></defaultValueExpression>
</parameter>
...
<field name="clientId" class="java.lang.String">
<fieldDescription><![CDATA[clientId]]></fieldDescription>
</field>
My problem is that if I use hardcoded key ("12") in 'credits' parameter, i can get the client transaction list. I'm also able to use the clientId field in a textField, but not as a key like:
$P{shareHolderCreditBeans}.get($F{clientId})
If i do this it returns with null.
Is it the right way, using field as parameter key?
Please let me know if I am not clear enough about describing this issue
Finally, I could resolve it with casting:
<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource((java.util.List)($P{shareHolderCreditBeans}.get($F{clientId})))]]></dataSourceExpression>

Dozer: get first value on a collection mapped to single value in destination

I am mapping two DTO objects through Dozer mapper. I am interested in choosing one value from list and map it to a single field in the destination file.
Is it possible to use mapping like this:
<field>
<a>someList[0]</a>
<b>someVariable</b>
</field>
It seems that b part can have a list[1].value type of approach, but I cannot get it to work when brackets are on a side. Where am I making it wrong?
Actually, you don't need more than suggested
<field>
<a>someList[0]</a>
<b>someVariable</b>
</field>
structure to achieve this. I had the problem other where: I did not call the correct map() function for that mapping on my code. I had several mappings and the map() call to this specific one was missing.
Use the following mapping:
<mapping map-id="collectionMapping" type="one-way">
<class-a>java.util.Collection</class-a>
<class-b>java.util.Collection</class-b>
<field>
<a>this</a>
<b set-method="add(java.lang.Object)" type="iterate">anything</b>
<b-hint>your destination object type</b-hint>
</field>
</mapping>

how can i use subclasses in hibernate for attributes within a table?

I have the following domain objects
Loan {
int id;
Date attribute1;
}
LoanExtension {
Date attribute2;
}
I would like to keep my objects like this because sometimes I would like to change only the attributes in LoanExtension in my database (i.e. attribute1 in the loan object will be null in the object and i don't want this to get set in the database).
How is this possible using a hibernate mapping with xml? I have done the following
<class name="org.domain.borrowerReview.Loan" table="loan_profiles" >
<cache usage="read-only"/>
<id name="loanId" column="id">
<generator class="native"/>
</id>
<version name="attribute1" column="date_1/>
<subclass name="org.domain.borrowerReview.LoanExtension" extends="org.rangde.domain.borrowerReview.LoanProfilesUpdate">
<property name="attribute2" column="date_2" />
</subclass>
</class>
I'm getting this exception :
Discriminator is needed when 'single-table-per-hierarchy' is used and a class has subclasses
Short answer
You need to add a discriminator column and change the snippet to something like this.
<class name="org.domain.borrowerReview.Loan" table="loan_profiles" >
<cache usage="read-only"/>
<id name="loanId" column="id">
<generator class="native"/>
</id>
<version name="attribute1" column="date_1/>
<discriminator column="loan_profiles_type" type="string"/>
<subclass name="org.domain.borrowerReview.LoanExtension" extends="org.rangde.domain.borrowerReview.LoanProfilesUpdate">
<property name="attribute2" column="date_2" />
</subclass>
</class>
Long answer
First off, do remember that the inheritance in JPA is not an absolute parallel to regular inheritance.
One must evaluate how the design of classes will have an impact on the underlying schema.
You have not mentioned how you would like to have your table structure as.
Hibernate provides three mechanisms for inheritance.
table per class hierarchy
table per subclass
table per concrete class
See detaiils here
Your xml snippet suggests that you are using table per class hierarchy.
Now, if one has subclasses, there would be little use if the is just one subclass (though it is allowed). And under "table per class hierarchy" all the sub classes are placed in the same table.
To distinguish between which subclass a particular record belongs to, hibernate relies on discriminator column.
You need to define the same.
Refer the following documentation documentation.

Categories