...
  View open merge request
Commits (10)
......@@ -127,7 +127,7 @@ public abstract class AbstractTestMojo extends AbstractMojo {
return descriptions;
}
private boolean filterEngineDescriptionWithoutTypeCapability(AnalysisEngineDescription engineDescription){
private boolean filterEngineDescriptionWithoutTypeCapability(AnalysisEngineDescription engineDescription) {
Class<?> implementationClass = analysisEngineService.loadAnalysisEngineImplementation(engineDescription);
return findAnnotation(implementationClass, TypeCapability.class) != null;
}
......
......@@ -26,6 +26,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import de.schrieveslaach.nlpf.maven.plugin.models.TestResult;
import de.schrieveslaach.nlpf.maven.plugin.reader.ClearTypesCombinationReader;
import de.tudarmstadt.ukp.dkpro.core.api.metadata.type.DocumentMetaData;
import de.tudarmstadt.ukp.dkpro.core.api.parameter.ComponentParameters;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
......@@ -34,18 +35,23 @@ import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.uima.UIMAException;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.collection.CollectionReaderDescription;
import org.apache.uima.fit.descriptor.ResourceMetaData;
import org.apache.uima.fit.descriptor.TypeCapability;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.apache.uima.resource.ResourceInitializationException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import static de.schrieveslaach.nlpf.maven.plugin.JCasDataUtil.loadJCas;
import static de.schrieveslaach.nlpf.plumbing.WriterDescriptionFactory.createWriterDescription;
import static de.schrieveslaach.nlpf.plumbing.util.AnalysisEngineDescriptionUtil.hash;
import static org.apache.uima.fit.pipeline.SimplePipeline.runPipeline;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
......@@ -82,7 +88,7 @@ public class IsolatedToolsTestMojo extends AbstractTestMojo {
TestResult testResult = new TestResult(engineDescription);
measureAndAddToTestResult(testData, plainTestData, testResult, engineDescription);
return new TestResultWrapper(testResult, engineDescription);
return new TestResultWrapper(testResult, engineDescription, plainTestData);
}
private void logNlpToolsInfo(AnalysisEngineDescription engineDescription) {
......@@ -118,7 +124,9 @@ public class IsolatedToolsTestMojo extends AbstractTestMojo {
private AnalysisEngineDescription engineDescription;
@SneakyThrows(IOException.class)
private List<JCas> testData;
@SneakyThrows({IOException.class})
private void store() {
File dataDirectory = directoryService.getIsolatedToolsTestDataDirectory();
File testDataFile = new File(dataDirectory, hash(engineDescription) + ".json");
......@@ -128,6 +136,44 @@ public class IsolatedToolsTestMojo extends AbstractTestMojo {
try (FileOutputStream fos = new FileOutputStream(testDataFile)) {
mapper.writeValue(fos, testResult);
}
storeCASData(dataDirectory);
}
private void storeCASData(File dataDirectory) {
File casDataDirectory = new File(dataDirectory, hash(engineDescription) + "/");
casDataDirectory.mkdir();
for (JCas jCas : testData) {
JCasUtil.select(jCas, DocumentMetaData.class).stream()
.findFirst()
.ifPresent(documentMetaData -> {
String sourceLocationName = documentMetaData.getDocumentId();
// useBaseUri and look into getRelativePath
if (sourceLocationName != null) {
//TODO: fallback if no documentId?
File sourceLocation = new File(directoryService.getTestCorpusDirectory(), sourceLocationName);
File targetLocation = new File(casDataDirectory, sourceLocationName);
String language = documentMetaData.getLanguage();
try {
AnalysisEngineDescription testWriterDescription = createWriterDescription(classLoaderService.getDependencyClassLoader(), sourceLocation, targetLocation,
ComponentParameters.PARAM_LANGUAGE, language);
runPipeline(jCas, testWriterDescription);
} catch (FileNotFoundException e) {
//TODO: exception logging
} catch (AnalysisEngineProcessException e) {
//TODO: exception logging
} catch (ResourceInitializationException e) {
//TODO: exception logging
}
} else {
//TODO: log
}
});
}
}
}
}
......@@ -38,13 +38,13 @@ import java.util.List;
import static org.apache.uima.fit.pipeline.SimplePipeline.iteratePipeline;
import static org.apache.uima.fit.util.JCasUtil.select;
class JCasDataUtil {
public class JCasDataUtil {
private JCasDataUtil() {
}
static List<JCas> loadJCas(CollectionReaderDescription collectionReaderDescription, AnalysisEngineDescription... engineDescriptions) {
public static List<JCas> loadJCas(CollectionReaderDescription collectionReaderDescription, AnalysisEngineDescription... engineDescriptions) {
List<JCas> jCasList = new ArrayList<>();
for (JCas originalJCas : iteratePipeline(collectionReaderDescription, engineDescriptions)) {
jCasList.add(copyJCas(originalJCas));
......
......@@ -60,6 +60,17 @@ public class DirectoryService {
return new File(mavenProject.getBasedir(), "src/test/corpus");
}
/**
* Returns the {@link MavenProject#getBuild() build directory}.
*
* @return
*/
public File getBuildDirectory() {
File buildDirectory = new File(mavenProject.getBuild().getDirectory());
buildDirectory.mkdirs();
return buildDirectory;
}
/**
* Returns the directory in the {@link MavenProject#getBuild() build directory} which contains the derived NLP
* models.
......
......@@ -28,6 +28,7 @@ import de.schrieveslaach.nlpf.maven.plugin.service.AnalysisEngineDescriptionServ
import de.schrieveslaach.nlpf.maven.plugin.service.ClassLoaderService;
import de.schrieveslaach.nlpf.maven.plugin.service.CollectionReaderDescriptionService;
import de.schrieveslaach.nlpf.maven.plugin.service.DirectoryService;
import de.tudarmstadt.ukp.dkpro.core.api.metadata.type.DocumentMetaData;
import de.tudarmstadt.ukp.dkpro.core.io.xmi.XmiReader;
import de.tudarmstadt.ukp.dkpro.core.io.xmi.XmiWriter;
import lombok.SneakyThrows;
......@@ -36,6 +37,7 @@ import org.apache.uima.UIMAException;
import org.apache.uima.analysis_component.AnalysisComponent;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.apache.uima.collection.CollectionReaderDescription;
import org.apache.uima.fit.util.JCasUtil;
import org.apache.uima.jcas.JCas;
import org.junit.Before;
import org.junit.Rule;
......@@ -163,35 +165,34 @@ public abstract class AbstractTestMojoTest {
}
}
@SneakyThrows({IOException.class, UIMAException.class, MojoExecutionException.class, SAXException.class})
public void provideTestJCasFromFile(String fileName) {
JCas satyaNadellaExample = createSatyaNadellaExample();
JCasUtil.select(satyaNadellaExample, DocumentMetaData.class).stream().findFirst().get().setDocumentId(fileName);
createTestJCas(satyaNadellaExample);
}
public void provideTestJCas() {
JCas satyaNadellaExample = createSatyaNadellaExample();
JCas openNlpExample = createOpenNlpExample();
JCas torwaldsExample = createTorwaldsExampleWithPosTags();
createTestJCas(satyaNadellaExample, openNlpExample, torwaldsExample);
}
@SneakyThrows({IOException.class, UIMAException.class, MojoExecutionException.class, SAXException.class})
private void createTestJCas(JCas... jCas) {
File testDirectory = folder.newFolder("src", "test", "corpus");
runPipeline(satyaNadellaExample,
createEngineDescription(
XmiWriter.class,
XmiWriter.PARAM_TARGET_LOCATION, testDirectory,
XmiWriter.PARAM_OVERWRITE, true
)
);
runPipeline(openNlpExample,
createEngineDescription(
XmiWriter.class,
XmiWriter.PARAM_TARGET_LOCATION, testDirectory,
XmiWriter.PARAM_OVERWRITE, true
)
);
runPipeline(torwaldsExample,
createEngineDescription(
XmiWriter.class,
XmiWriter.PARAM_TARGET_LOCATION, testDirectory,
XmiWriter.PARAM_OVERWRITE, true
)
);
for (JCas aJCas : jCas) {
runPipeline(aJCas,
createEngineDescription(
XmiWriter.class,
XmiWriter.PARAM_TARGET_LOCATION, testDirectory,
XmiWriter.PARAM_OVERWRITE, true
)
);
}
CollectionReaderDescription readerDescription = createReaderDescription(
XmiReader.class,
......
......@@ -44,6 +44,7 @@ import static java.util.Arrays.asList;
import static net.javacrumbs.jsonunit.JsonMatchers.jsonEquals;
import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.io.FileMatchers.anExistingDirectory;
import static org.hamcrest.io.FileMatchers.anExistingFile;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
......@@ -120,6 +121,13 @@ public class IsolatedToolsTestMojoTest extends AbstractTestMojoTest {
directory.mkdirs();
return directory;
});
when(directoryService.getTestCorpusDirectory()).then(invocation -> {
File testCorpusDirectory = new File(new File(new File(folder.getRoot(), "src"), "test"), "corpus");
testCorpusDirectory.mkdirs();
return testCorpusDirectory;
});
}
@Test
......@@ -156,6 +164,17 @@ public class IsolatedToolsTestMojoTest extends AbstractTestMojoTest {
assertThat(json, jsonEquals(jsonOpenNlpPersonTestResult()).withTolerance(0.001));
}
@Test
public void shouldStoreCASData_InIsolatedToolsTestData() throws Exception {
mockEngineDescriptionsInDescriptorsDirectory(MyPosTagger.class);
provideTestJCasFromFile("Satya_Nadella.xmi");
mojo.execute();
File casDataFile = assertThatCasDataFileExists(MyPosTagger.DEFAULT_HASH_CODE, "Satya_Nadella", "xmi");
//TODO compare content of the file?
}
@Override
protected AbstractTestMojo getMojoUnderTest() {
return mojo;
......@@ -166,4 +185,12 @@ public class IsolatedToolsTestMojoTest extends AbstractTestMojoTest {
assertThat(testResult, is(anExistingFile()));
return testResult;
}
private File assertThatCasDataFileExists(String hash, String casDataName, String extension) {
File casDataDirectory = new File(folder.getRoot(), "target/isolated-tools-test-data/" + hash);
assertThat(casDataDirectory, is(anExistingDirectory()));
File casDataFile = new File(casDataDirectory, casDataName + "." + extension);
assertThat(casDataFile, is(anExistingFile()));
return casDataFile;
}
}
package de.schrieveslaach.nlpf.plumbing;
/*-
* ========================LICENSE_START=================================
* nlp-maven-plugin
* %%
* Copyright (C) 2017 Schrieveslaach
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* =========================LICENSE_END==================================
*/
import de.tudarmstadt.ukp.dkpro.core.api.parameter.ComponentParameters;
import org.apache.commons.io.FilenameUtils;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static de.schrieveslaach.nlpf.plumbing.JCasFileWriterFactory.findWriterDescriptionByFileExtension;
public class WriterDescriptionFactory {
private WriterDescriptionFactory() {
}
/**
* Creates a writer for files with the given {@code extension} and configured with {@code parameters}.
*
* @param classLoader
* @param extension
* @param parameters
* @return
*/
public static AnalysisEngineDescription createWriterDescription(ClassLoader classLoader, String extension, Object... parameters) {
List<AnalysisEngineDescription> descriptions = findWriterDescriptionByFileExtension(
classLoader,
"." + extension,
parameters);
return descriptions.stream()
.findFirst()
//TODO: exception handling if null...or logging?
.get();
}
/**
* Creates a writer for the given {@code sourceFile} with {@link ComponentParameters#PARAM_TARGET_LOCATION} configured as {@code targetFile}.
*
* @param classloader
* @param sourceFile
* @param targetFile
* @param parameters
* @return
* @throws FileNotFoundException if the source file does not exist
*/
public static AnalysisEngineDescription createWriterDescription(ClassLoader classloader, File sourceFile, File targetFile, Object... parameters) throws FileNotFoundException {
if (!sourceFile.exists()) {
throw new FileNotFoundException(sourceFile + "(Does not exist)");
} else if (sourceFile.isDirectory()) {
throw new FileNotFoundException(sourceFile + "(Is a directory)");
}
//TODO: source and target should wether be file or directory, check this?
String extension = FilenameUtils.getExtension(sourceFile.getName());
List<Object> params = new ArrayList<>(Arrays.asList(ComponentParameters.PARAM_SOURCE_LOCATION, sourceFile,
ComponentParameters.PARAM_TARGET_LOCATION, targetFile,
"singularTarget", true));
params.addAll(Arrays.asList(parameters));
return createWriterDescription(classloader, extension, params.toArray());
}
}
package de.schrieveslaach.nlpf.plumbing;
/*-
* ========================LICENSE_START=================================
* nlp-maven-plugin
* %%
* Copyright (C) 2017 - 2018 Schrieveslaach
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* <http://www.gnu.org/licenses/lgpl-3.0.html>.
* =========================LICENSE_END==================================
*/
import de.tudarmstadt.ukp.dkpro.core.io.xmi.XmiWriter;
import lombok.SneakyThrows;
import org.apache.uima.analysis_engine.AnalysisEngineDescription;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import java.io.File;
import java.io.IOException;
import java.util.Objects;
import static de.schrieveslaach.nlpf.plumbing.WriterDescriptionFactory.createWriterDescription;
import static org.junit.Assert.assertThat;
@RunWith(MockitoJUnitRunner.class)
public class WriterDescriptionFactoryTest {
@Rule
public final TemporaryFolder folder = new TemporaryFolder();
@Rule
public final ExpectedException expectedException = ExpectedException.none();
private ClassLoader classLoader = ClassLoader.getSystemClassLoader();
@Before
public void setupFolder() throws IOException {
folder.newFolder("src", "test", "corpus");
}
@Test
public void shouldNotCreateWriterDescription_SourceFileIsMissing() throws Exception {
File sourceFile = folder.newFile("src/test/corpus/source.xmi");
sourceFile.delete();
expectedException.expectMessage(sourceFile + "(Does not exist)");
createWriterDescription(classLoader, sourceFile, folder.newFile());
}
@Test
public void shouldNotCreateReaderDescription_Source_IsDirectory() throws Exception {
File sourceDirectory = new File(folder.getRoot(), "src/test/corpus");
File targetDirectory = folder.newFolder("target/");
expectedException.expectMessage(sourceDirectory + "(Is a directory)");
createWriterDescription(classLoader, sourceDirectory, targetDirectory);
}
@Test
public void shouldCreateReaderDescription_Source_IsFile() throws Exception {
File sourceFile = folder.newFile("src/test/corpus/source.xmi");
File targetFile = folder.newFile("src/test/corpus/target.xmi");
AnalysisEngineDescription writerDescription = createWriterDescription(classLoader, sourceFile, targetFile);
assertThat(writerDescription, isXmiWriter());
assertThat(writerDescription, hasParamaterValue("sourceLocation", sourceFile.toString()));
assertThat(writerDescription, hasParamaterValue("targetLocation", targetFile.toString()));
assertThat(writerDescription, hasParamaterValue("singularTarget", true));
}
@Test
public void shouldCreateReaderDescription_WithParameters() throws Exception {
File sourceFile = folder.newFile("src/test/corpus/source.xmi");
File targetFile = folder.newFile("src/test/corpus/target.xmi");
AnalysisEngineDescription writerDescription = createWriterDescription(classLoader, sourceFile, targetFile,
"customParam", "customValue");
assertThat(writerDescription, hasParamaterValue("customParam", "customValue"));
}
public Matcher<AnalysisEngineDescription> isXmiWriter() {
return new TypeSafeMatcher<AnalysisEngineDescription>() {
@SneakyThrows
@Override
protected boolean matchesSafely(AnalysisEngineDescription analysisEngineDescription) {
Class<?> cls = Class.forName(analysisEngineDescription.getImplementationName());
return XmiWriter.class.isAssignableFrom(cls);
}
@Override
public void describeTo(Description description) {
}
};
}
public Matcher<AnalysisEngineDescription> hasParamaterValue(final String parameter, final Object expectedValue) {
return new TypeSafeMatcher<AnalysisEngineDescription>() {
@Override
protected boolean matchesSafely(AnalysisEngineDescription analysisEngineDescription) {
Object realValue = analysisEngineDescription.getMetaData().getConfigurationParameterSettings().getParameterValue(parameter);
return Objects.equals(realValue, expectedValue);
}
@Override
public void describeTo(Description description) {
description.appendText("parameter ").appendValue(parameter).appendText(" has value: ").appendValue(expectedValue);
}
@Override
protected void describeMismatchSafely(AnalysisEngineDescription analysisEngineDescription, Description mismatchDescription) {
Object realValue = analysisEngineDescription.getMetaData().getConfigurationParameterSettings().getParameterValue(parameter);
mismatchDescription.appendText("parameter ").appendValue(parameter).appendText(" has value: ").appendValue(realValue);
}
};
}
}