假设我有以下课程:
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlRootElement;
import core.type.ApplicationType;
import core.type.BaseApplicationType;
@XmlRootElement
public class Application
{
@XmlAnyElement
private ApplicationType type;
private int x = 0;
private int y = 0;
private String description = "";
public Application()
{
}
public Application(ApplicationType type)
{
this.type = type;
}
/**
* Get the application's type.
*
* @return the type
*/
public ApplicationType getType()
{
return type;
}
/**
* Get the description of this scenario.
*
* @return the description
*/
public String getDescription()
{
return description;
}
/**
* Set the scenario description.
*
* @param description the description to set
* @throws Exception if the description is invalid.
*/
public void setDescription(String description) throws Exception
{
if (description != null)
{
this.description = description;
}
else
{
throw new Exception("Invalid application description: '"
+ description + "'");
}
}
/**
* @param type the type to set
*/
public void setType(BaseApplicationType type)
{
this.type = type;
}
/**
* @return the x
*/
public int getX()
{
return x;
}
/**
* @param x the x to set
*/
public void setX(int x)
{
this.x = x;
}
/**
* @return the y
*/
public int getY()
{
return y;
}
/**
* @param y the y to set
*/
public void setY(int y)
{
this.y = y;
}
}
具有以下界面:
import core.Configuration;
import java.awt.*;
public interface ApplicationType
{
/**
* Get application name.
*
* @return This application name. Most likely it's entity ID.
*/
public String getName();
/**
* Get application icon.
*
* @param type Type of icon. Useful if it varies by state for example.
* @return Icon.
*/
public Image getIcon(int type);
/**
* Set the application's icon.
*
* @param icon Icon to set.
*/
public void setIcon(Image icon);
/**
* Set the application's name.
*
* @param name Name to set.
*/
public void setName(String name);
/**
* Get the application's path
*
* @return path
*/
public String getApplicationPath();
/**
* Create the application's folder.
*
* @throws Exception on any underlying error.
*/
public void createAppDirectory() throws Exception;
/**
* Set the application's path.
*
* @param path Path to set.
*/
public void setApplicationPath(String path);
/**
* Set the server's configuration.
*
* @param config New configuration.
*/
public void setConfiguration(Configuration config);
/**
* Get the server's configuration
*
* @return Configuration.
*/
public Configuration getConfiguration();
}
以及以下示例实现:
@XmlRootElement
public class ServerType extends BaseApplicationType
{
public ServerType()
{
setConfiguration(new Configuration());
setName("Server");
}
}
这个抽象类:
import java.awt.*;
import java.io.File;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public abstract class BaseApplicationType implements ApplicationType
{
private String path;
private String name;
private Image icon;
private Configuration config;
public BaseApplicationType(String path, String name, Image icon)
{
this.path = path;
this.name = name;
this.icon = icon;
}
public BaseApplicationType()
{
}
@Override
public Image getIcon(int type)
{
return icon;
}
@Override
public void setIcon(Image icon)
{
this.icon = icon;
}
@Override
public String getName()
{
return name;
}
@Override
public final void setName(String name)
{
this.name = name;
}
@Override
public String getApplicationPath()
{
return path;
}
@Override
public void createAppDirectory() throws Exception
{
if (path != null)
{
File appDir = new File(path);
if (appDir.exists())
{
throw new Exception("Path already exists: " + path);
}
else
{
if (!appDir.mkdirs())
{
throw new Exception("Error creating path: " + path);
}
}
}
else
{
throw new Exception("Invalid path: " + path);
}
}
@Override
public void setApplicationPath(String path)
{
this.path = path;
}
@Override
public final void setConfiguration(Configuration config)
{
this.config = config;
}
@Override
public final Configuration getConfiguration()
{
return config;
}
}
我可以将其整理如下:
@Test
public void testMarshallingApplication() throws JAXBException
{
Collection<? extends ApplicationType> types
= Lookup.getDefault().lookupAll(ApplicationType.class);
Class[] classes = new Class[types.size() + 1];
classes[0] = Application.class;
Iterator<? extends ApplicationType> it = types.iterator();
for (int i = 1; i <= types.size(); i++)
{
classes[i] = it.next().getClass();
}
JAXBContext jaxbContext = JAXBContext.newInstance(classes);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
// output pretty printed
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
for (ApplicationType type : types)
{
Application app = new Application((BaseApplicationType) type);
File testFile = new File(TestCaseUtils.createTempFile());
jaxbMarshaller.marshal(app, testFile);
jaxbMarshaller.marshal(app, TestCaseUtils.originalSystemOut);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Application loaded
= (Application) jaxbUnmarshaller.unmarshal(testFile);
assertNotNull(loaded);
assertNotNull(loaded.getType().getConfiguration());
assertEquals(app.getType().getConfiguration(),
loaded.getType().getConfiguration());
assertEquals(app.getDescription(), loaded.getDescription());
assertEquals(app.getX(), loaded.getX());
assertEquals(app.getType(), loaded.getType());
}
}
它给了我这个输出:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application>
<ServerType>
<configuration>
</configuration>
<name>Server</name>
</ServerType>
<description></description>
<x>0</x>
<y>0</y>
</application>
尝试解组时会给我错误:
java.lang.IllegalArgumentException: Can not set type.ApplicationType field core.application.Application.type to com.sun.org.apache.xerces.internal.dom.ElementNSImpl
我不知道如何将ServerType转换回去。欢迎任何帮助!
发现这确实接近JAXB: Can't unmarshal JAXBElement<?>, getting ElementNSImpl instead,但不完全相同。