我有一个包含以下输出的日志文件:
2226:org.powertac.common.TariffSpecification::6::new::1::CONSUMPTION
2231:org.powertac.common.Rate::7::new
2231:org.powertac.common.Rate::7::withValue::-0.5
2232:org.powertac.common.Rate::7::setTariffId::6
2232:org.powertac.common.TariffSpecification::6::addRate::7
2233:org.powertac.common.Tariff::6::new::6
2234:org.powertac.common.TariffSpecification::8::new::1::INTERRUPTIBLE_CONSUMPTION
2234:org.powertac.common.Rate::9::new
2234:org.powertac.common.Rate::9::withValue::-0.5
2235:org.powertac.common.Rate::9::setTariffId::8
解析文件后,请使用以下模式:
<id>:<full_classname>::<order_of_execution>::<new_or_method>::<params>
解析器运行良好,并且完成了我的期望。现在,我的目标是将同一条指令编组到XML
文件中。我完全不熟悉这种任务。
因此,XML
必须同时包含new
个对象和methods
调用。
我知道使用Reflection
API我会使用<full_classname>
来创建该类的对象:
Class<?> cl = Class.forName( className );
如何从XML
对象生成此类Class
文件?我是否必须拥有数据结构或方法来获取对象的所有方法和字段并将其写入xml文件?我知道Reflection API有这样的方法,但我需要一个更通用/样本的想法,我怎么能完成我的任务。
我开始写下这个方法,但我不确定它会如何工作:
// would send in the object to be marshalled.
public void toXML(Object obj){
try {
JAXBContext context = JAXBContext.newInstance(Object.class);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
以下是已解析文件的示例:
171269 org.powertac.common.Order 171417 new 4
171270 org.powertac.common.Order 171418 new 4
171271 org.powertac.common.Order 171419 new 4
parse
方法如下:
public void parse() throws ClassNotFoundException{
try{
//
// assure file exists before parsing
//
FileReader fr = new FileReader( this.filename );
BufferedReader textReader = new BufferedReader( fr );
String line;
File input = new File("test.xml");
//Integer id = 1;
while(( line = textReader.readLine()) != null ){
Pattern p = Pattern.compile("([^:]+):([^:]+)::([\\d]+)::([^:]+)::(.+)");
Matcher m = p.matcher( line );
if (m.find()) {
int id = Integer.parseInt(m.group(1));
String className = m.group(2);
int orderOfExecution = Integer.valueOf( m.group( 3 ));
String methodNameOrNew = m.group(4);
String[] arguments = m.group(5).split("::");
//
// there is the need to create a new object
//
if( methodNameOrNew.compareTo( "new" ) == 0 ){
//
// inner class
//
if( className.contains("$") == true){
continue;
}
else if( className.contains("genco")){
continue;
}
System.out.println("Loading class: " + className);
LogEntry le = new LogEntry(id, className, orderOfExecution, methodNameOrNew, arguments.toString());
Serializer ser = new Persister();
ser.write(le, input);
id++;
System.out.printf("%s %s %d %s %d\n", id, className, orderOfExecution, methodNameOrNew, arguments.length);
}
}
}
textReader.close();
}
catch( IOException ex ){
ex.printStackTrace();
}
catch( ArrayIndexOutOfBoundsException ex){
ex.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void write() throws Exception{
File file = new File("test.xml");
Serializer ser = new Persister();
for(LogEntry entry : entries){
ser.write(entry, file);
}
}
答案 0 :(得分:1)
以下是使用Simple XML库的第一次尝试:
@Default()
public class LogEntry
{
private int id;
private Object classInstance;
private String orderOfExecution;
private String newOrMethod;
private String params;
// throws 'Exception' only for testing
public LogEntry(int id, String className, String orderOfExecution, String newOrMethod, String params) throws Exception
{
this.id = id;
this.classInstance = Class.forName(className).newInstance();
this.orderOfExecution = orderOfExecution;
this.newOrMethod = newOrMethod;
this.params = params;
}
// getter / setter
}
如何从类LogEntry
中创建XML:
// Here is an example of an entry
LogEntry le = new LogEntry(3, "com.example.MyClass", "abc", "def", "ghi");
Serializer ser = new Persister();
ser.write(le, new File("test.xml"));
简单XML非常易于使用,请参阅此处tutorials和examples。
您可以使用LogEntry类中的Annotations来处理整个XML,但是您也可以让@Default()
为您完成所有操作: - )
答案 1 :(得分:1)
<强> LogEntry:强>
@Default()
public class LogEntry
{
private int id;
private Object classInstance;
private int orderOfExecution;
private String newOrMethod;
private List<Object> args;
public LogEntry(int id, Object classInstance, int orderOfExecution, String newOrMethod, List<Object> args)
{
this.id = id;
this.classInstance = classInstance;
this.orderOfExecution = orderOfExecution;
this.newOrMethod = newOrMethod;
this.args = args;
}
public LogEntry() { }
// getter / setter / toString / ... here
}
解析方法:
// Here all entries are saved
private List<LogEntry> entries = new ArrayList<>();
// ...
public void parse() throws Exception
{
// Don't compile this in a loop!
Pattern p = Pattern.compile("([^:]+):([^:]+)::([\\d]+)::([^:]+)::(.+)");
FileReader fr = new FileReader(this.filename);
BufferedReader textReader = new BufferedReader(fr);
String line;
while( (line = textReader.readLine()) != null )
{
Matcher m = p.matcher(line);
if( m.find() )
{
LogEntry entry = new LogEntry();
entry.setId(Integer.valueOf(m.group(1)));
String className = m.group(2);
entry.setOrderOfExecution(Integer.valueOf(m.group(3)));
String methodNameOrNew = m.group(4);
entry.setNewOrMethod(methodNameOrNew); // required in LogEntry?
Object[] arguments = m.group(5).split("::");
entry.setArgs(Arrays.asList(arguments));
if( methodNameOrNew.equals("new") )
{
if( className.contains("$") == true || className.contains("genco") )
continue;
createInstance(className, arguments);
}
else
{
callMethod(className, methodNameOrNew, arguments);
}
// XXX: for testing - set the instance 'not null'
entry.setClassInstance("only for testing");
entries.add(entry);
}
}
textReader.close();
}
修改强>
让我们说你的parse() - Method,List等属于Class Example
:
@Root
public class Example
{
private File filename = new File("test.txt");
@ElementList
private List<LogEntry> entries = new ArrayList<>();
// ...
// Only 'entries' is annotated as entry -> only it will get serialized
public void storeToXml(File f) throws Exception
{
Serializer ser = new Persister();
ser.write(this, f);
}
public void parse() throws Exception
{
// ...
}
}
注意:对于此示例,我在entry.setClassInstance("only for testing");
之上添加了entries.add(...)
,否则实例为null
。
编辑#2:解析()
的辅助方法private Object createInstance(String className, Object args[])
{
// TODO
return null;
}
private void callMethod(String className, String methodName, Object args[])
{
// TODO
}