This is an automated email from the ASF dual-hosted git repository. rec pushed a commit to branch refactoring/UIMA-6431-Use-lambda-functions-as-CAS-processors in repository https://gitbox.apache.org/repos/asf/uima-uimaj.git
commit 16ce603dc965be9475c0b415d63e4cc5f634ecaf Author: Richard Eckart de Castilho <[email protected]> AuthorDate: Fri Apr 8 15:41:50 2022 +0200 [UIMA-6431] Use lambda functions as CAS processors - Add default implementatins to AnalysisEngineServiceStub and ResourceServiceStub to reduce verbosity - Add analysis engine implementations using CAS- or JCas-accepting methods - Added tests --- .../uima/analysis_component/CasProcessor.java | 60 +++++++++++++++ .../analysis_component/CasProcessorAnnotator.java | 77 +++++++++++++++++++ .../analysis_component/JCasAnnotator_ImplBase.java | 1 - .../uima/analysis_component/JCasProcessor.java | 60 +++++++++++++++ .../analysis_component/JCasProcessorAnnotator.java | 87 ++++++++++++++++++++++ .../analysis_engine/AnalysisEngineServiceStub.java | 8 +- .../AnalysisEngineProcessorAdapter.java} | 70 +++++------------ .../impl/AnalysisEngineProcessorStub.java} | 41 +++++++--- .../service/impl/AnalysisEngineServiceAdapter.java | 5 +- .../apache/uima/resource/ResourceServiceStub.java | 7 +- .../CasProcessorAnnotatorTest.java | 82 ++++++++++++++++++++ .../JCasProcessorAnnotatorTest.java | 82 ++++++++++++++++++++ 12 files changed, 509 insertions(+), 71 deletions(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_component/CasProcessor.java b/uimaj-core/src/main/java/org/apache/uima/analysis_component/CasProcessor.java new file mode 100644 index 000000000..96b4c7e65 --- /dev/null +++ b/uimaj-core/src/main/java/org/apache/uima/analysis_component/CasProcessor.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.uima.analysis_component; + +import java.util.Objects; + +import org.apache.uima.cas.CAS; + +/** + * A functional interface for a CAS processor. + * + * @param <E> + * Thrown exception. + */ +@FunctionalInterface +public interface CasProcessor<E extends Throwable> { + + /** + * Accepts the processor. + * + * @param aCas + * the CAS to process. + * @throws E + * Thrown when the processor fails. + */ + void process(CAS aCas) throws E; + + /** + * Returns a composed {@code CasProcessor} like {@link CasProcessor#andThen(CasProcessor)}. + * + * @param after + * the operation to perform after this operation + * @return a composed {@code CasProcessor} like {@link CasProcessor#andThen(CasProcessor)}. + * @throws NullPointerException + * when {@code after} is null + */ + default CasProcessor<E> andThen(final CasProcessor<E> after) { + Objects.requireNonNull(after); + return (final CAS t) -> { + process(t); + after.process(t); + }; + } +} diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_component/CasProcessorAnnotator.java b/uimaj-core/src/main/java/org/apache/uima/analysis_component/CasProcessorAnnotator.java new file mode 100644 index 000000000..eeef72abb --- /dev/null +++ b/uimaj-core/src/main/java/org/apache/uima/analysis_component/CasProcessorAnnotator.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.uima.analysis_component; + +import java.util.Map; + +import org.apache.uima.UIMAFramework; +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.analysis_engine.impl.AnalysisEngineProcessorAdapter; +import org.apache.uima.analysis_engine.impl.AnalysisEngineProcessorStub; +import org.apache.uima.cas.CAS; +import org.apache.uima.resource.ResourceInitializationException; +import org.apache.uima.resource.ResourceSpecifier; +import org.apache.uima.resource.metadata.ResourceMetaData; + +public class CasProcessorAnnotator extends AnalysisEngineProcessorAdapter { + private ResourceMetaData metaData; + private CasProcessor<? extends Exception> delegate; + + public CasProcessorAnnotator(CasProcessor<? extends Exception> aCasAnnotator) { + metaData = UIMAFramework.getResourceSpecifierFactory().createAnalysisEngineMetaData(); + delegate = aCasAnnotator; + } + + @Override + public boolean initialize(ResourceSpecifier aSpecifier, Map<String, Object> aAdditionalParams) + throws ResourceInitializationException { + setStub(makeDelegate()); + return super.initialize(aSpecifier, aAdditionalParams); + } + + private AnalysisEngineProcessorStub makeDelegate() { + return new AnalysisEngineProcessorStub() { + + @Override + public ResourceMetaData getMetaData() { + return metaData; + } + + @Override + public void process(CAS aCAS) throws AnalysisEngineProcessException { + try { + delegate.process(aCAS); + } catch (Exception e) { + if (e instanceof AnalysisEngineProcessException) { + throw (AnalysisEngineProcessException) e; + } else { + throw new AnalysisEngineProcessException(e); + } + } + } + }; + } + + public static CasProcessorAnnotator of(CasProcessor<? extends Exception> aCasAnnotator) + throws ResourceInitializationException { + CasProcessorAnnotator engine = new CasProcessorAnnotator(aCasAnnotator); + engine.initialize(null, null); + return engine; + } +} diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasAnnotator_ImplBase.java b/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasAnnotator_ImplBase.java index 598edf3c5..9c450d166 100644 --- a/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasAnnotator_ImplBase.java +++ b/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasAnnotator_ImplBase.java @@ -16,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.uima.analysis_component; import org.apache.uima.analysis_engine.AnalysisEngineProcessException; diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasProcessor.java b/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasProcessor.java new file mode 100644 index 000000000..4bcc3160d --- /dev/null +++ b/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasProcessor.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.uima.analysis_component; + +import java.util.Objects; + +import org.apache.uima.jcas.JCas; + +/** + * A functional interface for a JCas processor. + * + * @param <E> + * Thrown exception. + */ +@FunctionalInterface +public interface JCasProcessor<E extends Throwable> { + + /** + * Accepts the processor. + * + * @param aJCas + * the JCas to process. + * @throws E + * Thrown when the processor fails. + */ + void process(JCas aJCas) throws E; + + /** + * Returns a composed {@code JCasProcessor} like {@link JCasProcessor#andThen(JCasProcessor)}. + * + * @param after + * the operation to perform after this operation + * @return a composed {@code JCasProcessor} like {@link JCasProcessor#andThen(JCasProcessor)}. + * @throws NullPointerException + * when {@code after} is null + */ + default JCasProcessor<E> andThen(final JCasProcessor<E> after) { + Objects.requireNonNull(after); + return (final JCas t) -> { + process(t); + after.process(t); + }; + } +} diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasProcessorAnnotator.java b/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasProcessorAnnotator.java new file mode 100644 index 000000000..8cecdc506 --- /dev/null +++ b/uimaj-core/src/main/java/org/apache/uima/analysis_component/JCasProcessorAnnotator.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.uima.analysis_component; + +import java.util.Map; + +import org.apache.uima.UIMAFramework; +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.analysis_engine.impl.AnalysisEngineProcessorAdapter; +import org.apache.uima.analysis_engine.impl.AnalysisEngineProcessorStub; +import org.apache.uima.cas.CAS; +import org.apache.uima.cas.CASException; +import org.apache.uima.jcas.JCas; +import org.apache.uima.resource.ResourceInitializationException; +import org.apache.uima.resource.ResourceSpecifier; +import org.apache.uima.resource.metadata.ResourceMetaData; + +public class JCasProcessorAnnotator extends AnalysisEngineProcessorAdapter { + private ResourceMetaData metaData; + private JCasProcessor<? extends Exception> delegate; + + public JCasProcessorAnnotator( + JCasProcessor<? extends Exception> aJCasAnnotator) { + metaData = UIMAFramework.getResourceSpecifierFactory().createAnalysisEngineMetaData(); + delegate = aJCasAnnotator; + } + + @Override + public boolean initialize(ResourceSpecifier aSpecifier, Map<String, Object> aAdditionalParams) + throws ResourceInitializationException { + setStub(makeDelegate()); + return super.initialize(aSpecifier, aAdditionalParams); + } + + private AnalysisEngineProcessorStub makeDelegate() { + return new AnalysisEngineProcessorStub() { + + @Override + public ResourceMetaData getMetaData() { + return metaData; + } + + @Override + public void process(CAS aCAS) throws AnalysisEngineProcessException { + JCas jcas; + try { + jcas = aCAS.getJCas(); + } catch (CASException e) { + throw new AnalysisEngineProcessException(e); + } + try { + delegate.process(jcas); + } catch (Exception e) { + if (e instanceof AnalysisEngineProcessException) { + throw (AnalysisEngineProcessException) e; + } else { + throw new AnalysisEngineProcessException(e); + } + } + } + }; + } + + public static JCasProcessorAnnotator of( + JCasProcessor<? extends AnalysisEngineProcessException> aJCasAnnotator) + throws ResourceInitializationException { + JCasProcessorAnnotator engine = new JCasProcessorAnnotator(aJCasAnnotator); + engine.initialize(null, null); + return engine; + } +} diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngineServiceStub.java b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngineServiceStub.java index c83cfacb6..4f287d8df 100644 --- a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngineServiceStub.java +++ b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/AnalysisEngineServiceStub.java @@ -43,7 +43,9 @@ public interface AnalysisEngineServiceStub extends ResourceServiceStub { * @throws ResourceServiceException * tbd */ - void callBatchProcessComplete() throws ResourceServiceException; + default void callBatchProcessComplete() throws ResourceServiceException { + // No action by default. + } /** * Performs service call to inform the AnalysisEngine that the processing of a collection has been @@ -52,5 +54,7 @@ public interface AnalysisEngineServiceStub extends ResourceServiceStub { * @throws ResourceServiceException * tbd */ - void callCollectionProcessComplete() throws ResourceServiceException; + default void callCollectionProcessComplete() throws ResourceServiceException { + // No action by default. + } } diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/service/impl/AnalysisEngineServiceAdapter.java b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineProcessorAdapter.java similarity index 69% copy from uimaj-core/src/main/java/org/apache/uima/analysis_engine/service/impl/AnalysisEngineServiceAdapter.java copy to uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineProcessorAdapter.java index 197f57cef..c99ac1fa2 100644 --- a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/service/impl/AnalysisEngineServiceAdapter.java +++ b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineProcessorAdapter.java @@ -17,53 +17,35 @@ * under the License. */ -package org.apache.uima.analysis_engine.service.impl; - -import java.util.Map; +package org.apache.uima.analysis_engine.impl; import org.apache.uima.UIMAFramework; -import org.apache.uima.UIMARuntimeException; import org.apache.uima.UIMA_UnsupportedOperationException; -import org.apache.uima.analysis_engine.AnalysisEngine; import org.apache.uima.analysis_engine.AnalysisEngineProcessException; -import org.apache.uima.analysis_engine.AnalysisEngineServiceStub; import org.apache.uima.analysis_engine.CasIterator; import org.apache.uima.analysis_engine.TextAnalysisEngine; -import org.apache.uima.analysis_engine.impl.AnalysisEngineImplBase; -import org.apache.uima.analysis_engine.impl.EmptyCasIterator; import org.apache.uima.cas.CAS; import org.apache.uima.collection.CasConsumer; import org.apache.uima.resource.ResourceConfigurationException; -import org.apache.uima.resource.ResourceServiceException; -import org.apache.uima.resource.ResourceSpecifier; import org.apache.uima.resource.metadata.ResourceMetaData; import org.apache.uima.util.Level; import org.apache.uima.util.UimaTimer; /** - * Base class for analysis engine service adapters. Implements the {@link AnalysisEngine} interface - * by communicating with an Analysis Engine service. This insulates the application from having to - * know whether it is calling a local AnalysisEngine or a remote service. - * <p> - * Subclasses must provide an implementation of the {@link #initialize(ResourceSpecifier,Map)} - * method, which must create an {@link AnalysisEngineServiceStub} object that can communicate with - * the remote service. The stub must be passed to the {@link #setStub(AnalysisEngineServiceStub)} - * method of this class. - * - * + * Base class for analysis engine processor adapters. Used for embedded (functional) processors. */ -public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBase +public abstract class AnalysisEngineProcessorAdapter extends AnalysisEngineImplBase implements TextAnalysisEngine, CasConsumer { /** * current class */ - private static final Class<AnalysisEngineServiceAdapter> CLASS_NAME = AnalysisEngineServiceAdapter.class; + private static final Class<AnalysisEngineProcessorAdapter> CLASS_NAME = AnalysisEngineProcessorAdapter.class; /** - * The stub that communicates with the remote service. + * The stub that talks to the actual implementation. */ - private AnalysisEngineServiceStub mStub; + private AnalysisEngineProcessorStub mStub; /** * The resource metadata, cached so that service does not have to be called each time metadata is @@ -77,13 +59,13 @@ public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBas private UimaTimer mTimer = UIMAFramework.newTimer(); /** - * Sets the stub to be used to communicate with the remote service. Subclasses must call this from - * their <code>initialize</code> method. + * Sets the stub to be used to actual implementation. Subclasses must call this from their + * <code>initialize</code> method. * * @param aStub * the stub for the remote service */ - protected void setStub(AnalysisEngineServiceStub aStub) { + protected void setStub(AnalysisEngineProcessorStub aStub) { mStub = aStub; } @@ -92,7 +74,7 @@ public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBas * * @return the stub for the remote service */ - protected AnalysisEngineServiceStub getStub() { + protected AnalysisEngineProcessorStub getStub() { return mStub; } @@ -101,14 +83,8 @@ public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBas */ @Override public ResourceMetaData getMetaData() { - try { - if (mCachedMetaData == null && getStub() != null) { - mCachedMetaData = getStub().callGetMetaData(); - } - return mCachedMetaData; - } catch (ResourceServiceException e) { - throw new UIMARuntimeException(e); - } + + return getStub() != null ? getStub().getMetaData() : null; } /** @@ -116,8 +92,9 @@ public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBas */ @Override public void destroy() { - if (getStub() != null) + if (getStub() != null) { getStub().destroy(); + } super.destroy(); } @@ -129,7 +106,7 @@ public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBas LOG_RESOURCE_BUNDLE, "UIMA_analysis_engine_process_begin__FINE", getResourceName()); try { // invoke service - getStub().callProcess(aCAS); + getStub().process(aCAS); // log end of event UIMAFramework.getLogger(CLASS_NAME).logrb(Level.FINE, CLASS_NAME.getName(), "process", @@ -138,10 +115,9 @@ public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBas // we don't support CasMultiplier services yet, so this always returns // an empty iterator return new EmptyCasIterator(); + } catch (AnalysisEngineProcessException e) { + throw e; } catch (Exception e) { - // log exception - UIMAFramework.getLogger(CLASS_NAME).log(Level.SEVERE, "", e); - // rethrow as AnalysisEngineProcessException throw new AnalysisEngineProcessException(e); } finally { mTimer.stopIt(); @@ -199,20 +175,12 @@ public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBas @Override public void batchProcessComplete() throws AnalysisEngineProcessException { - try { - getStub().callBatchProcessComplete(); - } catch (ResourceServiceException e) { - throw new AnalysisEngineProcessException(e); - } + getStub().batchProcessComplete(); } @Override public void collectionProcessComplete() throws AnalysisEngineProcessException { - try { - getStub().callCollectionProcessComplete(); - } catch (ResourceServiceException e) { - throw new AnalysisEngineProcessException(e); - } + getStub().collectionProcessComplete(); } /** diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/ResourceServiceStub.java b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineProcessorStub.java similarity index 52% copy from uimaj-core/src/main/java/org/apache/uima/resource/ResourceServiceStub.java copy to uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineProcessorStub.java index 3b7028437..28e390a97 100644 --- a/uimaj-core/src/main/java/org/apache/uima/resource/ResourceServiceStub.java +++ b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/AnalysisEngineProcessorStub.java @@ -16,28 +16,49 @@ * specific language governing permissions and limitations * under the License. */ +package org.apache.uima.analysis_engine.impl; -package org.apache.uima.resource; - +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.cas.CAS; import org.apache.uima.resource.metadata.ResourceMetaData; /** * A stub that calls a remote AnalysisEngine service. - * - * */ -public interface ResourceServiceStub { +public interface AnalysisEngineProcessorStub { /** * Performs service call to retrieve resource meta data. * * @return metadata for the Resource - * @throws ResourceServiceException - * passthru */ - ResourceMetaData callGetMetaData() throws ResourceServiceException; + ResourceMetaData getMetaData(); + + /** + * Performs service call to process an entity. + * + * @param aCAS + * the CAS to process + */ + void process(CAS aCAS) throws AnalysisEngineProcessException; + + /** + * Notify the stub that all items in the batch have been processed. + */ + default void batchProcessComplete() throws AnalysisEngineProcessException { + // No action by default. + } + + /** + * Notify the stub that all items in the collection have been processed. + */ + default void collectionProcessComplete() throws AnalysisEngineProcessException { + // No action by default. + } /** - * Called when this stub is no longer needed, so any open connections can be closed. + * Called when this stub is no longer needed, so resources can be cleaned up. */ - void destroy(); + default void destroy() { + // No action by default + } } diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/service/impl/AnalysisEngineServiceAdapter.java b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/service/impl/AnalysisEngineServiceAdapter.java index 197f57cef..3c440ed98 100644 --- a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/service/impl/AnalysisEngineServiceAdapter.java +++ b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/service/impl/AnalysisEngineServiceAdapter.java @@ -49,8 +49,6 @@ import org.apache.uima.util.UimaTimer; * method, which must create an {@link AnalysisEngineServiceStub} object that can communicate with * the remote service. The stub must be passed to the {@link #setStub(AnalysisEngineServiceStub)} * method of this class. - * - * */ public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBase implements TextAnalysisEngine, CasConsumer { @@ -116,8 +114,9 @@ public abstract class AnalysisEngineServiceAdapter extends AnalysisEngineImplBas */ @Override public void destroy() { - if (getStub() != null) + if (getStub() != null) { getStub().destroy(); + } super.destroy(); } diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/ResourceServiceStub.java b/uimaj-core/src/main/java/org/apache/uima/resource/ResourceServiceStub.java index 3b7028437..e81ba14ca 100644 --- a/uimaj-core/src/main/java/org/apache/uima/resource/ResourceServiceStub.java +++ b/uimaj-core/src/main/java/org/apache/uima/resource/ResourceServiceStub.java @@ -16,15 +16,12 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.uima.resource; import org.apache.uima.resource.metadata.ResourceMetaData; /** * A stub that calls a remote AnalysisEngine service. - * - * */ public interface ResourceServiceStub { /** @@ -39,5 +36,7 @@ public interface ResourceServiceStub { /** * Called when this stub is no longer needed, so any open connections can be closed. */ - void destroy(); + default void destroy() { + // No action by default + } } diff --git a/uimaj-core/src/test/java/org/apache/uima/analysis_component/CasProcessorAnnotatorTest.java b/uimaj-core/src/test/java/org/apache/uima/analysis_component/CasProcessorAnnotatorTest.java new file mode 100644 index 000000000..3f66c514b --- /dev/null +++ b/uimaj-core/src/test/java/org/apache/uima/analysis_component/CasProcessorAnnotatorTest.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.uima.analysis_component; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import org.apache.uima.analysis_engine.AnalysisEngine; +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.cas.CAS; +import org.apache.uima.util.CasCreationUtils; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class CasProcessorAnnotatorTest { + + private static final String NEEDLE = "needle"; + + private CAS cas; + + @BeforeEach + public void setup() throws Exception { + cas = CasCreationUtils.createCas(); + } + + @Test + void thatProcessingWithJCasInterfaceWorks() throws Exception { + AnalysisEngine engine = CasProcessorAnnotator.of(_cas -> _cas.setDocumentText(NEEDLE)); + engine.process(cas.getJCas()); + + assertThat(cas.getDocumentText()).isEqualTo(NEEDLE); + } + + @Test + void thatProcessingWithCasInterfaceWorks() throws Exception { + AnalysisEngine engine = CasProcessorAnnotator.of(_cas -> _cas.setDocumentText(NEEDLE)); + engine.process(cas); + + assertThat(cas.getDocumentText()).isEqualTo(NEEDLE); + } + + @Test + void thatAnalysisEngineProcessExceptionMakesItThrough() throws Exception { + AnalysisEngine engine = CasProcessorAnnotator.of(_cas -> { + throw new AnalysisEngineProcessException(NEEDLE, null); + }); + + assertThatExceptionOfType(AnalysisEngineProcessException.class) + .isThrownBy(() -> engine.process(cas)) // + .matches(ex -> NEEDLE.equals(ex.getMessageKey())); + } + + @Test + void thatGenericExceptionIsWrapped() throws Exception { + AnalysisEngine engine = CasProcessorAnnotator.of(_cas -> { + throw new RuntimeException(NEEDLE); + }); + + Assertions.setMaxStackTraceElementsDisplayed(1000); + assertThatExceptionOfType(AnalysisEngineProcessException.class) + .isThrownBy(() -> engine.process(cas)) // + .matches(ex -> ex.getCause() instanceof RuntimeException) + .matches(ex -> NEEDLE.equals(ex.getCause().getMessage())); + } +} diff --git a/uimaj-core/src/test/java/org/apache/uima/analysis_component/JCasProcessorAnnotatorTest.java b/uimaj-core/src/test/java/org/apache/uima/analysis_component/JCasProcessorAnnotatorTest.java new file mode 100644 index 000000000..11d67e7e5 --- /dev/null +++ b/uimaj-core/src/test/java/org/apache/uima/analysis_component/JCasProcessorAnnotatorTest.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.uima.analysis_component; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; + +import org.apache.uima.analysis_engine.AnalysisEngine; +import org.apache.uima.analysis_engine.AnalysisEngineProcessException; +import org.apache.uima.cas.CAS; +import org.apache.uima.util.CasCreationUtils; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +class JCasProcessorAnnotatorTest { + + private static final String NEEDLE = "needle"; + + private CAS cas; + + @BeforeEach + public void setup() throws Exception { + cas = CasCreationUtils.createCas(); + } + + @Test + void thatProcessingWithJCasInterfaceWorks() throws Exception { + AnalysisEngine engine = JCasProcessorAnnotator.of(_cas -> _cas.setDocumentText(NEEDLE)); + engine.process(cas.getJCas()); + + assertThat(cas.getDocumentText()).isEqualTo(NEEDLE); + } + + @Test + void thatProcessingWithCasInterfaceWorks() throws Exception { + AnalysisEngine engine = JCasProcessorAnnotator.of(_cas -> _cas.setDocumentText(NEEDLE)); + engine.process(cas); + + assertThat(cas.getDocumentText()).isEqualTo(NEEDLE); + } + + @Test + void thatAnalysisEngineProcessExceptionMakesItThrough() throws Exception { + AnalysisEngine engine = JCasProcessorAnnotator.of(_cas -> { + throw new AnalysisEngineProcessException(NEEDLE, null); + }); + + assertThatExceptionOfType(AnalysisEngineProcessException.class) + .isThrownBy(() -> engine.process(cas)) // + .matches(ex -> NEEDLE.equals(ex.getMessageKey())); + } + + @Test + void thatGenericExceptionIsWrapped() throws Exception { + AnalysisEngine engine = JCasProcessorAnnotator.of(_cas -> { + throw new RuntimeException(NEEDLE); + }); + + Assertions.setMaxStackTraceElementsDisplayed(1000); + assertThatExceptionOfType(AnalysisEngineProcessException.class) + .isThrownBy(() -> engine.process(cas)) // + .matches(ex -> ex.getCause() instanceof RuntimeException) + .matches(ex -> NEEDLE.equals(ex.getCause().getMessage())); + } +}
