简体   繁体   English

我怎样才能简化这个解析方法?

[英]How can I simplify this parsing method?

I am writing code to unmarshal XML from a file.我正在编写代码以从文件中解组 XML。 I don't know up front which schema the XML is based on so I try to unmarshal it with several schemas in the form of different Jaxb2Marshaller instances.我事先不知道 XML 基于哪个模式,因此我尝试使用不同 Jaxb2Marshaller 实例形式的多个模式对其进行解组。

The method needs to:该方法需要:

  1. attempt to unmarshal the XML with each marshaller尝试用每个编组器解组 XML
  2. If this succeeds, return the resulting object如果成功,返回结果 object
  3. If it fails, try the next marshaller如果失败,尝试下一个编组器
  4. If all marshallers fail, throw an exception with the last error message如果所有编组器都失败,则抛出最后一个错误消息的异常

Here is the current code:这是当前代码:

private Object getObject(final byte[] data) throws MyException {
    String lastErrorMessage = "";
    for (final Jaxb2Marshaller marshaller : this.marshallers) {
        try {
            return marshaller.unmarshal(new StreamSource(new ByteArrayInputStream(data)));
        } catch (final XmlMappingException e) {
            LOGGER.warn("Invalid XML", e);
            lastErrorMessage = e.getMessage();
        }
    }
    throw new MyException(lastErrorMessage);
}

I feel this method does too many things at different levels of abstraction:我觉得这种方法在不同的抽象层次上做了太多事情:

  • iterate over marshallers遍历编组器
  • apply a marshaller应用编组器
  • return result返回结果
  • catch exceptions捕获异常
  • throw exception抛出异常

But I don't see a way to simplify it.但我看不到简化它的方法。 The try-catch block is needed for every marshaller (because I should catch and ignore these XmlMappingExceptions except the last one).每个编组器都需要 try-catch 块(因为除了最后一个之外,我应该捕获并忽略这些 XmlMappingExceptions)。 That block either returns a result object, or the lastErrorMessage, which is needed below the iteration to throw the MyException.该块要么返回结果 object,要么返回 lastErrorMessage,在迭代下面需要它来抛出 MyException。

The only solution I can think of is to create some contrived Result class which contains either the result object or the error message but that feels cludgy.我能想到的唯一解决方案是创建一些人为的结果 class,其中包含结果 object 或错误消息,但感觉很笨拙。 Any other insights?还有其他见解吗?

I would like methods with a granularity like these: 我想要像这样的粒度方法:

private Object getObject(byte[] data) throws MyException {
    Result result;
    for (Jaxb2Marshaller marshaller : this.marshallers) {
        result = getObject(marshaller, data);
    }
    return handleError(result);
}

private Result getObject(Jaxb2Marshaller marshaller, byte[] data) {
    try {
        return Result.value(marshaller.unmarshal(new StreamSource(new ByteArrayInputStream(data))));
    } catch (final XmlMappingException e) {
        LOGGER.warn("Invalid XML", e);
        return Result.error(e.getMessage());
    }
}

private Object handleError(Result result) {
    if (result.isError()) {
        throw new MyException(result.errroMessage);
    }
    else {
        return result.value;        
    }
}

But the additional Result class is verbose and cludgy: 但是附加的Result类是冗长而且笨拙的:

private class Result {
    String errorMessage;
    Object value;

    static Result error(String errorMessage) {
        Result result = new Result();
        result.errorMessage = errorMessage;
        return result;
    }

    static Result value(Object value) {
        Result result = new Result();
        result.value = value;
        return result;
    }

    boolean isError() {
        return errorMessage != null;
    }
}

How about this?这个怎么样?

public class MultiUnmarshaller {

    private final List<Jaxb2Marshaller> marshallers;
    private Object value;
    private String error;

    public MultiUnmarshaller(List<Jaxb2Marshaller> marshallers) {
        this.marshallers = marshallers;
    }

    private void init() {
        error = "No marshallers available";
        value = null;
    }

    public Object getObject(byte[] data) throws MyException {
        init();
        Iterator<Jaxb2Marshaller> it = marshallers.iterator();           
        while(it.hasNext() && errorMessage != null) {
            unmarshalObject(marshaller, data);
        }
        return produceResult();
    }

    private void unmarshalObject(Jaxb2Marshaller marshaller, byte[] data) {
        try {
            value = marshaller.unmarshal(new StreamSource(new     ByteArrayInputStream(data)));
            error = null;
        } catch (final XmlMappingException e) {
            LOGGER.warn("Invalid XML", e);
            error = e.getMessage();
        }
    }

    private Object produceResult() {
        if (error == null) {
            return value;        
        }
        else {
            throw new MyException(error);
        }
    }
    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM