Author: schor
Date: Mon Nov  2 16:36:37 2015
New Revision: 1712071

URL: http://svn.apache.org/viewvc?rev=1712071&view=rev
Log:
[UIMA-4679] give messages for missing setters/ getters (except Sofa setters).

Modified:
    
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java

Modified: 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
URL: 
http://svn.apache.org/viewvc/uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java?rev=1712071&r1=1712070&r2=1712071&view=diff
==============================================================================
--- 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
 (original)
+++ 
uima/uimaj/branches/experiment-v3-jcas/uimaj-core/src/main/java/org/apache/uima/cas/impl/FSClassRegistry.java
 Mon Nov  2 16:36:37 2015
@@ -26,15 +26,16 @@ import java.lang.invoke.LambdaMetafactor
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
 import org.apache.uima.UIMARuntimeException;
 import org.apache.uima.cas.BuiltinTypeKinds;
 import org.apache.uima.cas.CAS;
+import org.apache.uima.cas.CASException;
 import org.apache.uima.cas.CASRuntimeException;
 import org.apache.uima.cas.Feature;
-import org.apache.uima.cas.FeatureStructure;
 import org.apache.uima.cas.function.JCas_getter_boolean;
 import org.apache.uima.cas.function.JCas_getter_byte;
 import org.apache.uima.cas.function.JCas_getter_double;
@@ -168,13 +169,14 @@ public class FSClassRegistry {
     TypeImpl ti = tsi.getType(CAS.TYPE_NAME_SOFA);
     jcasClassesInfoForBuiltins[ti.getCode()] = createJCasClassInfo(Sofa.class, 
ti); 
     
+    reportErrors();
   }
+
+  static private ThreadLocal<ArrayList<Exception>> errorSet = new 
ThreadLocal<ArrayList<Exception>>();
   
   // the loaded JCas cover classes, generators, setters, and getters.  index 
is typecode; value is JCas cover class which may belong to a supertype.
   private final JCasClassInfo[] jcasClassesInfo; 
-   
-  //  
-  // 
+
   /**
    * install the default (non-JCas) generator for all types in the type system 
and the
    * JCas style generators for the built-in types
@@ -210,6 +212,8 @@ public class FSClassRegistry {
     if (isDoUserJCasLoading) {
       maybeLoadJCasAndSubtypes(ts, ts.topType, 
jcasClassesInfo[TypeSystemImpl.topTypeCode]);
     }
+    
+    reportErrors();
   }
 
   private void maybeLoadJCasAndSubtypes(TypeSystemImpl ts, TypeImpl ti, 
JCasClassInfo copyDownDefault_jcasClassInfo) {
@@ -222,7 +226,7 @@ public class FSClassRegistry {
     if (!isBuiltin) {
       clazz = maybeLoadJCas(ti.getName(), ti.getClass().getClassLoader()); 
       if (null != clazz && TOP.class.isAssignableFrom(clazz)) {
-        jcasClassInfo = createJCasClassInfo(clazz, ti);
+        jcasClassInfo = createJCasClassInfo(clazz, ti);  // side effect - 
creates method handles for getters/setters
         ts.setJCasRegisteredType(Misc.getStaticIntField(clazz, "typeIndexID"), 
ti);
       }
       jcasClassesInfo[typecode] = jcasClassInfo;  // sets new one or default 
one
@@ -300,20 +304,20 @@ public class FSClassRegistry {
    *   boolean, byte, short, int, long, float, double, String, FeatureStructure
    *   
    */
+  // static for setting up builtin values
   private static Object createGetterOrSetter(Class<?> jcasClass, FeatureImpl 
fi, boolean isGetter) {
     
     TypeImpl range = fi.getRangeImpl();
     
     try {
       /* get an early-bound getter    
-      /* find special invokes a specific method in a specific class, without 
looking at the 
-       * runtime class */
+      /* Instead of findSpecial, we use findVirtual, in case the method is 
overridden by a subtype loaded later */
       MethodHandle mh = lookup.findVirtual(
           jcasClass,  // class having the method code for the getter 
           fi.getGetterSetterName(isGetter), // the name of the method for the 
getter 
           isGetter ? methodType(range.javaClass)
                    : methodType(void.class, range.javaClass) // return value, 
e.g. int.class, xyz.class, FeatureStructureImplC.class
-          );
+        );
       
       // getter methodtype is return_type, FeatureStructure.class
       //   return_type is int, byte, etc. primitive (except string/substring), 
or
@@ -359,15 +363,25 @@ public class FSClassRegistry {
         return isGetter ? (JCas_getter_double) 
callSite.getTarget().invokeExact() 
                         : (JCas_setter_double) 
callSite.getTarget().invokeExact();
       } else {
-        return isGetter ? (JCas_getter_generic) 
callSite.getTarget().invokeExact() 
-                        : (JCas_setter_generic) 
callSite.getTarget().invokeExact();
+        return isGetter ? (JCas_getter_generic<?>) 
callSite.getTarget().invokeExact() 
+                        : (JCas_setter_generic<?>) 
callSite.getTarget().invokeExact();
       }
     } catch (NoSuchMethodException e) {
+      if (jcasClass == Sofa.class && !isGetter) {return null;}  // this one 
case is ok, setters blocked for sofa
+      // report missing setter or getter
+      CASException casEx = new 
CASException(CASException.JCAS_FEATURENOTFOUND_ERROR, 
+          jcasClass.getName(), 
+          fi.getGetterSetterName(isGetter));
+      ArrayList<Exception> es = errorSet.get();
+      if (es == null) {
+        es = new ArrayList<Exception>();
+        errorSet.set(es);
+      }
+      es.add(casEx);
       return null;
     } catch (Throwable e) {
       throw new UIMARuntimeException(e, UIMARuntimeException.INTERNAL_ERROR);
     }
-
   }
  
   
@@ -383,7 +397,8 @@ public class FSClassRegistry {
     return jcasClassesInfo[typecode].jcasClass; 
   }
   
-  private static  JCasClassInfo createJCasClassInfo(Class<?> jcasClass, 
TypeImpl ti) {
+  // static for setting up static builtin values
+  private static JCasClassInfo createJCasClassInfo(Class<?> jcasClass, 
TypeImpl ti) {
     JCasClassInfo jcasClassInfo = new JCasClassInfo(jcasClass, 
ti.getName().equals(CAS.TYPE_NAME_SOFA) ? null : createGenerator(jcasClass, 
ti));
 
     for (FeatureImpl fi : ti.getMergedStaticFeaturesIntroducedByThisType()) {
@@ -409,7 +424,18 @@ public class FSClassRegistry {
     }    
   }
   
-  
+  static void reportErrors() {
+    ArrayList<Exception> es = errorSet.get();
+    if (es != null) {
+      StringBuilder msg = new StringBuilder(100);
+      for (Exception f : es) {
+        msg.append(f.getMessage());
+        msg.append('\n');
+      }
+      errorSet.set(null); // reset after reporting
+      throw new CASRuntimeException(CASException.JCAS_INIT_ERROR, msg);
+    }
+  }
   
 }
   
\ No newline at end of file


Reply via email to