In my dozerBeanMapping.xml, wildcard is set to false.
I have an object A with a field named list which is a List.
I have an object B with a field named list which is a List.
My mapping is :
I have a A instance with 2 String in list field.
When i map A to B, the B.list field also contains 2 String ! To avoid this, i have to add wildcard="false" as a property for the current mapping ...
2/ Inheritance
Case 1 :
--------
Look at my class diagram : http://img6.imageshack.us/img6/6892/050824inheritance6sp.jpg
I have 2 mappings : one between SuperClass and ClassPrime, and one between SubClass and ClassPrime.
When i try to map a SubClass object fully loaded in a ClassPrime empty one, getSuperAttribute2() always gives me null.
Case 2 :
--------
Let's make a few changes : http://img208.imageshack.us/img208/1579/050824inheritance27aw.jpg
My mappings are now between SuperClass and SuperClassPrime, and between SubClass and SubClassPrime.
The previous mapping test gives me the same result :(
Mappings between B and BPrime, between B1 and BPrime1, and between B2 and BPrime2 are also made.
Suppose i have a A object. A.roleB contains one B1 object and one B2 object.
When i map my A object to a APrime one, and when i look into APrime.roleB, it contains only BPrime-type objects :'(
So here's a suggestion to complete your great product :
What do you think about introducing a new property for mapping tag : inherits
My mapping will be :
<!-- mapping between A and APrime is untouched -->
When dozer is loaded, you can easily (yes you can ;-) ) find all inherited children mapping for each named-mapping. Then, when you iterate on A.roleB, you 'just' have to use the relevant mapping :D
I think the inheritance 'problem' (2/) can be resolved this way.
Every Open Source project wishes they had someone with the bug finding abilities of Seb. Once again we appreciate your finely honed investigative skills and will fix all of these for the 1.5 release.
Thanks Seb.
Franz
BTW - You got these Ben?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
As Seb said, its dozerBeanMapping.xml contains wildcard set to false.
So, logically, none of the attributes of A will be mapped to B. But list attributes of A ARE mapped to B ;-)
If we set the wildcard property to false in the mapping itself (<mapping wildcard="false">...), its ok : none of the attributes of A are mapped to B...
So, the wildcard default value is not used for list atrtibutes mapping (it seems to be a bug ;-)
Richard.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Well, this morning i was enjoyed to see the 1.5 release. But, i don't want to break the habits, so here are my conclusions :
Fixed a global wildcard bug --> tested and approved. Enjoy !
Addressed adding vs. updating List. We were not truly updating the list --> well, updating is now working, but it seems that "non-cumulative" value for relationshipType doesn't work anymore :-(
And i saw nothing about mappig inheritance :'(
Still in the roadmap ?
Bye
Seb, waiting for the 1.5.1 release ;-)
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Good morning to you :). I opened a defect against mapping inheritance. Ben is working on that for 1.5.1. He has 2 of your 3 UML diagrams done. The third one is pretty hard he said.
As far as non-cumulative...here is my unit test and it seems to work:
TestReferenceObject tro = new TestReferenceObject();
TestReferenceFoo foo2 = new TestReferenceFoo();
foo2.setA("a");
foo2.setB(null);
foo2.setC("c");
tro.setArrayToArrayNoncumulative(new Object[] { foo2 });
// clone for our assert
TestReferenceObject toClone = (TestReferenceObject) SerializationUtils.clone(tro);
// map to prime
TestReferencePrimeObject trop = (TestReferencePrimeObject) Mapper.map(tro, TestReferencePrimeObject.class);
// change 'b' value on fooPrime
TestReferenceFooPrime fooPrime2 = (TestReferenceFooPrime) trop.getArrayToArrayNoncumulative()[0];
fooPrime2.setB("b");
// map by reference back to original
Mapper.map(trop, tro);
// make sure we didn't lose the initial value 'c' set
assertEquals("c", ((TestReferenceFoo) tro.getArrayToArrayNoncumulative()[0]).getC());
// compare cloned and original - if non-cumulative did not work this should fail since we would have two objects in the object[] vs. only the one we started with
assertEquals(toClone, tro);
Thoughts?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
We are still working on those. I didn't want to put that in until it is fully tested. We should have them entirely done in a few days. I will let you know when we finish that. A little more complicated than we thought...
thanks for asking.
franz
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have the first two scenarios working. Basically, the fix was just to walk up the source classes' superclasses and see if we have any mappings with the destintation class OR its superclasses. That one was pretty easy. The bug was that we only checked the source classes' superclass to the destination classes' superclass and nothing in between.
The third scenario seems unrelated in that it has more to do with storing different object types in a Collection, vs. a pure 'inheritance' problem since that has been solved above. I don't know if I want to put mapping hierarchy into Dozer and start naming our maps. I can see a pandora's box with this.
How about if every object we find in a Collection we look into our bag of Class Maps and see if any of them have the source object and a mapping to another class?. If we do find it then we map accordingly unless we have a destination hint which makes life easier. If we have more than one mapping to the source object then our only choice is not to map since we can not determine which mapping to choose, and I don't want to be responsible for those permutations.
Thoughts?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Inheritance of mappings would be useful but hard to implement and also hard to use.
I understand you don't want to go this way.
I'm ok with the search of a mapping between B1 (third example of Seb) and something else. But you can make a more precise search of a mapping between B1 and a subtype of BPrime.
An other idea was to use multiple classes in source and destination type hint :
<A>roleB</A>
<B>roleBPrime</B>
<sourceTypeHint>B,B1,B2</sourceTypeHint>
<destinationTypeHint>BPrime,BPrime1,BPrime2</destinationTypeHint>
If roleB is an instance of B it is map to BPrime,
If roleB is an instance if B1, it is map to BPrime1,
If roleB is an instance if B2, it is map to BPrime2
The Dozer user can then define precisely his mappings...
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
If I don't have mapping inheritance, I must explicitly give to Dozer all the possible mappings between an instance of B (or subtype of B) and and instance of BPrime (or subtype of BPrime) for each relationship where B is mapped to BPrime.
Mapping inheritance as we though it would be used to state that :
I was searching for a way to reuse an existing mapping on 2 classes that are exactly the same except for its package names, i.e.
Already have mapping for A->B
Want to have mapping for A->C where B and C have exactly the same attributes and I want it to be mapped the same way as A->B
I looked around the support forums and thought this mapping inheritance would do the trick. However, looking at the dtd, I cannot find out the attributes needed to tell mapping A->C to use the A->B mapping.
Thanks in advance for any help.
Cheers!
Ching
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Notice that class C also contains fieldB which is the same as fieldB in class B. Is there any way to tell Dozer to use the first mapping when mapping A->C even though C is not related in any way to B in terms of class hierarchy?
The situation is that we have some generated code which unfortunately results in exactly the same class (X) being placed once in packageY and another time in packageZ where packageY.X and packageZ.X are exactly the same except for the package location.
Cheers!
Ching
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi guys ! (oh no, he's back again !!)
3 points today :)
1/ Wildcard property
In my dozerBeanMapping.xml, wildcard is set to false.
I have an object A with a field named list which is a List.
I have an object B with a field named list which is a List.
My mapping is :
<mapping>
<classA>wildcard.A</classA>
<classB>wildcard.B</classB>
</mapping>
I have a A instance with 2 String in list field.
When i map A to B, the B.list field also contains 2 String ! To avoid this, i have to add wildcard="false" as a property for the current mapping ...
2/ Inheritance
Case 1 :
--------
Look at my class diagram : http://img6.imageshack.us/img6/6892/050824inheritance6sp.jpg
I have 2 mappings : one between SuperClass and ClassPrime, and one between SubClass and ClassPrime.
When i try to map a SubClass object fully loaded in a ClassPrime empty one, getSuperAttribute2() always gives me null.
Case 2 :
--------
Let's make a few changes : http://img208.imageshack.us/img208/1579/050824inheritance27aw.jpg
My mappings are now between SuperClass and SuperClassPrime, and between SubClass and SubClassPrime.
The previous mapping test gives me the same result :(
3/ List and inheritance
Here's a more complex problem. Look at the class diagram : http://img364.imageshack.us/img364/9441/050824listandinheritance3ne.jpg
So A contains a List field (roleB) of B objects, maybe B1 or B2.
APrime contains a List field (roleB) of BPrime objects, maybe BPrime1 or BPrime2.
My mapping between A and APrime looks like (wilcard turned off) :
<mapping>
<classA>A</classA>
<classB>APrime</class>
<field relationshipType="non-cumulative">
<A>roleB</A>
<B>roleB</B>
<sourceTypeHint>B</sourceTypeHint>
<destinationTypeHint>BPrime</destinationTypeHint>
</field>
</mapping>
Mappings between B and BPrime, between B1 and BPrime1, and between B2 and BPrime2 are also made.
Suppose i have a A object. A.roleB contains one B1 object and one B2 object.
When i map my A object to a APrime one, and when i look into APrime.roleB, it contains only BPrime-type objects :'(
So here's a suggestion to complete your great product :
What do you think about introducing a new property for mapping tag : inherits
My mapping will be :
<mapping name="m1">
<classA>B</classA>
<classB>BPrime</classB>
<mapping>
<mapping inherits="m1">
<classA>B1</classA>
<classB>BPrime1</classB>
<field>
<A>b1</A>
<B>b1</B>
</field>
<mapping>
<mapping inherits="m1">
<classA>B2</classA>
<classB>BPrime2</classB>
<field>
<A>b2</A>
<B>b2</B>
</field>
<mapping>
<!-- mapping between A and APrime is untouched -->
When dozer is loaded, you can easily (yes you can ;-) ) find all inherited children mapping for each named-mapping. Then, when you iterate on A.roleB, you 'just' have to use the relevant mapping :D
I think the inheritance 'problem' (2/) can be resolved this way.
Furthermore, this behaviour can be extended to allow multiple inheritance.
Here's another (and my last ;-) ) class diagram : http://img297.imageshack.us/img297/4106/050824multipleinheritance5md.jpg
I hope it illustrates mapping inheritance advantages :)
Ready for the next release ? ;-)
Bye
Seb
We could not hope for a better user. Thanks Seb.
Every Open Source project wishes they had someone with the bug finding abilities of Seb. Once again we appreciate your finely honed investigative skills and will fix all of these for the 1.5 release.
Thanks Seb.
Franz
BTW - You got these Ben?
yes
Seb,
Your point #1 seems to work as designed, not sure what you are referring to here.
I will start the other points today.
Ben
Hi,
As Seb said, its dozerBeanMapping.xml contains wildcard set to false.
So, logically, none of the attributes of A will be mapped to B. But list attributes of A ARE mapped to B ;-)
If we set the wildcard property to false in the mapping itself (<mapping wildcard="false">...), its ok : none of the attributes of A are mapped to B...
So, the wildcard default value is not used for list atrtibutes mapping (it seems to be a bug ;-)
Richard.
Nice find guys. This will be fixed for the 1.5 release.
Thanks,
Franz
Hi guys !
Well, this morning i was enjoyed to see the 1.5 release. But, i don't want to break the habits, so here are my conclusions :
Fixed a global wildcard bug --> tested and approved. Enjoy !
Addressed adding vs. updating List. We were not truly updating the list --> well, updating is now working, but it seems that "non-cumulative" value for relationshipType doesn't work anymore :-(
And i saw nothing about mappig inheritance :'(
Still in the roadmap ?
Bye
Seb, waiting for the 1.5.1 release ;-)
Hey Seb -
Good morning to you :). I opened a defect against mapping inheritance. Ben is working on that for 1.5.1. He has 2 of your 3 UML diagrams done. The third one is pretty hard he said.
As far as non-cumulative...here is my unit test and it seems to work:
TestReferenceObject tro = new TestReferenceObject();
TestReferenceFoo foo2 = new TestReferenceFoo();
foo2.setA("a");
foo2.setB(null);
foo2.setC("c");
tro.setArrayToArrayNoncumulative(new Object[] { foo2 });
// clone for our assert
TestReferenceObject toClone = (TestReferenceObject) SerializationUtils.clone(tro);
// map to prime
TestReferencePrimeObject trop = (TestReferencePrimeObject) Mapper.map(tro, TestReferencePrimeObject.class);
// change 'b' value on fooPrime
TestReferenceFooPrime fooPrime2 = (TestReferenceFooPrime) trop.getArrayToArrayNoncumulative()[0];
fooPrime2.setB("b");
// map by reference back to original
Mapper.map(trop, tro);
// make sure we didn't lose the initial value 'c' set
assertEquals("c", ((TestReferenceFoo) tro.getArrayToArrayNoncumulative()[0]).getC());
// compare cloned and original - if non-cumulative did not work this should fail since we would have two objects in the object[] vs. only the one we started with
assertEquals(toClone, tro);
Thoughts?
Hi,
I see nothing in 1.5.1 release notes about mapping inheritance (we don't have made any tests on that yet).
Do these updates have been merged in this release ?
Thanks,
Richard.
Hey Richard -
We are still working on those. I didn't want to put that in until it is fully tested. We should have them entirely done in a few days. I will let you know when we finish that. A little more complicated than we thought...
thanks for asking.
franz
So....
I have the first two scenarios working. Basically, the fix was just to walk up the source classes' superclasses and see if we have any mappings with the destintation class OR its superclasses. That one was pretty easy. The bug was that we only checked the source classes' superclass to the destination classes' superclass and nothing in between.
The third scenario seems unrelated in that it has more to do with storing different object types in a Collection, vs. a pure 'inheritance' problem since that has been solved above. I don't know if I want to put mapping hierarchy into Dozer and start naming our maps. I can see a pandora's box with this.
How about if every object we find in a Collection we look into our bag of Class Maps and see if any of them have the source object and a mapping to another class?. If we do find it then we map accordingly unless we have a destination hint which makes life easier. If we have more than one mapping to the source object then our only choice is not to map since we can not determine which mapping to choose, and I don't want to be responsible for those permutations.
Thoughts?
Inheritance of mappings would be useful but hard to implement and also hard to use.
I understand you don't want to go this way.
I'm ok with the search of a mapping between B1 (third example of Seb) and something else. But you can make a more precise search of a mapping between B1 and a subtype of BPrime.
An other idea was to use multiple classes in source and destination type hint :
<A>roleB</A>
<B>roleBPrime</B>
<sourceTypeHint>B,B1,B2</sourceTypeHint>
<destinationTypeHint>BPrime,BPrime1,BPrime2</destinationTypeHint>
If roleB is an instance of B it is map to BPrime,
If roleB is an instance if B1, it is map to BPrime1,
If roleB is an instance if B2, it is map to BPrime2
The Dozer user can then define precisely his mappings...
Richard -
So are you saying there is a one-to-one relationship (and in correct order) of the multiple hints you have to add?
For example, I must know that since source hint B is first in the hint listing, and dest hint BPrime is first, then map those?
That's it.
If I don't have mapping inheritance, I must explicitly give to Dozer all the possible mappings between an instance of B (or subtype of B) and and instance of BPrime (or subtype of BPrime) for each relationship where B is mapped to BPrime.
Mapping inheritance as we though it would be used to state that :
<mapping id="1"
<classA>B</classA>
<classB>BPrime</classB>
</mapping>
<mapping id="2" extends="1">
<classA>B1</classA>
<classB>BPrime1</classB>
</mapping>
<mapping id="3" extends="1">
<classA>B1</classA>
<classB>BPrime1</classB>
</mapping>
And why not :
<mapping id="4" extends="2">
<classA>B11</classA>
<classB>BPrime11</classB>
</mapping>
So the list of hints and its order can be found using these inheritance relationships.
source hints = B11,B1,B2,B
destination hints = BPrime11, BPrime1, BPrime2, BPrime.
Sounds reasonable. I will put that functionality in for 1.5.2.
Hi all,
Sorry to dig up a potentially old thread.
I was searching for a way to reuse an existing mapping on 2 classes that are exactly the same except for its package names, i.e.
Already have mapping for A->B
Want to have mapping for A->C where B and C have exactly the same attributes and I want it to be mapped the same way as A->B
I looked around the support forums and thought this mapping inheritance would do the trick. However, looking at the dtd, I cannot find out the attributes needed to tell mapping A->C to use the A->B mapping.
Thanks in advance for any help.
Cheers!
Ching
Have you checked out our inheritance documentation?
http://dozer.sourceforge.net/documentation/baseattributes.html
Please let me know if you have any questions.
Thanks,
Franz
Hi Franz,
Thanks for the quick reply!
I had a look around the doco previously and after reviewing the link that you sent through, I will rephrase my question:
The 2 classes B and C are exactly the same class but not related in any sort of class hierarchy.
Example, assuming we already have the following mapping between A->B:
<mapping>
<classA>A</classA>
<classB>B</class>
<field>
<A>fieldA</A>
<B>fieldB</B>
</field>
</mapping>
Class C comes along and I want to map A->C according to:
<mapping>
<classA>A</classA>
<classB>C</class>
<field>
<A>fieldA</A>
<B>fieldB</B>
</field>
</mapping>
Notice that class C also contains fieldB which is the same as fieldB in class B. Is there any way to tell Dozer to use the first mapping when mapping A->C even though C is not related in any way to B in terms of class hierarchy?
The situation is that we have some generated code which unfortunately results in exactly the same class (X) being placed once in packageY and another time in packageZ where packageY.X and packageZ.X are exactly the same except for the package location.
Cheers!
Ching
Ahh....We do not have any support for that at this time. Interesting use case...copy/paste is the only option I see... :(
Franz
Thanks Franz, I was afraid of that =(
I will do the copy/paste reuse method for the time being - is this a feature that would interest others enough to have it be added to the roadmap?
Cheers!
Ching
We haven't had any other requests quite like that. The use case sounds pretty unique and I don't think we can add that to our roadmap... :(
thanks for looking.
franz