Search code examples
javaxmlcastingxsdxmlbeans

How to upcast and use child specific methods


I have the following problem:

//class XmlObject is part of org.apache.xmlbeans
public class DepartmentType extends XmlObject; // getName method is defined in this class
public class OrganizatiopnType extends XmlObject; // getName method is defined in this class

XmlObject department = null;
if (a == 1)
    department = (DepartmentType) order.getDepartment(); // returns DepartmentType
else
    department = (OrganizationType) order.getOrganization(); // returns OrganizationType

department.getName(); // throws cannot find symbol
// ... and do some other complex stuff using methods which are defined in both classes ...

What is the cleanest way to call the getName() method?

UPDATE 1:
Cybernate, your approach seems the most logical, if you have control over the DepartmentType & OrganizationType. Unfortunately, these objects are generated from XML schema by xmlbeans. In my case, I could redesign the schema, so that both types have common base.

But what if I wouldn't have the control over the schema. How could I implement the basic idea?


Solution

  • If you have control of your schema you can define a base abstract type that your other types can extend from. I haven't tried this myself so I'm not sure how it XmlBeans will handle it.

    <complexType name="NamedEntity" abstract="true">
        <sequence>
            <element name="name" type="string"/>
        </sequence>
    </complexType>
    
    <complexType name="DepartmentType">
        <complexContent>
            <extension base="NamedEntity">
                <sequence>
                    <element name="whatever"/>
                </sequence>
            </extension>
        </complexContent>
    </complexType>
    

    Otherwise, it's a work-around (hack?) but you could use Commons BeanUtils provided your generated classes follow JavaBean naming convention. If these objects are getting passed around a lot you could create a wrapper class to make the calls a little more concrete.

    public class Department {
        XmlObject obj;
    
        public Department(XmlObject obj){
            if(!obj instanceof DepartmentType || !obj instanceof OrganizatiopnType){
                throw new IllegalArgumentException();
            }
            this.obj = obj;
        }
    
        public String getName(){
            return (String)PropertyUtils.getProperty(obj, "name");
        }
    }
    

    Any problem can be solved with another layer of indirection.....except too much indirection.