| ||
|
This community works best when people use their real names. Please
register for a free account.
Other Groups: Joel on Software Business of Software Design of Software (CLOSED) .NET Questions (CLOSED) TechInterview.org CityDesk FogBugz Fog Creek Copilot The Old Forum Your hosts: Albert D. Kallal Li-Fan Chen Stephen Jones |
I have 2 classes, we will call them Address. Both have the same attributes but are in different packages. I am trying to write a mediator/converter to convert back and forth between them but i am unsure on how to do this in java, if it is possible. This works fine for simple types but complex types have me stumped. So for example i have: class Address{ int number; String[] address; String suffix; } one of these is defined in com.myspace.client and one is defined in com.myspace.server. I have a wsdl that i created in eclipse that represent the functions that the client will call to get info on the server side. the converter will manage the types to get info from the server, then convert them back to the client types. The idea is to keep the server completely separate from any client to achieve total separation, so that in the future only parts of the converter would have to be re-written. any help is appreciated.
package com.myspace.client public class Address { public Address(com.myspace.server.Address address) { this.number = address.getNumber(); ... } } So just pass one of the Address types into the constructor of the other (and possibly vice-versa) and do the conversion right there.
ok let me be more specific and lets see if that helps to make sure we are on the same page. A few schemas were created in eclipse to define certain types. One of the types is Address, like i described before. A WSDL was created from these schemas and built into a package. From this, the main IMPL class was created which are the WSDL stub calls that the client will use to retrieve information. I have no control over the client other than the fact that it knows what functions are available and thats all the client knows about. It doesnt know nor is it supposed to know anything about the server side. An example would be a certain function: public class myengineSOAPImpl implements com.generated.services.myengine_PortType{ public com.general.client.Address getAddress(int id) throws java.rmi.RemoteException{ Converter convert = new Converter(id); } } where the com.general.client.Address is the package name + class type that it expects to be returned. My Converter class is to use the argument 'id' and use that number to do whatever it needs to do to get the correct data that i need, in this case an Address..that is, my own Address class back to the converter as a result. Because its my own definition of Address(with the same attributes) its going to have a different package name. Remember though that the IMPL class expects to be returned its own Address type thats in a different package that i described at the beginning. So in my converter class how, would i make the appropriate java method calls or casting class to convert my Address class type to the correct IMPL Address class type that it expects? thanks for the previous response, hopefully i explained it better this time.
Use reflection. Iterate declared fields, find matched by name, copy values. Almost trival operation. Repeat for superclasses if required.
You won't be able to typecast between the 2 object hierarchies unless they implement a common base Address class or interface. To reference 2 identically named classes in the same class, one can be imported and the other will need a fully-qualified package.class when referenced, or both could be fully qualified import client.Address; public class ServerProxy { public Address getAddress(String id) { // Retrieve the server version of the Address class com.x.y.server.Address serverAddress = dbQuery.findAddress(id); // Do stuff to the server side Address ... // Convert server version to the client-side representation AddressConverter converter = new AddressConverter(); return converter.toClientAddress(serverAddress); } } If AddressConverter's only responsibility is to convert between the 2 Address classes, then it would have 2 conversion methods, where 1 of the Address classes is fully qualified: import client.Address; public class AddressConverter { public com.x.y.server.Address toServerAddress(Address clientAddress) public Address toClientAddress(com.x.y.server.Address serverAddress) }
Avoid bi-directional dependencies between packages like a plague, they create "interesting" build failures.
As suggested, have both classes implement an interface: interface IAddress { int getNumber(); String[] getAddress(); String getSuffix(); void setNumber( int number ); void setAddress( String[] address ); void setSuffix( String suffix ); } You can then create a utility method to convert from any implementation of IAddress to any other given implementation: Class AddressBridge { public static void convertAddress( IAddressI sourceAddress, IAddressI destAddress ) { if ( null != sourceAddress && null != destAddress ) { destAddress.setNumber( sourceAddress.getNumber() ); destAddress.setAddress( sourceAddress.getAddress() ); destAddress.setPrefix( sourceAddress.getPrefix() ); } } So, the client would take whatever IAdress object it received and the client's version of the object like so: myspace.client.Address clientAddress = myspace.client.Address(); AddressBridge.convertAddress( someAddress, clientAddress ); That's it.
Sorry, that last bit would be: myspace.client.Address clientAddress = new myspace.client.Address(); AddressBridge.convertAddress( someAddress, clientAddress );
The problem is that it forces both classes to be mutable. I prefer my data objects to be as immutable as possible.
You could preserve immutability by reducing the common interface to its read-only part and implementing copy constructors in both classes. Address1(IAddress other) Address2(IAddress other)
thanks all for the input. what i ended up doing was brute assignment of each part of the structure into whichever package type i needed to convert to. so if i have package a.address and b.address and both of them have the same members and types i just build locally in my converter class what class i need to convert to and assign values separately all the way down to the primitive types(in the case of a member being a struct). so if struct is so if you pass in a com.server.address myAddress... private static com.client.Address wsdlAddress = new com.client.Address; wsdlAddress.zipcode = myAddress.zipcode; wsdlAddress.name = myAddress.name; ..... ..... if members are their own struct with the main Address struct then obviously i have to convert that first. After all everything at the lowest level is a primitive and can be copied as such. just takes a bit more code. gosh i hope that makes sense. i am just getting over a cold. | |
Powered by FogBugz
