You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by sc...@apache.org on 2010/11/22 16:15:15 UTC

svn commit: r1037752 - /uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/CasCopier.java

Author: schor
Date: Mon Nov 22 15:15:15 2010
New Revision: 1037752

URL: http://svn.apache.org/viewvc?rev=1037752&view=rev
Log: (empty)

Modified:
    uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/CasCopier.java

Modified: uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/CasCopier.java
URL: http://svn.apache.org/viewvc/uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/CasCopier.java?rev=1037752&r1=1037751&r2=1037752&view=diff
==============================================================================
--- uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/CasCopier.java (original)
+++ uima/uimaj/trunk/uimaj-core/src/main/java/org/apache/uima/util/CasCopier.java Mon Nov 22 15:15:15 2010
@@ -18,6 +18,7 @@
  */
 package org.apache.uima.util;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -59,6 +60,12 @@ public class CasCopier {
   private Feature mDestSofaFeature;
 
   private Map<FeatureStructure, FeatureStructure> mFsMap = new HashMap<FeatureStructure, FeatureStructure>();
+  
+  /**
+   * feature structures whose slots need copying are put on this list, together with their source
+   * List is operated as a stack, from the end, for efficiency
+   */
+  private ArrayList<FeatureStructure> fsToDo = new ArrayList<FeatureStructure>();
 
   /**
    * Creates a new CasCopier that can be used to copy FeatureStructures from one CAS to another.
@@ -160,6 +167,30 @@ public class CasCopier {
     }
   }
 
+  /**
+   * For long lists, and other structures, the straight-forward impl with recursion can
+   * nest too deep, causing a Java failure - out of stack space.
+   * 
+   * This is a non-recursive impl, making use of an aux object: featureStructuresWithSlotsToSet to
+   * hold copied FSs whose slots need to be scanned and set with values.
+   * 
+   * The main loop dequeues one element, and copies the features.
+   * 
+   * The copying of a FS copies the FS without setting the slots; instead it queues the
+   * copied FS together with its source instance on featureStructuresWithSlotsToSet 
+   * for later processing.
+   * 
+   */
+  
+  public FeatureStructure copyFs(FeatureStructure aFS) {
+    FeatureStructure copy = copyFsInner(aFS);  // doesn't copy the slot values, but enqueues them
+    while (!fsToDo.isEmpty()) {
+      FeatureStructure copyToFillSlots = fsToDo.remove(fsToDo.size()-1);
+      FeatureStructure srcToFillSlots = fsToDo.remove(fsToDo.size()-1);
+      copyFeatures(srcToFillSlots, copyToFillSlots);   
+    }
+    return copy;
+  }
 
   /**
    * Copies an FS from the source CAS to the destination CAS. Also copies any referenced FS, except
@@ -169,7 +200,7 @@ public class CasCopier {
    *          the FS to copy. Must be contained within the source CAS.
    * @return the copy of <code>aFS</code> in the target CAS.
    */
-  public FeatureStructure copyFs(FeatureStructure aFS) {
+  public FeatureStructure copyFsInner(FeatureStructure aFS) {
     //FS must be in the source CAS
     assert ((CASImpl)aFS.getCAS()).getBaseCAS() == ((CASImpl)mSrcCas).getBaseCAS();
 
@@ -232,10 +263,11 @@ public class CasCopier {
     // add to map so we don't try to copy this more than once
     mFsMap.put(aFS, destFs);
 
-    copyFeatures(aFS, destFs);
+    fsToDo.add(aFS);  // order important
+    fsToDo.add(destFs);
     return destFs;
   }
-
+  
   /**
    * Copy feature values from one FS to another. For reference-valued features, this does a deep
    * copy.
@@ -266,13 +298,20 @@ public class CasCopier {
       // copy primitive values using their string representation
       // TODO: could be optimized but this code would be very messy if we have to
       // enumerate all possible primitive types. Maybe LowLevel CAS API could help?
+      String srcRangeName = srcFeat.getRange().getName();
+      if (srcRangeName.equals(CAS.TYPE_NAME_STRING)) {
+        aDestFS.setStringValue(destFeat, aSrcFS.getStringValue(srcFeat));
+      } else
+      if (srcRangeName.equals(CAS.TYPE_NAME_INTEGER)) {
+        aDestFS.setIntValue(destFeat, aSrcFS.getIntValue(srcFeat));
+      } else
       if (srcFeat.getRange().isPrimitive()) {
         aDestFS.setFeatureValueFromString(destFeat, aSrcFS.getFeatureValueAsString(srcFeat));
       } else {
-        // recursive copy
+        // recursive copy no longer done recursively, to avoid blowing the stack
         FeatureStructure refFS = aSrcFS.getFeatureValue(srcFeat);
         if (refFS != null) {
-          FeatureStructure copyRefFs = copyFs(refFS);
+          FeatureStructure copyRefFs = copyFsInner(refFS);
           aDestFS.setFeatureValue(destFeat, copyRefFs);
         }
       }
@@ -372,7 +411,7 @@ public class CasCopier {
       for (int i = 0; i < len; i++) {
         FeatureStructure srcElem = arrayFs.get(i);
         if (srcElem != null) {
-          FeatureStructure copyElem = copyFs(arrayFs.get(i));
+          FeatureStructure copyElem = copyFsInner(arrayFs.get(i));
           destFS.set(i, copyElem);
         }
       }