如何使用Java API获取CLIPS事实的字段数据?

How to get the field data of a CLIPS fact using the Java API?

假设我有一些 plain CLIPS 事实(无插槽):

(deffacts happyFacts
(happy Peter)
(happy Alex)
(happy Mary))

使用 Java API (CLIPSJNI),我可以按如下方式检索这些事实:

MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?f happy)) TRUE)");

然后我可以检索第一个单独的事实如下:

FactAddressValue fact = (FactAddressValue) mv.multifieldValue().get(0);

如果那个事实有命名插槽,我就可以按如下方式获得字段数据:

fact.getFactSlot("someSlot")

但它没有插槽;那么,如何检索它的字段值(在本例中,Peter)?

对于 CLIPSJNI 0.5,修改 net_sf_cilpsrules_jni_Environment.c 中的 Java_net_sf_clipsrules_jni_Environment_getFactSlot 以允许将空值作为插槽名称传递:

JNIEXPORT jobject JNICALL Java_net_sf_clipsrules_jni_Environment_getFactSlot(
  JNIEnv *env,
  jclass javaClass, 
  jobject javaEnv,
  jlong clipsEnv,
  jlong clipsFact,
  jstring slotName)
  {
   jobject rv;
   DATA_OBJECT theDO;
   void *theCLIPSEnv = JLongToPointer(clipsEnv);
   const char *cSlotName = NULL;

   if (slotName != NULL)
     { cSlotName = (*env)->GetStringUTFChars(env,slotName,NULL); }

   void *oldContext = SetEnvironmentContext(theCLIPSEnv,(void *) env);

   EnvGetFactSlot(JLongToPointer(clipsEnv),JLongToPointer(clipsFact),(char *) cSlotName,&theDO);

   if (slotName != NULL)
     { (*env)->ReleaseStringUTFChars(env,slotName,cSlotName); }

   rv = ConvertDataObject(env,javaEnv,theCLIPSEnv,&theDO);

   SetEnvironmentContext(JLongToPointer(clipsEnv),oldContext);

   return rv;
  }

然后您可以将空值传递给 return 隐含插槽:

   public static void main(String args[])
     {  
      Environment clips;

      clips = new Environment();
            clips.build("(deffacts happyFacts " +
                  "  (happy Peter)" +
                  "  (happy Alex)" +
                  "  (happy Mary))");

      clips.reset();            

      clips.eval("(facts)");
      MultifieldValue mv = (MultifieldValue) clips.eval("(find-all-facts ((?f happy)) TRUE)");
      FactAddressValue fact = (FactAddressValue) mv.multifieldValue().get(0);

      try
        {
         System.out.println("Slot value is " + fact.getFactSlot(null));
        }
      catch (Exception e)
        {
         e.printStackTrace();
        }
     }