/* * Copyright 2013, 2014 Deutsche Nationalbibliothek * * Licensed under the Apache License, Version 2.0 the "License"; * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.culturegraph.mf.test; import java.io.FileNotFoundException; import java.io.StringReader; import org.culturegraph.mf.commons.ResourceUtil; import org.culturegraph.mf.commons.XmlUtil; import org.culturegraph.mf.commons.reflection.ReflectionUtil; import org.culturegraph.mf.framework.StreamPipe; import org.culturegraph.mf.framework.StreamReceiver; import org.culturegraph.mf.javaintegration.EventList; import org.culturegraph.mf.metamorph.Metamorph; import org.culturegraph.mf.test.reader.MultiFormatReader; import org.culturegraph.mf.test.reader.Reader; import org.culturegraph.mf.test.validators.StreamValidator; import org.junit.runners.model.InitializationError; import org.junit.runners.model.Statement; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; /** * Runs a test defined in a Metamorph-Test definition. * * @author Christoph Böhme * */ final class MetamorphTestCase extends Statement { private static final String NO_DATA_FOUND = "Please specify either element content or a src attribute"; private static final String NAME_ATTR = "name"; private static final String IGNORE_ATTR = "ignore"; private static final String RESULT_TAG = "result"; private static final String TRANSFORMATION_TAG = "transformation"; private static final String INPUT_TAG = "input"; private static final String SRC_ATTR = "src"; private static final String TYPE_ATTR = "type"; private static final String STRICT_RECORD_ORDER_ATTR = "strict-record-order"; private static final String STRICT_KEY_ORDER_ATTR = "strict-key-order"; private static final String STRICT_VALUE_ORDER_ATTR = "strict-value-order"; private static final String MIME_METAMORPH = "text/x-metamorph+xml"; private static final String MIME_JAVACLASS = "application/java"; private final Element config; MetamorphTestCase(final Element config) { this.config = config; } public String getName() { return config.getAttribute(NAME_ATTR); } public boolean isIgnore() { return Boolean.parseBoolean(config.getAttribute(IGNORE_ATTR)); } @Override public void evaluate() throws InitializationError { final Reader inputReader = getReader(INPUT_TAG); @SuppressWarnings("unchecked") final StreamPipe<StreamReceiver>transformation = getTransformation(); final EventList resultStream = new EventList(); if (transformation == null) { inputReader.setReceiver(resultStream); } else { inputReader.setReceiver(transformation).setReceiver(resultStream); } inputReader.process(getInputData()); inputReader.closeStream(); final StreamValidator validator = new StreamValidator(resultStream.getEvents()); validator.setErrorHandler(msg -> { throw new AssertionError(msg); }); final Element result = (Element) config.getElementsByTagName(RESULT_TAG).item(0); validator.setStrictRecordOrder(Boolean.parseBoolean( result.getAttribute(STRICT_RECORD_ORDER_ATTR))); validator.setStrictKeyOrder(Boolean.parseBoolean( result.getAttribute(STRICT_KEY_ORDER_ATTR))); validator.setStrictValueOrder(Boolean.parseBoolean( result.getAttribute(STRICT_VALUE_ORDER_ATTR))); final Reader resultReader = getReader(RESULT_TAG); resultReader.setReceiver(validator); resultReader.process(getExpectedResult()); validator.closeStream(); } private Reader getReader(final String tag) { final Element element = (Element) config.getElementsByTagName(tag).item(0); final String mimeType = element.getAttribute(TYPE_ATTR); return new MultiFormatReader(mimeType); } @SuppressWarnings("rawtypes") private StreamPipe getTransformation() throws InitializationError { final NodeList nodes = config.getElementsByTagName(TRANSFORMATION_TAG); if (nodes.getLength() == 0) { return null; } final Element transformationElement = (Element) nodes.item(0); final String type = transformationElement.getAttribute(TYPE_ATTR); final String src = transformationElement.getAttribute(SRC_ATTR); if (MIME_METAMORPH.equals(type)) { if (src.isEmpty()) { final InputSource transformationSource = new InputSource(getDataEmbedded(transformationElement)); transformationSource.setSystemId(transformationElement.getBaseURI()); return new Metamorph(transformationSource); } return new Metamorph(src); } else if (MIME_JAVACLASS.equals(type)) { if (src.isEmpty()) { throw new InitializationError( "class defining transformation not specified"); } return ReflectionUtil.loadClass(src, StreamPipe.class).newInstance(); } throw new InitializationError("transformation of type " + type + " is not supperted"); } private java.io.Reader getInputData() throws InitializationError { final Element input = (Element) config.getElementsByTagName(INPUT_TAG).item(0); if (input.hasAttribute(SRC_ATTR)) { return getDataFromSource(input.getAttribute(SRC_ATTR)); } return getDataEmbedded(input); } private java.io.Reader getExpectedResult() throws InitializationError { final Element result = (Element) config.getElementsByTagName(RESULT_TAG).item(0); if (result.hasAttribute(SRC_ATTR)) { return getDataFromSource(result.getAttribute(SRC_ATTR)); } return getDataEmbedded(result); } private java.io.Reader getDataFromSource(final String src) throws InitializationError { try { return ResourceUtil.getReader(src); } catch (final FileNotFoundException e) { throw new InitializationError("Could not find input file '" + src + "': " + e.getMessage()); } } private java.io.Reader getDataEmbedded(final Element input) throws InitializationError { final String inputType = input.getAttribute(TYPE_ATTR); if (input.hasChildNodes()) { if (XmlUtil.isXmlMimeType(inputType)) { return new StringReader(XmlUtil.nodeListToString(input.getChildNodes())); } return new StringReader(input.getTextContent()); } throw new InitializationError(NO_DATA_FOUND); } }