This is an automated email from the ASF dual-hosted git repository. rec pushed a commit to branch bugfix/275-Improved-error-message-made-it-even-more-misleading in repository https://gitbox.apache.org/repos/asf/uima-uimaj.git
commit 0a595133f43fe85ce518481e6418e5b5cf01e452 Author: Richard Eckart de Castilho <r...@apache.org> AuthorDate: Wed Jan 11 16:02:29 2023 +0100 Issue #275: Improved error message made it even more misleading - Added tests for the different error messages - Found out that the recently introduced error message makes no sense and removed it - Improved wording of a few additional error messages --- .../org/apache/uima/cas/CASRuntimeException.java | 6 -- .../org/apache/uima/cas/impl/TypeSystemImpl.java | 34 ++++---- .../apache/uima/UIMAException_Messages.properties | 7 +- .../apache/uima/cas/impl/TypeSystemImplTest.java | 99 ++++++++++++++++++++++ .../java/org/apache/uima/jcas/test/JCasTest.java | 28 ------ 5 files changed, 118 insertions(+), 56 deletions(-) diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/CASRuntimeException.java b/uimaj-core/src/main/java/org/apache/uima/cas/CASRuntimeException.java index 47e4282f9..0668d61d3 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/CASRuntimeException.java +++ b/uimaj-core/src/main/java/org/apache/uima/cas/CASRuntimeException.java @@ -127,12 +127,6 @@ public class CASRuntimeException extends UIMARuntimeException { */ public static final String JCAS_TYPE_NOT_IN_CAS = "JCAS_TYPE_NOT_IN_CAS"; - /** - * JCas type "{0}" defined in CAS type system and used in Java code, but was not registered in - * JCasRegistry. - */ - public static final String JCAS_TYPE_NOT_IN_CAS_REGISTRY = "JCAS_TYPE_NOT_IN_CAS_REGISTRY"; - /** * CAS type system type "{0}" defines field "{1}" with range "{2}", but JCas class has range * "{3}". diff --git a/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java b/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java index 2c31e9b5d..aa9fe7ebf 100644 --- a/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java +++ b/uimaj-core/src/main/java/org/apache/uima/cas/impl/TypeSystemImpl.java @@ -2725,21 +2725,22 @@ public class TypeSystemImpl implements TypeSystem, TypeSystemMgr, LowLevelTypeSy * For a given JCasRegistry index, that doesn't have a corresponding UIMA type, throw an * appropriate exception * - * @param i - * - the index in the JCasRegistry - */ - private void throwMissingUIMAtype(int typeindex) { - Class<? extends TOP> cls = JCasRegistry.getClassForIndex(typeindex); - if (cls != null) { - String className = cls.getName(); - System.err.format( - "Missing UIMA type, JCas Class name: %s, index: %d, jcasRegisteredTypes size: %d%n", - className, typeindex, jcasRegisteredTypes.size()); - dumpTypeSystem(); - throw new CASRuntimeException(CASRuntimeException.JCAS_TYPE_NOT_IN_CAS_REGISTRY, className); - } else { + * @param typeIndex + * the index in the JCasRegistry + */ + private void throwMissingUIMAtype(int typeIndex) { + Class<? extends TOP> cls = JCasRegistry.getClassForIndex(typeIndex); + if (cls == null) { throw new CASRuntimeException(CASRuntimeException.JCAS_UNKNOWN_TYPE_NOT_IN_CAS); } + + String className = cls.getName(); + UIMAFramework.getLogger().error( + "Missing UIMA type, JCas Class name: {}, index: {}, jcasRegisteredTypes size: {}", + className, typeIndex, jcasRegisteredTypes.size()); + dumpTypeSystem(); + + throw new CASRuntimeException(CASRuntimeException.JCAS_TYPE_NOT_IN_CAS, className); } // for debugging @@ -2758,7 +2759,7 @@ public class TypeSystemImpl implements TypeSystem, TypeSystemMgr, LowLevelTypeSy } } } - System.err.println(sb); + UIMAFramework.getLogger().error(sb::toString); /** debug dump all types **/ sb.setLength(0); @@ -2775,7 +2776,7 @@ public class TypeSystemImpl implements TypeSystem, TypeSystemMgr, LowLevelTypeSy sb.append('\n'); } } - System.err.println(sb); + UIMAFramework.getLogger().error(sb::toString); } // public FSClassRegistry getFSClassRegistry() { @@ -2792,9 +2793,6 @@ public class TypeSystemImpl implements TypeSystem, TypeSystemMgr, LowLevelTypeSy * the UIMA type */ void setJCasRegisteredType(int typeIndexID, TypeImpl ti) { - // if (typeIndexID == 23) { - // System.out.format("debug typeIndexId = 23, typeImpl = %s%n", ti.getName()); - // } synchronized (jcasRegisteredTypes) { TypeImpl existing = Misc.getWithExpand(jcasRegisteredTypes, typeIndexID); if (existing != null) { diff --git a/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties b/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties index 71df49ed0..c079e6643 100644 --- a/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties +++ b/uimaj-core/src/main/resources/org/apache/uima/UIMAException_Messages.properties @@ -555,13 +555,12 @@ CHILD_INDEX_OOB = Error accessing child node in tree, index out of range. JCAS_ARRAY_NOT_SUPPORTED = User-defined JCas classes for built-in Arrays not supported, class: {0} JCAS_CAS_NOT_V3 = JCas Class "{0}", loaded from "{1}", is missing required constructor; likely cause is wrong version (UIMA version 3 or later JCas required). JCAS_MISSING_FIELD_ACCESSOR = JCas Class "{0}" is missing required field accessor, or access not permitted, for field "{1}" during {2} operation. -JCAS_CAS_MISMATCH = CAS type system doesn''t match JCas Type definition for type "{0}". +JCAS_CAS_MISMATCH = CAS type system does not match JCas Type definition for type "{0}". JCAS_TYPE_NOT_IN_CAS = JCas type "{0}" used in Java code, but was not declared in the XML type descriptor. -JCAS_TYPE_NOT_IN_CAS_REGISTRY = JCas type "{0}" defined in CAS type system and used in Java code, but was not registered in JCasRegistry. JCAS_UNKNOWN_TYPE_NOT_IN_CAS = Unknown JCas type used in Java code but was not declared or imported in the XML descriptor for this component. -JCAS_FIELD_MISSING_IN_TYPE_SYSTEM = JCAS class "{0}" defines a UIMA field "{1}" but the UIMA type doesn''t define that field. +JCAS_FIELD_MISSING_IN_TYPE_SYSTEM = JCAS class "{0}" defines a UIMA field "{1}" but the UIMA type does not define that field. JCAS_FIELD_ADJ_OFFSET_CHANGED = In JCAS class "{0}", UIMA field "{1}" was set up when this class was previously loaded and initialized, to have an adjusted offset of "{2}" but now the feature has a different adjusted offset of "{3}"; this may be due to something else other than type system commit actions loading and initializing the JCas class, or to having a different non-compatible type system for this class, trying to use a common JCas cover class, which is not supported. -JCAS_CAS_MISMATCH_SUPERTYPE = JCas Class's supertypes for "{0}", "{1}" and the corresponding UIMA Supertypes for "{2}", "{3}" don't have an intersection. +JCAS_CAS_MISMATCH_SUPERTYPE = JCas class supertypes for "{0}", "{1}" and the corresponding UIMA supertypes for "{2}", "{3}" do not have an intersection. JCAS_MISMATCH_SUPERTYPE = The JCas class: "{0}" has supertypes: "{1}" which do not match the UIMA type "{2}"''s supertypes "{3}". JCAS_TYPE_RANGE_MISMATCH = CAS type system type "{0}" defines field "{1}" with range "{2}", but JCas getter method is returning "{3}" which is not a subtype of the declared range. JCAS_GET_NTH_ON_EMPTY_LIST = JCas getNthElement method called via invalid object - an empty list: {0}. diff --git a/uimaj-core/src/test/java/org/apache/uima/cas/impl/TypeSystemImplTest.java b/uimaj-core/src/test/java/org/apache/uima/cas/impl/TypeSystemImplTest.java new file mode 100644 index 000000000..471379fd7 --- /dev/null +++ b/uimaj-core/src/test/java/org/apache/uima/cas/impl/TypeSystemImplTest.java @@ -0,0 +1,99 @@ +/* + * 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.cas.impl; + +import static org.apache.uima.UIMAFramework.getResourceSpecifierFactory; +import static org.apache.uima.util.CasCreationUtils.createCas; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatNoException; +import static org.assertj.core.api.InstanceOfAssertFactories.throwable; + +import java.util.Iterator; + +import org.apache.uima.cas.CAS; +import org.apache.uima.cas.CASRuntimeException; +import org.apache.uima.jcas.JCas; +import org.apache.uima.jcas.JCasRegistry; +import org.apache.uima.jcas.tcas.Annotation; +import org.apache.uima.resource.metadata.TypeSystemDescription; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import x.y.z.Sentence; + +public class TypeSystemImplTest { + private TypeSystemDescription tsd; + + @BeforeEach + public void setup() { + tsd = getResourceSpecifierFactory().createTypeSystemDescription(); + } + + @Test + public void thatTypeUsedInJavaAndDeclaredInTypeSytemDoesNotThrowException() throws Exception { + tsd.addType(Sentence._TypeName, "", CAS.TYPE_NAME_ANNOTATION); + + JCas localJcas = createCas(tsd, null, null).getJCas(); + localJcas.setDocumentText("This is a test."); + + assertThatNoException() // + .isThrownBy(() -> localJcas.getCasType(Sentence.type)); + } + + @Test + public void thatTypeUsedInJavaButNotDeclaredInTypeSytemThrowsException() throws Exception { + JCas localJcas = createCas(tsd, null, null).getJCas(); + localJcas.setDocumentText("This is a test."); + + assertThat(JCasRegistry.getClassForIndex(Sentence.type)).isSameAs(Sentence.class); + + assertThatExceptionOfType(CASRuntimeException.class) // + .isThrownBy(() -> localJcas.getCasType(Sentence.type)) // + .asInstanceOf(throwable(CASRuntimeException.class)) // + .extracting(CASRuntimeException::getMessageKey) // + .isEqualTo(CASRuntimeException.JCAS_TYPE_NOT_IN_CAS); + + sanityCheckForCasConsistencyUIMA_738(localJcas); + } + + @Test + public void thatTypeNotInTypeSystemAndWithoutJCasClassThrowsException() throws Exception { + JCas localJcas = createCas(tsd, null, null).getJCas(); + localJcas.setDocumentText("This is a test."); + + assertThatExceptionOfType(CASRuntimeException.class) // + .isThrownBy(() -> localJcas.getCasType(Integer.MAX_VALUE)) // + .asInstanceOf(throwable(CASRuntimeException.class)) // + .extracting(CASRuntimeException::getMessageKey) // + .isEqualTo(CASRuntimeException.JCAS_UNKNOWN_TYPE_NOT_IN_CAS); + + sanityCheckForCasConsistencyUIMA_738(localJcas); + } + + private void sanityCheckForCasConsistencyUIMA_738(JCas localJcas) { + // check that this does not leave JCAS in an inconsistent state + // (a check for bug UIMA-738) + Iterator<Annotation> iter = localJcas.getAnnotationIndex().iterator(); + assertThat(iter).hasNext(); + assertThat(iter.next()) // + .extracting(Annotation::getCoveredText) // + .isEqualTo("This is a test."); + } +} diff --git a/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasTest.java b/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasTest.java index 359c51c58..78bec197e 100644 --- a/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasTest.java +++ b/uimaj-core/src/test/java/org/apache/uima/jcas/test/JCasTest.java @@ -19,10 +19,6 @@ package org.apache.uima.jcas.test; -import static org.apache.uima.util.CasCreationUtils.createCas; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.InstanceOfAssertFactories.throwable; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @@ -71,7 +67,6 @@ import org.apache.uima.jcas.cas.StringArray; import org.apache.uima.jcas.cas.StringList; import org.apache.uima.jcas.cas.TOP; import org.apache.uima.jcas.tcas.Annotation; -import org.apache.uima.resource.metadata.impl.TypeSystemDescription_impl; import org.apache.uima.test.junit_extension.JUnitExtension; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.AfterEach; @@ -81,7 +76,6 @@ import org.junit.jupiter.api.Test; import aa.ConcreteType; import aa.Root; import x.y.z.EndOfSentence; -import x.y.z.Sentence; import x.y.z.Token; /** @@ -996,28 +990,6 @@ public class JCasTest { for (double v : doa) { Assertions.assertThat(expectedDoa[i++]).isEqualTo(v); } - - } - - @Test - public void testUndefinedType() throws Exception { - // create jcas with no type system - JCas localJcas = createCas(new TypeSystemDescription_impl(), null, null).getJCas(); - localJcas.setDocumentText("This is a test."); - - assertThatExceptionOfType(CASRuntimeException.class) // - .isThrownBy(() -> localJcas.getCasType(Sentence.type)) // - .asInstanceOf(throwable(CASRuntimeException.class)) // - .extracting(CASRuntimeException::getMessageKey) // - .isEqualTo(CASRuntimeException.JCAS_TYPE_NOT_IN_CAS_REGISTRY); - - // check that this does not leave JCAS in an inconsistent state - // (a check for bug UIMA-738) - Iterator<Annotation> iter = localJcas.getAnnotationIndex().iterator(); - assertThat(iter).hasNext(); - assertThat(iter.next()) // - .extracting(Annotation::getCoveredText) // - .isEqualTo("This is a test."); } /*