1

我有一个带有以下输出的日志文件:

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调用。我知道使用ReflectionAPI<full_classname>来创建该类的对象:

Class<?> cl = Class.forName( className );

我怎么能从那个对象生成这样XML的文件?Class我是否必须有一个数据结构或一种方法来获取对象的所有方法和字段并将它们写入 xml 文件?我知道反射 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);
        }
    }
4

2 回答 2

1

日志条目:

@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: parse() 的辅助方法

private Object createInstance(String className, Object args[])
{
    // TODO
    return null;
}


private void callMethod(String className, String methodName, Object args[])
{
    // TODO
}
于 2012-08-28T21:01:40.540 回答
1

这是使用简单 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 
}

以及如何使 XML 脱离类LogEntry

// 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 非常易于使用,请参阅此处获取教程示例。您可以使用 LogEntry 类中的注释自定义整个 XML,但是您也可以让@Default()一切为您做 :-)

于 2012-08-28T19:27:26.717 回答