blob: 59550b3bb79894146306fa856b1fef14d6e22846 [file] [log] [blame]
/*
* 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 java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.uima.UIMAFramework;
import org.apache.uima.UIMARuntimeException;
import org.apache.uima.cas.AbstractCas_ImplBase;
import org.apache.uima.cas.ArrayFS;
import org.apache.uima.cas.BooleanArrayFS;
import org.apache.uima.cas.ByteArrayFS;
import org.apache.uima.cas.CAS;
import org.apache.uima.cas.CASException;
import org.apache.uima.cas.CASRuntimeException;
import org.apache.uima.cas.CasOwner;
import org.apache.uima.cas.ComponentInfo;
import org.apache.uima.cas.ConstraintFactory;
import org.apache.uima.cas.DoubleArrayFS;
import org.apache.uima.cas.FSIndex;
import org.apache.uima.cas.FSIndexRepository;
import org.apache.uima.cas.FSIterator;
import org.apache.uima.cas.FSMatchConstraint;
import org.apache.uima.cas.Feature;
import org.apache.uima.cas.FeaturePath;
import org.apache.uima.cas.FeatureStructure;
import org.apache.uima.cas.FeatureValuePath;
import org.apache.uima.cas.FloatArrayFS;
import org.apache.uima.cas.IntArrayFS;
import org.apache.uima.cas.LongArrayFS;
import org.apache.uima.cas.Marker;
import org.apache.uima.cas.SerialFormat;
import org.apache.uima.cas.ShortArrayFS;
import org.apache.uima.cas.SofaFS;
import org.apache.uima.cas.SofaID;
import org.apache.uima.cas.StringArrayFS;
import org.apache.uima.cas.Type;
import org.apache.uima.cas.TypeSystem;
import org.apache.uima.cas.admin.CASAdminException;
import org.apache.uima.cas.admin.CASFactory;
import org.apache.uima.cas.admin.CASMgr;
import org.apache.uima.cas.admin.FSIndexComparator;
import org.apache.uima.cas.admin.FSIndexRepositoryMgr;
import org.apache.uima.cas.admin.TypeSystemMgr;
import org.apache.uima.cas.impl.CommonSerDes.Header;
import org.apache.uima.cas.impl.CommonSerDes.Reading;
import org.apache.uima.cas.impl.FSsTobeAddedback.FSsTobeAddedbackSingle;
import org.apache.uima.cas.text.AnnotationFS;
import org.apache.uima.cas.text.AnnotationIndex;
import org.apache.uima.cas.text.Language;
import org.apache.uima.internal.util.IntVector;
import org.apache.uima.internal.util.MiscImpl;
import org.apache.uima.internal.util.PositiveIntSet_impl;
import org.apache.uima.jcas.JCas;
import org.apache.uima.jcas.impl.JCasImpl;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.util.Level;
import org.apache.uima.util.Misc;
/**
* Implements the CAS interfaces. This class must be public because we need to
* be able to create instance of it from outside the package. Use at your own
* risk. May change without notice.
*
*/
public class CASImpl extends AbstractCas_ImplBase implements CAS, CASMgr, LowLevelCAS {
private static final boolean trace = false;
public static final boolean traceFSs = false; // debug - trace FS creation and update
private static final String traceFile = "traceFSs.log.txt";
private static final PrintStream traceOut;
static {
try {
if (traceFSs) {
System.out.println("Creating traceFSs file in directory " + System.getProperty("user.dir"));
traceOut = traceFSs ? new PrintStream(new BufferedOutputStream(new FileOutputStream(traceFile, false))) : null;
} else {
traceOut = null;
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// debug
private static final AtomicInteger casIdProvider = new AtomicInteger(0);
// Notes on the implementation
// ---------------------------
// Floats are handled by casting them to ints when they are stored
// in the heap. Conveniently, 0 casts to 0.0f, which is the default
// value.
public static final int NULL = 0;
// Boolean scalar values are stored as ints in the fs heap.
// TRUE is 1 and false is 0.
public static final int TRUE = 1;
public static final int FALSE = 0;
private static final int[] INT0 = new int[0];
public static final int DEFAULT_INITIAL_HEAP_SIZE = 500000;
public static final int DEFAULT_RESET_HEAP_SIZE = 5000000;
// no longer used 3/2015
// private static final int resetHeapSize = DEFAULT_RESET_HEAP_SIZE;
/**
* The UIMA framework detects (unless disabled, for high performance) updates to indexed FS which update
* key values used as keys in indexes. Normally the framework will protect against index corruption by
* temporarily removing the FS from the indexes, then do the update to the feature value, and then addback
* the changed FS.
* <p>
* Users can use the protectIndexes() methods to explicitly control this remove - add back cycle, for instance
* to "batch" together several updates to multiple features in a FS.
* <p>
* Some build processes may want to FAIL if any unprotected updates of this kind occur, instead of having the
* framework silently recover them. This is enabled by having the framework throw an exception; this is controlled
* by this global JVM property, which, if defined, causes the framework to throw an exception rather than recover.
*
*/
public static final String THROW_EXCEPTION_FS_UPDATES_CORRUPTS = "uima.exception_when_fs_update_corrupts_index";
// public for test case use
public static final boolean IS_THROW_EXCEPTION_CORRUPT_INDEX = Misc.getNoValueSystemProperty(THROW_EXCEPTION_FS_UPDATES_CORRUPTS);
/**
* Define this JVM property to enable checking for invalid updates to features which are used as
* keys by any index.
* <ul>
* <li>The following are the same: -Duima.check_invalid_fs_updates and -Duima.check_invalid_fs_updates=true</li>
* </ul>
*/
public static final String REPORT_FS_UPDATES_CORRUPTS = "uima.report_fs_update_corrupts_index";
private static final boolean IS_REPORT_FS_UPDATE_CORRUPTS_INDEX =
IS_THROW_EXCEPTION_CORRUPT_INDEX || Misc.getNoValueSystemProperty(REPORT_FS_UPDATES_CORRUPTS);
/**
* Set this JVM property to false for high performance, (no checking);
* insure you don't have the report flag (above) turned on - otherwise it will force this to "true".
*/
public static final String DISABLE_PROTECT_INDEXES = "uima.disable_auto_protect_indexes";
/**
* the protect indexes flag is on by default, but may be turned of via setting the property.
*
* This is overridden if a report is requested or the exception detection is on.
*/
private static final boolean IS_DISABLED_PROTECT_INDEXES =
Misc.getNoValueSystemProperty(DISABLE_PROTECT_INDEXES) &&
!IS_REPORT_FS_UPDATE_CORRUPTS_INDEX &&
!IS_THROW_EXCEPTION_CORRUPT_INDEX;
// The offset for the array length cell. An array consists of length+2
// number
// of cells, where the first cell contains the type, the second one the
// length,
// and the rest the actual content of the array.
private static final int arrayLengthFeatOffset = 1;
// The number of cells we need to skip to get to the array contents. That
// is,
// if we have an array starting at addr, the first cell is at
// addr+arrayContentOffset.
private static final int arrayContentOffset = 2;
private static final boolean DEFAULT_USE_FS_CACHE = false;
// this next seemingly non-sensical static block
// is to force the classes needed by Eclipse debugging to load
// otherwise, you get a com.sun.jdi.ClassNotLoadedException when
// the class is used as part of formatting debugging messages
static {
new DebugNameValuePair(null, null);
new DebugFSLogicalStructure();
}
private static enum ModifiedHeap { FSHEAP, BYTEHEAP, SHORTHEAP, LONGHEAP };
// Static classes representing shared instance data
// - shared data is computed once for all views
// fields shared among all CASes belong to views of a common base CAS
private static class SharedViewData {
final private Heap heap;
// private SymbolTable stringTable;
// private ArrayList stringList;
final private StringHeap stringHeap = new StringHeap();
final private ByteHeap byteHeap = new ByteHeap(); // for storing 8 bit values
final private ShortHeap shortHeap = new ShortHeap(); // for storing 16 bit values
final private LongHeap longHeap = new LongHeap(); // for storing 64 bit values
// for efficiency in accessing the begin and end offsets of annotations
private int annotFeatOffset_begin;
private int annotFeatOffset_end;
// Base CAS for all views
final private CASImpl baseCAS;
private int cache_not_in_index = 0; // a one item cache of a FS not in the index
private final PositiveIntSet_impl featureCodesInIndexKeys = new PositiveIntSet_impl();
// A map from Sofas to IndexRepositories.
private Map<Integer, FSIndexRepository> sofa2indexMap;
// A map from Sofa numbers to CAS views.
// number 0 - not used
// number 1 - used for view named "_InitialView"
// number 2-n used for other views
// private Map<Integer, CAS> sofaNbr2ViewMap;
private ArrayList<CAS> sofaNbr2ViewMap;
// set of instantiated sofaNames
private Set<String> sofaNameSet;
// Flag that initial Sofa has been created
private boolean initialSofaCreated = false;
// Count of Views created in this cas
// equals count of sofas except if initial view has no sofa.
private int viewCount;
// The ClassLoader that should be used by the JCas to load the generated
// FS cover classes for this CAS. Defaults to the ClassLoader used
// to load the CASImpl class.
private ClassLoader jcasClassLoader = this.getClass().getClassLoader();
private ClassLoader previousJCasClassLoader = this.jcasClassLoader;
// If this CAS can be flushed (reset) or not.
// often, the framework disables this before calling users code
private boolean flushEnabled = true;
// controls whether Java cover objects for CAS objects,
// including JCas objects,
// are cached and reused.
// If set true, don't also cache the JCas ones - this will
// duplicate the space with no benefit
private final boolean useFSCache;
// this is the actual cache. It is simply an array of the same size
// as the heap, with the CAS object's addr slot filled with
// a (strong) ref to the Java object.
// This is a trade off verses using hash tables
// The actual cache.
// TODO implement the resizing algorithm used for the main heap, here too.
private FeatureStructure[] fsArray;
// not final because set with reinit deserialization
private CASMetadata casMetadata;
private ComponentInfo componentInfo;
private FSGenerator<? extends FeatureStructure>[] localFsGenerators;
/**
* This tracks the changes for delta cas
* May also in the future support Journaling by component,
* allowing determination of which component in a flow
* created/updated a FeatureStructure (not implmented)
*
* TrackingMarkers are held on to by things outside of the
* Cas, to support switching from one tracking marker to
* another (currently not used, but designed to support
* Component Journaling).
*/
private MarkerImpl trackingMark;
private IntVector modifiedPreexistingFSs;
private IntVector modifiedFSHeapCells;
private IntVector modifiedByteHeapCells;
private IntVector modifiedShortHeapCells;
private IntVector modifiedLongHeapCells;
/**
* This list currently only contains at most 1 element.
* If Journaling is implemented, it may contain an
* element per component being journaled.
*/
private List<MarkerImpl> trackingMarkList;
/**
* This stack corresponds to nested protectIndexes contexts. Normally should be very shallow.
*/
private final ArrayList<FSsTobeAddedback> fssTobeAddedback = new ArrayList<FSsTobeAddedback>();
/**
* This version is for single fs use, by binary deserializers and by automatic mode
* Only one user at a time is allowed.
*/
private final FSsTobeAddedbackSingle fsTobeAddedbackSingle = (FSsTobeAddedbackSingle) FSsTobeAddedback.createSingle();
/**
* Set to true while this is in use.
*/
private boolean fsTobeAddedbackSingleInUse = false;
private final AtomicInteger casResets = new AtomicInteger(0);
private final int casId;
private final StringBuilder traceFScreationSb = traceFSs ? new StringBuilder() : null;
private int traceFSid = 0;
private boolean traceFSisCreate;
private SharedViewData(boolean useFSCache, Heap heap, CASImpl baseCAS, CASMetadata casMetadata) {
this.useFSCache = useFSCache;
this.heap = heap;
this.baseCAS = baseCAS;
this.casMetadata = casMetadata;
casId = casIdProvider.incrementAndGet();
}
}
// -----------------------------------------------------
// Non-shared instance data for base CAS and each view
// -----------------------------------------------------
// package protected to let other things share this info
final SharedViewData svd; // shared view data
void addbackSingle(int fsAddr) {
svd.fsTobeAddedbackSingle.addback(fsAddr);
svd.fsTobeAddedbackSingleInUse = false;
// System.out.format("debug return (addbackSingle) add back single for cas %s%n", this.getViewName());
}
void resetAddbackSingleInUse() {
// System.out.format("debug return (reset) add back single for cas %s%n", this.getViewName());
svd.fsTobeAddedbackSingleInUse = false;
}
FSsTobeAddedbackSingle getAddbackSingle() {
if (svd.fsTobeAddedbackSingleInUse) {
throw new RuntimeException(); // internal error
}
// System.out.format("debug checkout add back single for cas %s%n", this.getViewName());
svd.fsTobeAddedbackSingleInUse = true;
return svd.fsTobeAddedbackSingle;
}
void featureCodesInIndexKeysAdd(int featCode) {
svd.featureCodesInIndexKeys.add(featCode);
}
void maybeClearCacheNotInIndex(int fsAddr) {
if (svd.cache_not_in_index == fsAddr) {
svd.cache_not_in_index = 0;
}
}
/**
* Called by feature setters which know the FS is not in any index
* to bypass any index corruption checking, e.g., CasCopier
*
* Internal use only
* @param fsAddr the address of the feature structure
*/
public void setCacheNotInIndex(int fsAddr) {
svd.cache_not_in_index = fsAddr;
}
// The index repository. Referenced by XmiCasSerializer
FSIndexRepositoryImpl indexRepository;
// the sofaFS this view is based on
// SofaFS mySofa;
/**
* The heap address of the sofa FS for this view, or
* -1 if the sofa FS is for the initial view, or
* 0 if there is no sofa FS - for instance, in the "base cas"
*/
private int mySofaRef = 0;
private JCas jcas = null;
private final boolean isUsedJcasCache;
private final ArrayList<String> getStringList() {
ArrayList<String> stringList = new ArrayList<String>();
stringList.add(null);
int pos = this.getStringHeap().getLeastStringCode();
final int end = this.getStringHeap().getLargestStringCode();
while (pos <= end) {
stringList.add(this.getStringHeap().getStringForCode(pos));
++pos;
}
return stringList;
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.admin.CASMgr#setCAS(org.apache.uima.cas.CAS)
* Internal use Never called Kept because it's in the interface.
*/
public void setCAS(CAS cas) {
// this.indexRepository = ((CASImpl)cas).indexRepository; // only for test
// case, others override later
// this.svd.casMetadata.fsClassRegistry = casImpl.fsClassReg;
// initTypeCodeVars();
// this.jcas = in.jcas;
}
// CASImpl(TypeSystemImpl typeSystem) {
// this(typeSystem, DEFAULT_INITIAL_HEAP_SIZE);
// }
// // Reference existing CAS
// // For use when creating views of the CAS
// CASImpl(CAS cas) {
// this.setCAS(cas);
// this.useFSCache = false;
// initTypeVariables();
// }
public CASImpl(TypeSystemImpl typeSystem, int initialHeapSize, boolean useJcasCache) {
this(typeSystem, initialHeapSize, DEFAULT_USE_FS_CACHE, useJcasCache);
}
/*
* Configure a new (base view) CASImpl, **not a new view** typeSystem can be
* null, in which case a new instance of TypeSystemImpl is set up, but not
* committed. If typeSystem is not null, it is committed (locked). ** Note: it
* is assumed that the caller of this will always set up the initial view **
* by calling
*/
CASImpl(TypeSystemImpl typeSystem, int initialHeapSize, boolean useFSCache, boolean useJcasCache) {
super();
this.isUsedJcasCache = useJcasCache;
TypeSystemImpl ts;
final boolean externalTypeSystem = (typeSystem != null);
if (externalTypeSystem) {
ts = typeSystem;
} else {
ts = new TypeSystemImpl(); // creates also new CASMetadata and
// FSClassRegistry instances
}
this.svd = new SharedViewData(useFSCache, new Heap(initialHeapSize), this, ts.casMetadata);
// this.svd.baseCAS = this;
// this.svd.heap = new Heap(initialHeapSize);
if (externalTypeSystem) {
commitTypeSystem();
}
this.svd.sofa2indexMap = new HashMap<Integer, FSIndexRepository>();
this.svd.sofaNbr2ViewMap = new ArrayList<CAS>();
this.svd.sofaNameSet = new HashSet<String>();
this.svd.initialSofaCreated = false;
this.svd.viewCount = 0;
clearTrackingMarks();
}
/**
* Constructor. Use only if you want to use the low-level APIs.
*/
public CASImpl() {
this(DEFAULT_INITIAL_HEAP_SIZE, CASFactory.USE_JCAS_CACHE_DEFAULT);
}
public CASImpl(int initialHeapSize, boolean useJcasCache) {
this((TypeSystemImpl) null, initialHeapSize, useJcasCache);
}
// In May 2007, appears to have 1 caller, createCASMgr in Serialization class,
// could have
// out-side the framework callers because it is public.
public CASImpl(CASMgrSerializer ser) {
this(ser.getTypeSystem(), DEFAULT_INITIAL_HEAP_SIZE, CASFactory.USE_JCAS_CACHE_DEFAULT);
checkInternalCodes(ser);
// assert(ts != null);
// assert(getTypeSystem() != null);
this.indexRepository = ser.getIndexRepository(this);
}
// Use this when creating a CAS view
CASImpl(CASImpl cas, SofaFS aSofa, boolean useJcasCache) {
this.isUsedJcasCache = useJcasCache;
// these next fields are final and must be set in the constructor
this.svd = cas.svd;
// this.mySofa = aSofa;
if (aSofa != null) {
// save address of SofaFS
this.mySofaRef = ((FeatureStructureImpl) aSofa).getAddress();
} else {
// this is the InitialView
this.mySofaRef = -1;
}
// get the indexRepository for this Sofa
this.indexRepository = (this.mySofaRef == -1) ?
(FSIndexRepositoryImpl) cas.getSofaIndexRepository(1) :
(FSIndexRepositoryImpl) cas.getSofaIndexRepository(aSofa);
if (null == this.indexRepository) {
// create the indexRepository for this CAS
// use the baseIR to create a lightweight IR copy
this.indexRepository = new FSIndexRepositoryImpl(
this,
(FSIndexRepositoryImpl) cas.getBaseIndexRepository());
this.indexRepository.commit();
// save new sofa index
if (this.mySofaRef == -1) {
cas.setSofaIndexRepository(1, this.indexRepository);
} else {
cas.setSofaIndexRepository(aSofa, this.indexRepository);
}
}
}
// Use this when creating a CAS view
void refreshView(CAS cas, SofaFS aSofa) {
if (aSofa != null) {
// save address of SofaFS
this.mySofaRef = ((FeatureStructureImpl) aSofa).getAddress();
} else {
// this is the InitialView
this.mySofaRef = -1;
}
// toss the JCas, if it exists
this.jcas = null;
// create the indexRepository for this Sofa
this.indexRepository = new FSIndexRepositoryImpl(this, (FSIndexRepositoryImpl) ((CASImpl) cas)
.getBaseIndexRepository());
this.indexRepository.commit();
// save new sofa index
if (this.mySofaRef == -1) {
((CASImpl) cas).setSofaIndexRepository(1, this.indexRepository);
} else {
((CASImpl) cas).setSofaIndexRepository(aSofa, this.indexRepository);
}
}
private void checkInternalCodes(CASMgrSerializer ser) throws CASAdminException {
if ((ser.topTypeCode > 0)
&& (ser.topTypeCode != ((TypeImpl) this.svd.casMetadata.ts.getTopType()).getCode())) {
throw new CASAdminException(CASAdminException.DESERIALIZATION_ERROR);
}
if (ser.featureOffsets == null) {
return;
}
if (ser.featureOffsets.length != this.svd.casMetadata.featureOffset.length) {
throw new CASAdminException(CASAdminException.DESERIALIZATION_ERROR);
}
for (int i = 1; i < ser.featureOffsets.length; i++) {
if (ser.featureOffsets[i] != this.svd.casMetadata.featureOffset[i]) {
throw new CASAdminException(CASAdminException.DESERIALIZATION_ERROR);
}
}
}
public void enableReset(boolean flag) {
this.svd.flushEnabled = flag;
}
public TypeSystem getTypeSystem() {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
if (ts.isCommitted()) {
return ts;
}
throw new CASRuntimeException(CASRuntimeException.TYPESYSTEM_NOT_LOCKED);
}
public ConstraintFactory getConstraintFactory() {
return ConstraintFactory.instance();
}
public <T extends FeatureStructure> T createFS(Type type) {
final int typeCode = ((TypeImpl) type).getCode();
if (!isCreatableType(typeCode)) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.NON_CREATABLE_TYPE,
new String[] { type.getName(), "CAS.createFS()" });
throw e;
}
return ll_getFSForRef(ll_createFSAnnotCheck(typeCode));
}
public int ll_createFSAnnotCheck(int typeCode) {
final int addr = ll_createFS(typeCode);
final TypeSystemImpl ts = this.svd.casMetadata.ts;
final boolean isAnnot = ts.subsumes(TypeSystemImpl.annotBaseTypeCode, typeCode);
if (isAnnot && (this == this.getBaseCAS())) {
CASRuntimeException e = new CASRuntimeException(
CASRuntimeException.DISALLOW_CREATE_ANNOTATION_IN_BASE_CAS,
new String[] { ts.ll_getTypeForCode(typeCode).getName() });
throw e;
}
if (isAnnot) {
this.setFeatureValueNotJournaled(addr, TypeSystemImpl.annotSofaFeatCode, this.getSofaRef());
}
return addr;
}
// public FeatureStructure createPermFS(Type type) {
// final int addr = createPermFS(((TypeImpl) type).getCode());
// return getFSClassRegistry().createFS(addr, this);
// }
public ArrayFS createArrayFS(int length) {
checkArrayPreconditions(length);
final int addr = createTempArray(TypeSystemImpl.fsArrayTypeCode, length);
return (ArrayFS) createFS(addr);
}
public IntArrayFS createIntArrayFS(int length) {
checkArrayPreconditions(length);
final int addr = createTempArray(TypeSystemImpl.intArrayTypeCode, length);
return (IntArrayFS) createFS(addr);
}
public FloatArrayFS createFloatArrayFS(int length) {
checkArrayPreconditions(length);
final int addr = createTempArray(TypeSystemImpl.floatArrayTypeCode, length);
return (FloatArrayFS) createFS(addr);
}
public StringArrayFS createStringArrayFS(int length) {
checkArrayPreconditions(length);
final int addr = createTempArray(TypeSystemImpl.stringArrayTypeCode, length);
return (StringArrayFS) createFS(addr);
}
public final void checkArrayPreconditions(int len) throws CASRuntimeException {
// Check array size.
if (len < 0) {
throw new CASRuntimeException(CASRuntimeException.ILLEGAL_ARRAY_SIZE);
}
}
// return true if only one sofa and it is the default text sofa
public boolean isBackwardCompatibleCas() {
// check that there is exactly one sofa
if (this.svd.viewCount != 1) {
return false;
}
if (!this.svd.initialSofaCreated) {
return false;
}
final int llsofa = this.getInitialView().getLowLevelCAS().ll_getSofa();
// check for mime type exactly equal to "text"
String sofaMime = ll_getStringValue(llsofa, TypeSystemImpl.sofaMimeFeatCode);
if (!"text".equals(sofaMime)) {
return false;
}
// check that sofaURI and sofaArray are not set
String sofaUri = ll_getStringValue(llsofa, TypeSystemImpl.sofaUriFeatCode);
if (sofaUri != null) {
return false;
}
int sofaArray = ll_getRefValue(llsofa, TypeSystemImpl.sofaArrayFeatCode);
if (sofaArray != CASImpl.NULL) {
return false;
}
// check that name is NAME_DEFAULT_SOFA
String sofaname = ll_getStringValue(llsofa, TypeSystemImpl.sofaIdFeatCode);
return NAME_DEFAULT_SOFA.equals(sofaname);
}
int getBaseSofaCount() {
return this.svd.viewCount;
}
FSIndexRepository getSofaIndexRepository(SofaFS aSofa) {
return getSofaIndexRepository(aSofa.getSofaRef());
}
FSIndexRepository getSofaIndexRepository(int aSofaRef) {
return this.svd.sofa2indexMap.get(aSofaRef);
}
void setSofaIndexRepository(SofaFS aSofa, FSIndexRepository indxRepos) {
setSofaIndexRepository(aSofa.getSofaRef(), indxRepos);
}
void setSofaIndexRepository(int aSofaRef, FSIndexRepository indxRepos) {
this.svd.sofa2indexMap.put(Integer.valueOf(aSofaRef), indxRepos);
}
/**
* @deprecated
*/
@Deprecated
public SofaFS createSofa(SofaID sofaID, String mimeType) {
// extract absolute SofaName string from the ID
SofaFS aSofa = createSofa(sofaID.getSofaID(), mimeType);
getView(aSofa); // will create the view, needed to make the
// resetNoQuestions and other things that
// iterate over views work.
return aSofa;
}
SofaFS createSofa(String sofaName, String mimeType) {
final int addr = ll_createFS(TypeSystemImpl.sofaTypeCode);
final FeatureStructure sofa = ll_getFSForRef(addr);
addSofa(sofa, sofaName, mimeType);
return (SofaFS) sofa;
}
SofaFS createInitialSofa(String mimeType) {
final int addr = ll_createFS(TypeSystemImpl.sofaTypeCode);
final FeatureStructure sofa = ll_getFSForRef(addr);
// final int llsofa = ll_getFSRef(sofa);
ll_setIntValue(/* llsofa */addr, TypeSystemImpl.sofaNumFeatCode, 1);
addSofa(sofa, CAS.NAME_DEFAULT_SOFA, mimeType);
registerInitialSofa();
this.mySofaRef = /* ((FeatureStructureImpl)sofa).getAddress() */addr;
return (SofaFS) sofa;
}
void registerInitialSofa() {
this.svd.initialSofaCreated = true;
}
boolean isInitialSofaCreated() {
return this.svd.initialSofaCreated;
}
// Internal use only
public void addSofa(FeatureStructure sofa, String sofaName, String mimeType) {
if (this.svd.sofaNameSet.contains(sofaName)) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.SOFANAME_ALREADY_EXISTS,
new String[] { sofaName });
throw e;
}
final int llsofa = ll_getFSRef(sofa);
if (0 == ll_getIntValue(llsofa, TypeSystemImpl.sofaNumFeatCode)) {
ll_setIntValue(llsofa, TypeSystemImpl.sofaNumFeatCode, ++this.svd.viewCount);
}
ll_setStringValue(llsofa, TypeSystemImpl.sofaIdFeatCode, sofaName);
ll_setStringValue(llsofa, TypeSystemImpl.sofaMimeFeatCode, mimeType);
this.getBaseIndexRepository().addFS(sofa);
this.svd.sofaNameSet.add(sofaName);
}
/**
* @deprecated
*/
@Deprecated
public SofaFS getSofa(SofaID sofaID) {
// extract absolute SofaName string from the ID
return getSofa(sofaID.getSofaID());
}
private SofaFS getSofa(String sofaName) {
FSIterator<SofaFS> iterator = this.svd.baseCAS.getSofaIterator();
while (iterator.isValid()) {
SofaFS sofa = iterator.get();
if (sofaName.equals(getStringValue(((FeatureStructureImpl) sofa).getAddress(),
TypeSystemImpl.sofaIdFeatCode))) {
return sofa;
}
iterator.moveToNext();
}
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.SOFANAME_NOT_FOUND,
new String[] { sofaName });
throw e;
}
SofaFS getSofa(int sofaRef) {
SofaFS aSofa = (SofaFS) this.ll_getFSForRef(sofaRef);
if (aSofa == null) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.SOFAREF_NOT_FOUND);
throw e;
}
return aSofa;
}
public int ll_getSofaNum(int sofaRef) {
return ll_getIntValue(sofaRef, TypeSystemImpl.sofaNumFeatCode);
}
public String ll_getSofaID(int sofaRef) {
return ll_getStringValue(sofaRef, TypeSystemImpl.sofaIdFeatCode);
}
public String ll_getSofaDataString(int sofaAddr) {
return ll_getStringValue(sofaAddr, TypeSystemImpl.sofaStringFeatCode);
}
public CASImpl getBaseCAS() {
return this.svd.baseCAS;
}
@SuppressWarnings("unchecked")
public FSIterator<SofaFS> getSofaIterator() {
FSIndex<SofaFS> sofaIndex = (FSIndex<SofaFS>) ( FSIndex<?>) this.svd.baseCAS.indexRepository.getIndex(CAS.SOFA_INDEX_NAME);
return sofaIndex.iterator();
}
// For internal use only
public void setSofaFeat(int addr, int sofa) {
// never an index key
setFeatureValueNoIndexCorruptionCheck(addr, TypeSystemImpl.annotSofaFeatCode, sofa);
}
// For internal use only
public int getSofaFeat(int addr) {
return getFeatureValue(addr, TypeSystemImpl.annotSofaFeatCode);
}
// For internal use only
public int getSofaRef() {
if (this.mySofaRef == -1) {
// create the SofaFS for _InitialView ...
// ... and reset mySofaRef to point to it
this.mySofaRef = this.createInitialSofa(null).hashCode();
}
return this.mySofaRef;
}
// For internal use only
public InputStream getSofaDataStream(SofaFS aSofa) {
try {
if (null != aSofa.getLocalStringData()) {
ByteArrayInputStream bis = new ByteArrayInputStream(aSofa.getLocalStringData().getBytes(
"UTF-8"));
return bis;
} else if (null != aSofa.getLocalFSData()) {
FeatureStructureImpl fs = (FeatureStructureImpl) aSofa.getLocalFSData();
int arrayStart = 0;
int arraySize = this.ll_getArraySize(fs.getAddress());
ByteBuffer buf = null;
Type type = fs.getType();
if (type.getName().equals(CAS.TYPE_NAME_STRING_ARRAY)) {
StringBuffer sb = new StringBuffer();
for (int i=0; i<((StringArrayFS)fs).size(); i++) {
if (i==0) {
sb.append( ((StringArrayFS)fs).get(i) );
} else {
sb.append( "\n" + ((StringArrayFS)fs).get(i) );
}
}
ByteArrayInputStream bis = new ByteArrayInputStream( sb.toString().getBytes("UTF-8") );
return bis;
} else if (type.getName().equals(CAS.TYPE_NAME_INTEGER_ARRAY)) {
arrayStart = getArrayStartAddress(fs.getAddress());
buf = ByteBuffer.allocate(arraySize * 4);
IntBuffer intbuf = buf.asIntBuffer();
intbuf.put(this.getHeap().heap, arrayStart, arraySize);
ByteArrayInputStream bis = new ByteArrayInputStream(buf.array());
return bis;
} else if (type.getName().equals(CAS.TYPE_NAME_FLOAT_ARRAY)) {
arrayStart = getArrayStartAddress(fs.getAddress());
buf = ByteBuffer.allocate(arraySize * 4);
FloatBuffer floatbuf = buf.asFloatBuffer();
float[] floatArray = new float[arraySize];
for (int i = arrayStart; i < arrayStart + arraySize; i++) {
floatArray[i - arrayStart] = Float.intBitsToFloat(this.getHeap().heap[i]);
}
floatbuf.put(floatArray);
ByteArrayInputStream bis = new ByteArrayInputStream(buf.array());
return bis;
} else if (type.getName().equals(CAS.TYPE_NAME_BOOLEAN_ARRAY)
|| type.getName().equals(CAS.TYPE_NAME_BYTE_ARRAY)) {
arrayStart = this.getHeap().heap[getArrayStartAddress(fs.getAddress())];
buf = ByteBuffer.allocate(arraySize);
buf.put(this.getByteHeap().heap, arrayStart, arraySize);
ByteArrayInputStream bis = new ByteArrayInputStream(buf.array());
return bis;
} else if (type.getName().equals(CAS.TYPE_NAME_SHORT_ARRAY)) {
arrayStart = this.getHeap().heap[getArrayStartAddress(fs.getAddress())];
buf = ByteBuffer.allocate(arraySize * 2);
ShortBuffer shortbuf = buf.asShortBuffer();
shortbuf.put(this.getShortHeap().heap, arrayStart, arraySize);
ByteArrayInputStream bis = new ByteArrayInputStream(buf.array());
return bis;
} else if (type.getName().equals(CAS.TYPE_NAME_LONG_ARRAY)) {
arrayStart = this.getHeap().heap[getArrayStartAddress(fs.getAddress())];
buf = ByteBuffer.allocate(arraySize * 8);
LongBuffer longbuf = buf.asLongBuffer();
longbuf.put(this.getLongHeap().heap, arrayStart, arraySize);
ByteArrayInputStream bis = new ByteArrayInputStream(buf.array());
return bis;
} else if (type.getName().equals(CAS.TYPE_NAME_DOUBLE_ARRAY)) {
arrayStart = this.getHeap().heap[getArrayStartAddress(fs.getAddress())];
buf = ByteBuffer.allocate(arraySize * 8);
DoubleBuffer doublebuf = buf.asDoubleBuffer();
double[] doubleArray = new double[arraySize];
for (int i = arrayStart; i < arrayStart + arraySize; i++) {
doubleArray[i - arrayStart] = Double.longBitsToDouble(this.getLongHeap().heap[i]);
}
doublebuf.put(doubleArray);
ByteArrayInputStream bis = new ByteArrayInputStream(buf.array());
return bis;
}
} else if (null != aSofa.getSofaURI()) {
URL url = new URL(aSofa.getSofaURI());
return url.openStream();
} else {
return null;
}
} catch (MalformedURLException exc) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.SOFADATASTREAM_ERROR,
new String[] { exc.getMessage() });
throw e;
} catch (CASRuntimeException exc) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.SOFADATASTREAM_ERROR,
new String[] { exc.getMessage() });
throw e;
} catch (IOException exc) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.SOFADATASTREAM_ERROR,
new String[] { exc.getMessage() });
throw e;
}
return null;
}
@Override
public<T extends FeatureStructure> FSIterator<T> createFilteredIterator(FSIterator<T> it, FSMatchConstraint cons) {
return new FilteredIterator<T>(it, cons);
}
public void commitTypeSystem() {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
// For CAS pools, the type system could have already been committed
// Skip the initFSClassReg if so, because it may have been updated to a JCas
// version by another CAS processing in the pool
// @see org.apache.uima.cas.impl.FSClassRegistry
// avoid race: two instances of a CAS from a pool attempting to commit the
// ts
// at the same time
synchronized (ts) {
if (!ts.isCommitted()) {
this.svd.casMetadata.ts.commit();
initFSClassRegistry();
FSClassRegistry fscr = getFSClassRegistry();
// save for the case of non=jcas pipeline with a jcas pear in the middle
// - this
// allows subsequent downstream annotators to run without jcas
fscr.saveGeneratorsForClassLoader(this.svd.previousJCasClassLoader, fscr
.getBaseGenerators());
}
}
setLocalFsGenerators(this.svd.casMetadata.fsClassRegistry.getBaseGenerators());
// After the type system has been committed, we can create the
// index repository.
createIndexRepository();
svd.annotFeatOffset_begin = getFeatureOffset(TypeSystemImpl.startFeatCode);
svd.annotFeatOffset_end = getFeatureOffset(TypeSystemImpl.endFeatCode);
}
// internal use, public for cross class ref
public void setLocalFsGenerators(FSGenerator<? extends FeatureStructure>[] fsGenerators) {
this.svd.localFsGenerators = fsGenerators;
}
private void createIndexRepository() {
if (!this.getTypeSystemMgr().isCommitted()) {
throw new CASAdminException(CASAdminException.MUST_COMMIT_TYPE_SYSTEM);
}
if (this.indexRepository == null) {
this.indexRepository = new FSIndexRepositoryImpl(this);
}
}
public FSIndexRepositoryMgr getIndexRepositoryMgr() {
// assert(this.cas.getIndexRepository() != null);
return this.indexRepository;
}
/**
* @deprecated
* @param fs -
*/
@Deprecated
public void commitFS(FeatureStructure fs) {
getIndexRepository().addFS(fs);
}
public FeaturePath createFeaturePath() {
return new FeaturePathImpl();
}
// Implement the ConstraintFactory interface.
/**
* @see org.apache.uima.cas.admin.CASMgr#getTypeSystemMgr()
*/
public TypeSystemMgr getTypeSystemMgr() {
return this.svd.casMetadata.ts;
}
public void reset() {
if (!this.svd.flushEnabled) {
throw new CASAdminException(CASAdminException.FLUSH_DISABLED);
}
if (this == this.svd.baseCAS) {
resetNoQuestions();
return;
}
// called from a CAS view.
// clear CAS ...
this.svd.baseCAS.resetNoQuestions();
}
/*
* iterated reset - once per view of a CAS except for the base CAS
*/
private void resetView() {
this.indexRepository.flush();
// if (this.mySofaRef > 0 && this.getSofa().getSofaRef() == 1) {
// // indicate no Sofa exists for the initial view
// this.mySofaRef = -1;
// } else {
// this.mySofaRef = 0;
// }
// if (this.jcas != null) {
// try {
// JCasImpl.clearData(this);
// } catch (CASException e) {
// CASAdminException cae = new
// CASAdminException(CASAdminException.JCAS_ERROR);
// cae.addArgument(e.getMessage());
// throw cae;
// }
// }
}
public void resetNoQuestions() {
svd.casResets.incrementAndGet();
if (trace) {
System.out.println("CAS Reset in thread " + Thread.currentThread().getName() +
" for CasId = " + getCasId() + ", new reset count = " + svd.casResets.get());
}
int numViews = this.getBaseSofaCount();
// Flush indexRepository for all Sofa
for (int view = 1; view <= numViews; view++) {
CAS tcas = (view == 1) ? getInitialView() : getView(view);
if (tcas != null) {
((CASImpl) tcas).resetView();
// mySofaRef = -1 is a flag in initial view that sofa has not been set.
// For the initial view, it is possible to not have a sofa - it is set
// "lazily" upon the first need.
// all other views always have a sofa set. The sofaRef is set to 0,
// but will be set to the actual sofa addr in the cas when the view is
// initialized.
((CASImpl) tcas).mySofaRef = (1 == view) ? -1 : 0;
}
}
this.getHeap().reset(/*this.getHeap().getHeapSize() > CASImpl.resetHeapSize*/);
resetStringTable();
this.getByteHeap().reset();
this.getShortHeap().reset();
this.getLongHeap().reset();
this.indexRepository.flush(); // for base view, other views flushed above
this.svd.sofaNameSet = new HashSet<String>();
this.svd.initialSofaCreated = false;
// always an Initial View now!!!
this.svd.viewCount = 1;
if (null != this.svd.casMetadata.fsClassRegistry) {
// needed only if caching non-JCas Java cover objects
// NOTE: This code doesn't work - impl commented outhas not been maintained
this.svd.casMetadata.fsClassRegistry.flush();
}
if (this.jcas != null) {
JCasImpl.clearData(this);
}
clearTrackingMarks();
this.svd.cache_not_in_index = 0;
this.svd.fssTobeAddedback.clear();
this.svd.fssTobeAddedback.trimToSize();
svd.traceFSid = 0;
if (traceFSs) svd.traceFScreationSb.setLength(0);
}
/**
* @deprecated Use {@link #reset reset()}instead.
*/
@Deprecated
public void flush() {
reset();
}
public FSIndexRepository getIndexRepository() {
if (this == this.svd.baseCAS) {
// BaseCas has no indexes for users
return null;
}
if (this.indexRepository.isCommitted()) {
return this.indexRepository;
}
return null;
}
FSIndexRepository getBaseIndexRepository() {
if (this.svd.baseCAS.indexRepository.isCommitted()) {
return this.svd.baseCAS.indexRepository;
}
return null;
}
void addSofaFsToIndex(SofaFS sofa) {
this.svd.baseCAS.getBaseIndexRepository().addFS(sofa);
}
void registerView(SofaFS aSofa) {
this.mySofaRef = ((FeatureStructureImpl) aSofa).getAddress();
}
public void reinit(CASSerializer ser) {
if (this != this.svd.baseCAS) {
this.svd.baseCAS.reinit(ser);
return;
}
this.resetNoQuestions();
reinit(ser.getHeapMetadata(), ser.getHeapArray(), ser.getStringTable(), ser.getFSIndex(), ser
.getByteArray(), ser.getShortArray(), ser.getLongArray());
}
/**
* @see org.apache.uima.cas.CAS#fs2listIterator(FSIterator)
*/
public <T extends FeatureStructure> ListIterator<T> fs2listIterator(FSIterator<T> it) {
return new FSListIteratorImpl<T>(it);
}
/**
* @see org.apache.uima.cas.admin.CASMgr#getCAS()
*/
public CAS getCAS() {
if (this.indexRepository.isCommitted()) {
return this;
}
throw new CASAdminException(CASAdminException.MUST_COMMIT_INDEX_REPOSITORY);
}
void resetStringTable() {
this.getStringHeap().reset();
}
// public void setFSClassRegistry(FSClassRegistry fsClassReg) {
// this.svd.casMetadata.fsClassRegistry = fsClassReg;
// }
private void initFSClassRegistry() {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
// System.out.println("Initializing FSClassRegistry");
this.svd.casMetadata.fsClassRegistry.initGeneratorArray();
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.fsArrayType, new ArrayFSGenerator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.intArrayType, IntArrayFSImpl
.generator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.floatArrayType, FloatArrayFSImpl
.generator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.stringArrayType, StringArrayFSImpl
.generator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.sofaType, SofaFSImpl
.getSofaFSGenerator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.annotBaseType, AnnotationBaseImpl
.getAnnotationGenerator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.annotType, AnnotationImpl
.getAnnotationGenerator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.byteArrayType, ByteArrayFSImpl
.generator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.booleanArrayType, BooleanArrayFSImpl
.generator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.shortArrayType, ShortArrayFSImpl
.generator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.longArrayType, LongArrayFSImpl
.generator());
this.svd.casMetadata.fsClassRegistry.addClassForType(ts.doubleArrayType, DoubleArrayFSImpl
.generator());
// assert(fsClassReg != null);
}
// JCasGen'd cover classes use this to add their generators to the class
// registry
// Note that this now (June 2007) a no-op for JCasGen'd generators
// Also used in JCas initialization to copy-down super generators to subtypes
// as needed
public FSClassRegistry getFSClassRegistry() // for JCas integration
{
return this.svd.casMetadata.fsClassRegistry;
}
public CASImpl setupCasFromCasMgrSerializer(CASImpl cas, CASMgrSerializer casMgrSerializer) {
cas = cas.getBaseCAS();
TypeSystemImpl ts = casMgrSerializer.getTypeSystem();
cas.svd.casMetadata = ts.casMetadata;
cas.commitTypeSystem();
// reset index repositories -- wipes out Sofa index
cas.indexRepository = casMgrSerializer.getIndexRepository(cas);
cas.indexRepository.commit();
// get handle to existing initial View
CAS initialView = cas.getInitialView();
// throw away all other View information as the CAS definition may have
// changed
cas.svd.sofa2indexMap.clear();
cas.svd.sofaNbr2ViewMap.clear();
cas.svd.viewCount = 0;
// freshen the initial view
((CASImpl) initialView).refreshView(cas.svd.baseCAS, null);
setViewForSofaNbr(1, initialView);
cas.svd.viewCount = 1;
return cas;
}
public void reinit(CASCompleteSerializer casCompSer) {
if (this != this.svd.baseCAS) {
this.svd.baseCAS.reinit(casCompSer);
return;
}
setupCasFromCasMgrSerializer(this, casCompSer.getCASMgrSerializer());
// deserialize heap
CASSerializer casSer = casCompSer.getCASSerializer();
reinit(casSer.getHeapMetadata(), casSer.getHeapArray(), casSer.getStringTable(), casSer
.getFSIndex(), casSer.getByteArray(), casSer.getShortArray(), casSer.getLongArray());
// we also need to throw away the JCAS. A new JCAS will be created on
// the next
// call to getJCas(). As with the CAS, we are counting on the fact that
// this happens only in a service, where JCAS handles are not held on
// to.
this.jcas = null;
// this.sofa2jcasMap.clear();
clearTrackingMarks();
}
private void clearTrackingMarks() {
// resets all markers that might be held by things outside the Cas
// Currently (2009) this list has a max of 1 element
// Future impl may have one element per component for component Journaling
if (this.svd.trackingMarkList != null) {
for (int i=0; i < this.svd.trackingMarkList.size(); i++) {
this.svd.trackingMarkList.get(i).isValid = false;
}
}
this.svd.trackingMark = null;
this.svd.modifiedPreexistingFSs = null;
this.svd.modifiedFSHeapCells = null;
this.svd.modifiedByteHeapCells = null;
this.svd.modifiedShortHeapCells = null;
this.svd.modifiedLongHeapCells = null;
this.svd.trackingMarkList = null;
}
void reinit(int[] heapMetadata, int[] heapArray, String[] stringTable, int[] fsIndex,
byte[] byteHeapArray, short[] shortHeapArray, long[] longHeapArray) {
createStringTableFromArray(stringTable);
this.getHeap().reinit(heapMetadata, heapArray);
if (byteHeapArray != null) {
this.getByteHeap().reinit(byteHeapArray);
}
if (shortHeapArray != null) {
this.getShortHeap().reinit(shortHeapArray);
}
if (longHeapArray != null) {
this.getLongHeap().reinit(longHeapArray);
}
reinitIndexedFSs(fsIndex);
}
/**
* Binary Deserializaion Support
* An instance of this class is made for every reinit operation
*
*/
private class BinDeserSupport {
private int fsStartAddr;
private int fsEndAddr;
/**
* An array of all the starting indexes of the FSs on the old/prev heap
* (below the mark, for delta CAS, plus one last one (one beyond the end)
*/
private int[] fssAddrArray;
private int fssIndex;
private int lastRemovedFsAddr;
// feature codes - there are exactly the same number as their are features
private int[] featCodes;
private FSsTobeAddedback tobeAddedback = FSsTobeAddedback.createSingle();
}
/**
* --------------------------------------------------------------------- see
* Blob Format in CASSerializer
*
* This reads in and deserializes CAS data from a stream. Byte swapping may be
* needed if the blob is from C++ -- C++ blob serialization writes data in
* native byte order.
*
* @param istream -
* @return -
* @throws CASRuntimeException wraps IOException
*/
public SerialFormat reinit(InputStream istream) throws CASRuntimeException {
if (this != this.svd.baseCAS) {
return this.svd.baseCAS.reinit(istream);
}
final DataInputStream dis = CommonSerDes.maybeWrapToDataInputStream(istream);
try {
Header h = CommonSerDes.readHeader(dis);
return reinit(h, istream);
} catch (IOException e) {
String msg = e.getMessage();
if (msg == null) {
msg = e.toString();
}
CASRuntimeException exception = new CASRuntimeException(
CASRuntimeException.BLOB_DESERIALIZATION, new String[] { msg });
throw exception;
}
}
/**
* --------------------------------------------------------------------- see
* Blob Format in CASSerializer
*
* This reads in and deserializes CAS data from a stream. Byte swapping may be
* needed if the blob is from C++ -- C++ blob serialization writes data in
* native byte order.
*
* @param istream -
* @return -
* @throws CASRuntimeException wraps IOException
*/
public SerialFormat reinit(Header h, InputStream istream) throws CASRuntimeException {
if (this != this.svd.baseCAS) {
return this.svd.baseCAS.reinit(h, istream);
}
final DataInputStream dis = CommonSerDes.maybeWrapToDataInputStream(istream);
final BinDeserSupport bds = new BinDeserSupport();
try {
final boolean delta = h.isDelta;
if (!delta) {
this.resetNoQuestions();
}
if (h.form4) {
(new BinaryCasSerDes4(this.getTypeSystemImpl(), false)).deserialize(this, dis, delta);
return SerialFormat.COMPRESSED;
}
if (h.form6) {
try {
(new BinaryCasSerDes6(this)).deserializeAfterVersion(dis, delta, AllowPreexistingFS.allow);
return h.typeSystemIncluded ? SerialFormat.COMPRESSED_FILTERED_TSI
: SerialFormat.COMPRESSED_FILTERED;
} catch (ResourceInitializationException e) {
throw new CASRuntimeException(CASRuntimeException.DESERIALIZING_COMPRESSED_BINARY_UNSUPPORTED, null, e);
}
}
final Reading r = h.reading;
// main fsheap
final int fsheapsz = r.readInt();
int startPos = 0;
if (!delta) {
this.getHeap().reinitSizeOnly(fsheapsz);
} else {
startPos = this.getHeap().getNextId();
this.getHeap().grow(fsheapsz);
}
// add new heap slots
for (int i = startPos; i < fsheapsz+startPos; i++) {
this.getHeap().heap[i] = r.readInt();
}
// string heap
int stringheapsz = r.readInt();
final StringHeapDeserializationHelper shdh = new StringHeapDeserializationHelper();
shdh.charHeap = new char[stringheapsz];
for (int i = 0; i < stringheapsz; i++) {
shdh.charHeap[i] = (char) r.readShort();
}
shdh.charHeapPos = stringheapsz;
// word alignment
if (stringheapsz % 2 != 0) {
dis.readChar();
}
// string ref heap
int refheapsz = r.readInt();
refheapsz--;
refheapsz = refheapsz / 2;
refheapsz = refheapsz * 3;
// read back into references consisting to three ints
// --stringheap offset,length, stringlist offset
shdh.refHeap = new int[StringHeapDeserializationHelper.FIRST_CELL_REF + refheapsz];
dis.readInt(); // 0
for (int i = shdh.refHeapPos; i < shdh.refHeap.length; i += StringHeapDeserializationHelper.REF_HEAP_CELL_SIZE) {
shdh.refHeap[i + StringHeapDeserializationHelper.CHAR_HEAP_POINTER_OFFSET] = r.readInt();
shdh.refHeap[i + StringHeapDeserializationHelper.CHAR_HEAP_STRLEN_OFFSET] = r.readInt();
shdh.refHeap[i + StringHeapDeserializationHelper.STRING_LIST_ADDR_OFFSET] = 0;
}
shdh.refHeapPos = refheapsz + StringHeapDeserializationHelper.FIRST_CELL_REF;
this.getStringHeap().reinit(shdh, delta);
//if delta, handle modified fs heap cells
if (delta) {
final int heapsize = this.getHeap().getNextId();
// compute table of ints which correspond to FSs in the existing heap
// we need this because the list of modifications is just arbitrary single words on the heap
// at arbitrary boundaries
IntVector fss = new IntVector(Math.max(128, heapsize >> 6));
int fsAddr;
for (fsAddr = 1; fsAddr < heapsize; fsAddr = getNextFsHeapAddr(fsAddr)) {
fss.add(fsAddr);
}
fss.add(fsAddr); // add trailing value
bds.fssAddrArray = fss.toArray();
int fsmodssz = r.readInt();
bds.fsStartAddr = -1;
// loop over all heap modifications to existing FSs
// first disable auto addbacks for index corruption - this routine is handling that
svd.fsTobeAddedbackSingleInUse = true; // sorry, a bad hack...
// System.out.format("debug checkout (fake) add back single for cas %s%n", this.getViewName());
try {
for (int i = 0; i < fsmodssz; i++) {
final int heapAddrBeingModified = r.readInt();
maybeAddBackAndRemoveFs(heapAddrBeingModified, bds);
this.getHeap().heap[heapAddrBeingModified] = r.readInt();
}
bds.tobeAddedback.addback(bds.lastRemovedFsAddr);
bds.fssAddrArray = null; // free storage
} finally {
// System.out.format("debug return (fake) add back single for cas %s%n", this.getViewName());
svd.fsTobeAddedbackSingleInUse = false;
}
}
// indexed FSs
int fsindexsz = r.readInt();
int[] fsindexes = new int[fsindexsz];
for (int i = 0; i < fsindexsz; i++) {
fsindexes[i] = r.readInt();
}
// build the index
if (delta) {
reinitDeltaIndexedFSs(fsindexes);
} else {
reinitIndexedFSs(fsindexes);
}
// byte heap
int heapsz = r.readInt();
if (!delta) {
this.getByteHeap().heap = new byte[Math.max(16, heapsz)]; // must be > 0
dis.readFully(this.getByteHeap().heap, 0, heapsz);
this.getByteHeap().heapPos = heapsz;
} else {
for (int i=0; i < heapsz; i++) {
this.getByteHeap().addByte(dis.readByte());
}
}
// word alignment
int align = (4 - (heapsz % 4)) % 4;
BinaryCasSerDes6.skipBytes(dis, align);
// short heap
heapsz = r.readInt();
if (!delta) {
this.getShortHeap().heap = new short[Math.max(16, heapsz)]; // must be > 0
for (int i = 0; i < heapsz; i++) {
this.getShortHeap().heap[i] = r.readShort();
}
this.getShortHeap().heapPos = heapsz;
} else {
for (int i = 0; i < heapsz; i++) {
this.getShortHeap().addShort(r.readShort());
}
}
// word alignment
if (heapsz % 2 != 0) {
dis.readShort();
}
// long heap
heapsz = r.readInt();
if (!delta) {
this.getLongHeap().heap = new long[Math.max(16, heapsz)]; // must be > 0
for (int i = 0; i < heapsz; i++) {
this.getLongHeap().heap[i] = r.readLong();
}
this.getLongHeap().heapPos = heapsz;
} else {
for (int i = 0; i < heapsz; i++) {
this.getLongHeap().addLong(r.readLong());
}
}
if (delta) {
//modified Byte Heap
heapsz = r.readInt();
if (heapsz > 0) {
int[] heapAddrs = new int[heapsz];
for (int i = 0; i < heapsz; i++) {
heapAddrs[i] = r.readInt();
}
for (int i = 0; i < heapsz; i++) {
this.getByteHeap().heap[heapAddrs[i]] = dis.readByte();
}
}
// word alignment
align = (4 - (heapsz % 4)) % 4;
BinaryCasSerDes6.skipBytes(dis, align);
//modified Short Heap
heapsz = r.readInt();
if (heapsz > 0) {
int[] heapAddrs = new int[heapsz];
for (int i = 0; i < heapsz; i++) {
heapAddrs[i] = r.readInt();
}
for (int i = 0; i < heapsz; i++) {
this.getShortHeap().heap[heapAddrs[i]] = r.readShort();
}
}
// word alignment
if (heapsz % 2 != 0) {
dis.readShort();
}
//modified Long Heap
heapsz = r.readInt();
if (heapsz > 0) {
int[] heapAddrs = new int[heapsz];
for (int i = 0; i < heapsz; i++) {
heapAddrs[i] = r.readInt();
}
for (int i = 0; i < heapsz; i++) {
this.getLongHeap().heap[heapAddrs[i]] = r.readLong();
}
}
} // of delta - modified processing
} catch (IOException e) {
String msg = e.getMessage();
if (msg == null) {
msg = e.toString();
}
CASRuntimeException exception = new CASRuntimeException(
CASRuntimeException.BLOB_DESERIALIZATION, new String[] { msg });
throw exception;
}
return SerialFormat.BINARY;
}
/**
* for Deserialization of Delta, when updating existing FSs,
* If the heap addr is for the next FS, re-add the previous one to those indexes where it was removed,
* and then maybe remove the new one (and remember which views to re-add to).
* @param heapAddr
*/
private void maybeAddBackAndRemoveFs(int heapAddr, final BinDeserSupport bds) {
if (bds.fsStartAddr == -1) {
bds.fssIndex = -1;
bds.lastRemovedFsAddr = -1;
bds.tobeAddedback.clear();
}
findCorrespondingFs(heapAddr, bds); // sets fsStartAddr, end addr
if (bds.lastRemovedFsAddr != bds.fsStartAddr) {
bds.tobeAddedback.addback(bds.lastRemovedFsAddr);
if (bds.featCodes.length == 0) {
// is array
final int typeCode = getTypeCode(bds.fsStartAddr);
assert(getTypeSystemImpl().ll_isArrayType(typeCode));
} else {
int featCode = bds.featCodes[heapAddr - (bds.fsStartAddr + 1)];
removeFromCorruptableIndexAnyView(bds.lastRemovedFsAddr = bds.fsStartAddr, bds.tobeAddedback, featCode);
}
}
}
private void findCorrespondingFs(int heapAddr, final BinDeserSupport bds) {
if (bds.fsStartAddr < heapAddr && heapAddr < bds.fsEndAddr) {
return;
}
// search forward by 1 before doing binary search
bds.fssIndex ++; // incrementing dense index into fssAddrArray for start addrs
bds.fsStartAddr = bds.fssAddrArray[bds.fssIndex]; // must exist
if (bds.fssIndex + 1 < bds.fssAddrArray.length) { // handle edge case where prev was at the end
bds.fsEndAddr = bds.fssAddrArray[bds.fssIndex + 1]; // must exist
if (bds.fsStartAddr < heapAddr && heapAddr < bds.fsEndAddr) {
bds.featCodes = getTypeSystemImpl().ll_getAppropriateFeatures(getTypeCode(bds.fsStartAddr));
return;
}
}
int result;
if (heapAddr > bds.fsEndAddr) {
// item is higher
result = Arrays.binarySearch(bds.fssAddrArray, bds.fssIndex + 1, bds.fssAddrArray.length, heapAddr);
} else {
result = Arrays.binarySearch(bds.fssAddrArray, 0, bds.fssIndex - 1, heapAddr);
}
// result must be negative - should never modify a type code slot
assert (result < 0);
bds.fssIndex = (-result) - 2;
bds.fsStartAddr = bds.fssAddrArray[bds.fssIndex];
bds.fsEndAddr = bds.fssAddrArray[bds.fssIndex + 1];
bds.featCodes = getTypeSystemImpl().ll_getAppropriateFeatures(getTypeCode(bds.fsStartAddr));
assert(bds.fsStartAddr < heapAddr && heapAddr < bds.fsEndAddr);
}
private int getNextFsHeapAddr(int fsAddr) {
final TypeSystemImpl tsi = getTypeSystemImpl();
final int typeCode = getTypeCode(fsAddr);
final Type type = tsi.ll_getTypeForCode(typeCode);
//debug
// if (tsi.ll_getTypeForCode(typeCode) == null) {
// System.out.println("debug, typeCode = "+ typeCode);
// }
final boolean isHeapStoredArray = (typeCode == TypeSystemImpl.intArrayTypeCode) || (typeCode == TypeSystemImpl.floatArrayTypeCode)
|| (typeCode == TypeSystemImpl.fsArrayTypeCode) || (typeCode == TypeSystemImpl.stringArrayTypeCode)
|| (TypeSystemImpl.isArrayTypeNameButNotBuiltIn(type.getName()));
if (isHeapStoredArray) {
return fsAddr + 2 + getHeapValue(fsAddr + 1);
} else if (type.isArray()) {
return fsAddr + 3; // for the aux ref and the length
} else {
return fsAddr + this.svd.casMetadata.fsSpaceReq[typeCode];
}
}
// private long swap8(DataInputStream dis, byte[] buf) throws IOException {
//
// buf[7] = dis.readByte();
// buf[6] = dis.readByte();
// buf[5] = dis.readByte();
// buf[4] = dis.readByte();
// buf[3] = dis.readByte();
// buf[2] = dis.readByte();
// buf[1] = dis.readByte();
// buf[0] = dis.readByte();
// ByteBuffer bb = ByteBuffer.wrap(buf);
// return bb.getLong();
// }
//
// private int swap4(DataInputStream dis, byte[] buf) throws IOException {
// buf[3] = dis.readByte();
// buf[2] = dis.readByte();
// buf[1] = dis.readByte();
// buf[0] = dis.readByte();
// ByteBuffer bb = ByteBuffer.wrap(buf);
// return bb.getInt();
// }
//
// private char swap2(DataInputStream dis, byte[] buf) throws IOException {
// buf[1] = dis.readByte();
// buf[0] = dis.readByte();
// ByteBuffer bb = ByteBuffer.wrap(buf, 0, 2);
// return bb.getChar();
// }
// assumes:
// indexes are empty on entry
//
void reinitIndexedFSs(int[] fsIndex) {
// Add FSs to index repository for base CAS
int numViews = fsIndex[0];
int loopLen = fsIndex[1]; // number of sofas, not necessarily the same as
// number of views
// because the initial view may not have a sofa
for (int i = 2; i < loopLen + 2; i++) { // iterate over all the sofas,
this.indexRepository.addFS(fsIndex[i]); // add to base index
}
int loopStart = loopLen + 2;
FSIterator<SofaFS> iterator = this.svd.baseCAS.getSofaIterator();
final Feature idFeat = getTypeSystem().getFeatureByFullName(CAS.FEATURE_FULL_NAME_SOFAID);
// Add FSs to index repository for each View
while (iterator.isValid()) {
SofaFS sofa = iterator.get();
String id = ll_getStringValue(((FeatureStructureImpl) sofa).getAddress(),
((FeatureImpl) idFeat).getCode());
if (CAS.NAME_DEFAULT_SOFA.equals(id)) {
this.registerInitialSofa();
this.svd.sofaNameSet.add(id);
}
// next line the getView as a side effect
// checks for dupl sofa name, and if not,
// adds the name to the sofaNameSet
((CASImpl) this.getView(sofa)).registerView(sofa);
iterator.moveToNext();
}
getInitialView(); // done for side effect of creating the initial view.
// must be done before the next line, because it sets the
// viewCount to 1.
this.svd.viewCount = numViews; // total number of views
for (int viewNbr = 1; viewNbr <= numViews; viewNbr++) {
CAS view = (viewNbr == 1) ? getInitialView() : getView(viewNbr);
if (view != null) {
FSIndexRepositoryImpl loopIndexRep = (FSIndexRepositoryImpl) getSofaIndexRepository(viewNbr);
loopLen = fsIndex[loopStart];
for (int i = loopStart + 1; i < loopStart + 1 + loopLen; i++) {
loopIndexRep.addFS(fsIndex[i]);
}
loopStart += loopLen + 1;
((CASImpl) view).updateDocumentAnnotation();
} else {
loopStart += 1;
}
}
}
/**
* Adds the SofaFSs to the base view
* Assumes "cas" refers to the base cas
*
* Processes "adds", "removes" and "reindexes" for all views
*
* @param fsIndex - array of fsRefs and counts, for sofas, and all views
*/
void reinitDeltaIndexedFSs(int[] fsIndex) {
assert(this.svd.baseCAS == this);
// Add Sofa FSs to index repository for base CAS
int numViews = fsIndex[0]; // total number of views
int loopLen = fsIndex[1]; // number of sofas, not necessarily the same as number of views (initial view could be missing a Sofa)
// add Sofa FSs to base view number of views. Should only contain new Sofas.
for (int i = 2; i < loopLen + 2; i++) { // iterate over all the sofas,
this.indexRepository.addFS(fsIndex[i]); // add to base index
}
int loopStart = loopLen + 2;
FSIterator<SofaFS> iterator = this.getSofaIterator();
final int idFeatCode = ((FeatureImpl)getTypeSystem().getFeatureByFullName(CAS.FEATURE_FULL_NAME_SOFAID)).getCode();
// Register all Sofas
while (iterator.isValid()) {
SofaFS sofa = iterator.get();
String id = ll_getStringValue(((FeatureStructureImpl) sofa).getAddress(), idFeatCode);
if (CAS.NAME_DEFAULT_SOFA.equals(id)) {
this.registerInitialSofa();
this.svd.sofaNameSet.add(id);
}
// next line the getView as a side effect
// checks for dupl sofa name, and if not,
// adds the name to the sofaNameSet
((CASImpl) this.getView(sofa)).registerView(sofa);
iterator.moveToNext();
}
this.svd.viewCount = numViews; // total number of views
for (int viewNbr = 1; viewNbr <= numViews; viewNbr++) {
CAS view = (viewNbr == 1) ? getInitialView() : getView(viewNbr);
if (view != null) {
// for all views
FSIndexRepositoryImpl loopIndexRep = (FSIndexRepositoryImpl) getSofaIndexRepository(viewNbr);
loopLen = fsIndex[loopStart];
// add FSs to index
for (int i = loopStart + 1; i < loopStart + 1 + loopLen; i++) {
loopIndexRep.addFS(fsIndex[i]);
}
// remove FSs from indexes
loopStart += loopLen + 1;
loopLen = fsIndex[loopStart];
for (int i = loopStart + 1; i < loopStart + 1 + loopLen; i++) {
loopIndexRep.removeFS(fsIndex[i]);
}
// skip the reindex - this isn't done here https://issues.apache.org/jira/browse/UIMA-4100
// but we need to run the loop to read over the items in the input stream
loopStart += loopLen + 1;
loopLen = fsIndex[loopStart];
// for (int i = loopStart + 1; i < loopStart + 1 + loopLen; i++) {
// loopIndexRep.removeFS(fsIndex[i]);
// loopIndexRep.addFS(fsIndex[i]);
// }
loopStart += loopLen + 1;
((CASImpl) view).updateDocumentAnnotation();
} else {
loopStart += 1;
}
}
}
// IndexedFSs format:
// number of views
// number of sofas
// [sofa-1 ... sofa-n]
// number of FS indexed in View1
// [FS-1 ... FS-n]
// etc.
int[] getIndexedFSs() {
IntVector v = new IntVector();
int[] fsLoopIndex;
int numViews = getBaseSofaCount();
v.add(numViews);
// Get indexes for base CAS
fsLoopIndex = this.svd.baseCAS.indexRepository.getIndexedFSs();
v.add(fsLoopIndex.length);
v.add(fsLoopIndex, 0, fsLoopIndex.length);
// for (int k = 0; k < fsLoopIndex.length; k++) {
// v.add(fsLoopIndex[k]);
// }
// Get indexes for each SofaFS in the CAS
for (int sofaNum = 1; sofaNum <= numViews; sofaNum++) {
FSIndexRepositoryImpl loopIndexRep = (FSIndexRepositoryImpl) this.svd.baseCAS
.getSofaIndexRepository(sofaNum);
if (loopIndexRep != null) {
fsLoopIndex = loopIndexRep.getIndexedFSs();
} else {
fsLoopIndex = INT0;
}
v.add(fsLoopIndex.length);
for (int k = 0; k < fsLoopIndex.length; k++) {
v.add(fsLoopIndex[k]);
}
}
return v.toArray();
}
//Delta IndexedFSs format:
// number of views
// number of sofas - new
// [sofa-1 ... sofa-n]
// number of new FS add in View1
// [FS-1 ... FS-n]
// number of FS removed from View1
// [FS-1 ... FS-n]
//number of FS reindexed in View1
// [FS-1 ... FS-n]
// etc.
int[] getDeltaIndexedFSs(MarkerImpl mark) {
IntVector v = new IntVector();
int[] fsLoopIndex;
int[] fsDeletedFromIndex;
int[] fsReindexed;
int numViews = getBaseSofaCount();
v.add(numViews);
// Get indexes for base CAS
fsLoopIndex = this.svd.baseCAS.indexRepository.getIndexedFSs();
// Get the new Sofa FS
IntVector newSofas = new IntVector();
for (int k = 0; k < fsLoopIndex.length; k++) {
if ( mark.isNew(fsLoopIndex[k]) ) {
newSofas.add(fsLoopIndex[k]);
}
}
v.add(newSofas.size());
v.add(newSofas.getArray(), 0, newSofas.size());
// for (int k = 0; k < newSofas.size(); k++) {
// v.add(newSofas.get(k));
// }
// Get indexes for each view in the CAS
for (int sofaNum = 1; sofaNum <= numViews; sofaNum++) {
FSIndexRepositoryImpl loopIndexRep = (FSIndexRepositoryImpl) this.svd.baseCAS
.getSofaIndexRepository(sofaNum);
if (loopIndexRep != null) {
fsLoopIndex = loopIndexRep.getAddedFSs();
fsDeletedFromIndex = loopIndexRep.getDeletedFSs();
fsReindexed = loopIndexRep.getReindexedFSs();
} else {
fsLoopIndex = INT0;
fsDeletedFromIndex = INT0;
fsReindexed = INT0;
}
v.add(fsLoopIndex.length);
v.add(fsLoopIndex, 0, fsLoopIndex.length);
// for (int k = 0; k < fsLoopIndex.length; k++) {
// v.add(fsLoopIndex[k]);
// }
v.add(fsDeletedFromIndex.length);
v.add(fsDeletedFromIndex, 0, fsDeletedFromIndex.length);
// for (int k = 0; k < fsDeletedFromIndex.length; k++) {
// v.add(fsDeletedFromIndex[k]);
// }
v.add(fsReindexed.length);
v.add(fsReindexed, 0, fsReindexed.length);
// for (int k = 0; k < fsReindexed.length; k++) {
// v.add(fsReindexed[k]);
// }
}
return v.toArray();
}
void createStringTableFromArray(String[] stringTable) {
// why a new heap instead of reseting the old one???
// this.stringHeap = new StringHeap();
this.getStringHeap().reset();
for (int i = 1; i < stringTable.length; i++) {
this.getStringHeap().addString(stringTable[i]);
}
}
static String mapName(String name, HashMap<String, String> map) {
String out = map.get(name);
if (out != null) {
return out;
}
return name;
}
/**
* This is your link from the low-level API to the high-level API. Use this
* method to create a FeatureStructure object from an address. Not that the
* reverse is not supported by public APIs (i.e., there is currently no way to
* get at the address of a FeatureStructure. Maybe we will need to change
* that.
*
* @param addr
* The address of the feature structure to be created.
* @param <T> The Java class associated with this feature structure
* @return A FeatureStructure object. Note that no checking whatsoever is done
* on the input address. There is really no way of finding out which
* addresses in the valid address space actually represent feature
* structures, and which don't.
*/
public <T extends FeatureStructure> T createFS(int addr) {
return ll_getFSForRef(addr);
}
public int ll_getArraySize(int arrayFsRef) {
return this.getHeap().heap[arrayFsRef + arrayLengthFeatOffset];
}
/**
* Get the heap address of the first cell of this array.
*
* @param addr
* The address of the array.
* @return The address where the first cell of the array is located.
*/
public final int getArrayStartAddress(int addr) {
return addr + arrayContentOffset;
}
/**
* Get a specific value out of an array.
*
* @param addr
* The address of the array.
* @param index
* The index of the value we're interested in.
* @return The value at <code>index</code>.
* @exception ArrayIndexOutOfBoundsException -
*/
public int getArrayValue(int addr, int index) {
checkArrayBounds(addr, index);
return this.getHeap().heap[addr + arrayContentOffset + index];
}
/**
* Set an array value.
*
* @param addr
* The address of the array.
* @param index
* The index we want to set.
* @param value
* The value we want to set.
* @exception ArrayIndexOutOfBoundsException
*/
void setArrayValue(final int addr, final int index, final int value)
throws ArrayIndexOutOfBoundsException {
// Get the length of this array.
final int arraySize = this.getHeap().heap[addr + arrayLengthFeatOffset];
// Check for boundary violation.
if ((index < 0) || (index >= arraySize)) {
throw new ArrayIndexOutOfBoundsException();
}
this.getHeap().heap[addr + arrayContentOffset + index] = value;
if (this.svd.trackingMark != null) {
this.logFSUpdate(addr, addr+arrayContentOffset+index, ModifiedHeap.FSHEAP, 1);
}
}
void setArrayValueFromString(final int addr, final int index, final String value) {
int arrayType = this.getHeap().heap[addr];
if (arrayType == TypeSystemImpl.intArrayTypeCode) {
setArrayValue(addr, index, Integer.parseInt(value));
} else if (arrayType == TypeSystemImpl.floatArrayTypeCode) {
setArrayValue(addr, index, CASImpl.float2int(Float.parseFloat(value)));
} else if (arrayType == TypeSystemImpl.stringArrayTypeCode) {
setArrayValue(addr, index, addString(value));
} else if (arrayType == TypeSystemImpl.booleanArrayTypeCode) {
ll_setBooleanArrayValue(addr, index, Boolean.valueOf(value).booleanValue());
} else if (arrayType == TypeSystemImpl.byteArrayTypeCode) {
ll_setByteArrayValue(addr, index, Byte.parseByte(value));
} else if (arrayType == TypeSystemImpl.shortArrayTypeCode) {
ll_setShortArrayValue(addr, index, Short.parseShort(value));
} else if (arrayType == TypeSystemImpl.longArrayTypeCode) {
ll_setLongArrayValue(addr, index, Long.parseLong(value));
} else if (arrayType == TypeSystemImpl.doubleArrayTypeCode) {
ll_setDoubleArrayValue(addr, index, Double.parseDouble(value));
} else if (arrayType == TypeSystemImpl.fsArrayTypeCode) {
setArrayValue(addr, index, Integer.parseInt(value));
}
}
/**
* Copy the contents of an array to an externally provided array.
*
* @param addr
* The address of the source array.
* @param sourceOffset
* The offset we want to start copying at.
* @param dest
* The destination array.
* @param destOffset
* An offset into the destination array.
* @param length
* The number of items to copy.
*/
void copyToArray(int addr, int sourceOffset, int[] dest, int destOffset, int length) {
// Get the length of this array.
final int arraySize = this.getHeap().heap[addr + arrayLengthFeatOffset];
// Check boundary conditions for source array. We can rely on Java to
// complain about boundary violations for the destination array.
if ((sourceOffset < 0) || ((length + sourceOffset) > arraySize)) {
throw new ArrayIndexOutOfBoundsException();
}
// Compute the offset into the heap where the array starts.
final int offset = addr + arrayContentOffset;
System.arraycopy(this.getHeap().heap, offset + sourceOffset, dest, destOffset, length);
}
/**
* Copy the contents of an input array into a CAS array.
*
* @param src
* The array to copy from.
* @param srcOffset
* An offset into the source from where to start copying.
* @param addr
* The address of the array we're copying to.
* @param destOffset
* Where to start copying into the destination array.
* @param length
* How many elements to copy.
*/
void copyFromArray(int[] src, int srcOffset, int addr, int destOffset, int length) {
// Get the length of this array.
final int arraySize = this.getHeap().heap[addr + arrayLengthFeatOffset];
// Check boundary conditions for destination array. We can rely on Java
// to
// complain about boundary violations for the source array.
if ((destOffset < 0) || ((length + destOffset) > arraySize)) {
throw new ArrayIndexOutOfBoundsException();
}
// Compute the offset into the heap where the array starts.
final int offset = addr + arrayContentOffset;
System.arraycopy(src, srcOffset, this.getHeap().heap, offset + destOffset, length);
if (this.svd.trackingMark != null) {
this.logFSUpdate(addr, offset + destOffset, ModifiedHeap.FSHEAP, length);
}
}
public int getTypeCode(int fsAddr) {
return getHeapValue(fsAddr);
}
// not journaled, this is for a new FS only
void copyFeatures(int trgAddr, int srcAddr) throws CASRuntimeException {
int typeCode = getHeapValue(trgAddr);
if (typeCode != getHeapValue(srcAddr)) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.INAPPROP_TYPE);
// What's that supposed to mean? Internationalized, my foot.
// TODO: fix exception argument.
// e.addArgument("Type of source and target feature structures do not
// match");
throw (e);
}
// get features to copy
int[] featcodes = getTypeSystem().getLowLevelTypeSystem().ll_getAppropriateFeatures(typeCode);
for (int i = 0; i < featcodes.length; i++) {
// get range type of this feature
Feature feature = getTypeSystem().getLowLevelTypeSystem().ll_getFeatureForCode(featcodes[i]);
Type rangeType = feature.getRange();
// get feature code
int featCode = ((FeatureImpl) feature).getCode();
// get the value for this feature offset in src fs
int val = getHeapValue(srcAddr + this.svd.casMetadata.featureOffset[featCode]);
// if this is a string, create a new reference in the string
// reference heap
// and point to the same string as the string feature in src fs.
setFeatureValueNotJournaled(trgAddr, featCode, isStringType(rangeType) ?
this.getStringHeap().cloneStringReference(val) :
getHeapValue(srcAddr + this.svd.casMetadata.featureOffset[featCode]));
}
}
/**
* Get the value of an address on the heap.
*
* @param addr
* The target address.
* @return The value at the address.
*/
public int getHeapValue(int addr) {
return this.getHeap().heap[addr];
}
/**
* This is the common point where all sets of values in the heap come through
* It implements the check for invalid feature setting and potentially the addback.
*
* Set the value of a feature of a FS.
*
* @param addr
* The address of the FS.
* @param feat
* The code of the feature.
* @param val
* The new value for the feature.
* @exception ArrayIndexOutOfBoundsException
* If the feature is not a legal feature, or it is not
* appropriate for the type at the address.
*/
public void setFeatureValue(int addr, int feat, int val) {
boolean wasRemoved = checkForInvalidFeatureSetting(addr, feat);
setFeatureValueNotJournaled(addr, feat, val);
if (wasRemoved) {
maybeAddback(addr);
}
if (this.svd.trackingMark != null) {
this.logFSUpdate(addr, addr + this.svd.casMetadata.featureOffset[feat],
ModifiedHeap.FSHEAP, 1);
}
}
/**
* Set the value of a feature of a FS without checking for index corruption
* (typically because the feature isn't one that can be used as a key, or
* the context is one where the FS is being created, and is guaranteed not to be in any index (yet))
*
* @param addr The address of the FS.
* @param feat The code of the feature.
* @param val The new value for the feature.
* @exception ArrayIndexOutOfBoundsException
* If the feature is not a legal feature, or it is not
* appropriate for the type at the address.
*/
void setFeatureValueNoIndexCorruptionCheck(int addr, int feat, int val) {
setFeatureValueNotJournaled(addr, feat, val);
if (this.svd.trackingMark != null) {
this.logFSUpdate(addr, addr+this.svd.casMetadata.featureOffset[feat],
ModifiedHeap.FSHEAP, 1);
}
}
/**
* Set the value of a feature in the FS without journaling
* (because it's for a new FS above the mark)
* @param addr The address of the FS.
* @param feat The code of the feature.
* @param val The new value for the feature.
* @exception ArrayIndexOutOfBoundsException
* If the feature is not a legal feature, or it is not
* appropriate for the type at the address.
*/
void setFeatureValueNotJournaled(int addr, int feat, int val) {
this.getHeap().heap[(addr + this.svd.casMetadata.featureOffset[feat])] = val;
if (traceFSs) {
traceFSfeat(ll_getFSForRef(addr), (FeatureImpl) getTypeSystemImpl().ll_getFeatureForCode(feat), val);
}
}
public void setStringValue(int addr, int feat, String s) {
final int stringCode = ((s == null) ? NULL : this.getStringHeap().addString(s));
setFeatureValue(addr, feat, stringCode);
}
public void setFloatValue(int addr, int feat, float f) {
final int floatCode = Float.floatToIntBits(f);
setFeatureValue(addr, feat, floatCode);
}
// doesn't do proper index corruption checking
// because don't have FS addr
// never called 2014
// public void setFloatValue(int addr, float f) {
// final int floatCode = Float.floatToIntBits(f);
// this.getHeap().heap[addr] = floatCode;
// }
public int getFeatureValue(int addr, int feat) {
return this.getHeap().heap[(addr + this.svd.casMetadata.featureOffset[feat])];
}
public String getStringValue(int addr, int feat) {
return ll_getStringValue(addr, feat);
}
public float getFloatValue(int addr, int feat) {
return Float.intBitsToFloat(getFeatureValue(addr, feat));
}
public float getFloatValue(int addr) {
return Float.intBitsToFloat(this.getHeap().heap[addr]);
}
// byte
public void setFeatureValue(int addr, int feat, byte v) {
setFeatureValue(addr, feat, (int) v);
}
public byte getByteValue(int addr, int feat) {
return ll_getByteValue(addr, feat);
}
// boolean
public void setFeatureValue(int addr, int feat, boolean v) {
setFeatureValue(addr, feat, v ? CASImpl.TRUE : CASImpl.FALSE);
}
public boolean getBooleanValue(int addr, int feat) {
return ll_getBooleanValue(addr, feat);
}
// short
public void setFeatureValue(int addr, int feat, short s) {
setFeatureValue(addr, feat, (int) s);
}
public short getShortValue(int addr, int feat) {
return this.ll_getShortValue(addr, feat);
}
// long
public void setFeatureValue(int addr, int feat, long s) {
this.ll_setLongValue(addr, feat, s);
}
public long getLongValue(int addr, int feat) {
return this.ll_getLongValue(addr, feat);
}
public void setFeatureValue(int addr, int feat, float f) {
this.ll_setFloatValue(addr, feat, f);
}
// public void setFeatureValueNoIndexCorruptionCheck(int addr, int feat, float f) {
// this.ll_setFloatValueNoIndexCorruptionCheck(addr, feat, f);
// }
// double
public void setFeatureValue(int addr, int feat, double s) {
this.ll_setDoubleValue(addr, feat, s);
}
public double getDoubleValue(int addr, int feat) {
return ll_getDoubleValue(addr, feat);
}
public String getFeatureValueAsString(int addr, int feat) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
int typeCode = ts.range(feat);
if (typeCode == TypeSystemImpl.intTypeCode) {
return Integer.toString(this.ll_getIntValue(addr, feat));
} else if (typeCode == TypeSystemImpl.floatTypeCode) {
return Float.toString(this.ll_getFloatValue(addr, feat));
} else if (ts.subsumes(TypeSystemImpl.stringTypeCode, typeCode)) {
return this.getStringValue(addr, feat);
} else if (typeCode == TypeSystemImpl.booleanTypeCode) {
return Boolean.toString(this.getBooleanValue(addr, feat));
} else if (typeCode == TypeSystemImpl.byteTypeCode) {
return Byte.toString(this.getByteValue(addr, feat));
} else if (typeCode == TypeSystemImpl.shortTypeCode) {
return Short.toString(this.getShortValue(addr, feat));
} else if (typeCode == TypeSystemImpl.longTypeCode) {
return Long.toString(this.getLongValue(addr, feat));
} else if (typeCode == TypeSystemImpl.doubleTypeCode) {
return Double.toString(this.getDoubleValue(addr, feat));
} else {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.INAPPROP_RANGE,
new String[] { ts.ll_getFeatureForCode(feat).getName(),
ts.ll_getTypeForCode(typeCode).getName() });
throw e;
}
}
public void setFeatureValueFromString(int fsref, int feat, String value) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
int typeCode = (ts.range(feat));
if (typeCode == TypeSystemImpl.intTypeCode) {
this.ll_setIntValue(fsref, feat, Integer.parseInt(value));
} else if (typeCode == TypeSystemImpl.floatTypeCode) {
this.setFloatValue(fsref, feat, Float.parseFloat(value));
} else if (ts.subsumes(TypeSystemImpl.stringTypeCode, typeCode)) {
this.setStringValue(fsref, feat, value);
} else if (typeCode == TypeSystemImpl.booleanTypeCode) {
this.setFeatureValue(fsref, feat, Boolean.valueOf(value).booleanValue());
} else if (typeCode == TypeSystemImpl.byteTypeCode) {
this.setFeatureValue(fsref, feat, Byte.parseByte(value));
} else if (typeCode == TypeSystemImpl.shortTypeCode) {
this.setFeatureValue(fsref, feat, Short.parseShort(value));
} else if (typeCode == TypeSystemImpl.longTypeCode) {
this.setFeatureValue(fsref, feat, Long.parseLong(value));
} else if (typeCode == TypeSystemImpl.doubleTypeCode) {
this.setFeatureValue(fsref, feat, Double.parseDouble(value));
} else {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.INAPPROP_TYPE,
new String[] { ts.ll_getFeatureForCode(feat).getName(),
ts.ll_getTypeForCode(typeCode).getName() });
throw e;
}
}
public static final float int2float(int i) {
return Float.intBitsToFloat(i);
}
public static final int float2int(float f) {
return Float.floatToIntBits(f);
}
public static final double long2double(long l) {
return Double.longBitsToDouble(l);
}
public static final long double2long(double d) {
return Double.doubleToLongBits(d);
}
public TypeSystemImpl getTypeSystemImpl() {
return this.svd.casMetadata.ts;
}
public String getStringForCode(int stringCode) {
return this.getStringHeap().getStringForCode(stringCode);
}
/**
* Check if this is a regular type (i.e., not an array or a basic type).
*
* @param typeCode
* The code to check.
* @return <code>true</code> iff <code>typeCode</code> is a type for which
* a regular FS can be generated.
* @exception NullPointerException
* If <code>typeCode</code> is not a type code.
*/
final boolean isCreatableType(int typeCode) {
return this.svd.casMetadata.creatableType[typeCode];
}
// **** Never called
// boolean isBuiltinType(Type type) {
// // had to hack this because it wasn't considering List types as built in
// // -AL
// return (type.getName().startsWith("uima") || type == getAnnotationType());
// /*
// * final int typeCode = ((TypeImpl) type).getCode(); return (type ==
// ts.getTopType()) ||
// * isArrayType(typeCode) || isAbstractArrayType(typeCode) ||
// isStringType(typeCode) ||
// * isFloatType(typeCode) || isIntType(typeCode);
// */
// }
int addString(String s) {
return this.getStringHeap().addString(s);
}
// Type access methods.
public boolean isStringType(Type type) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
return ts.subsumes(ts.stringType, type);
}
public boolean isAbstractArrayType(Type type) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
return ts.subsumes(ts.arrayBaseType, type);
}
public boolean isArrayType(Type type) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
return ((type == ts.fsArrayType) || (type == ts.intArrayType) || (type == ts.floatArrayType)
|| (type == ts.stringArrayType) || (type == ts.booleanArrayType)
|| (type == ts.byteArrayType) || (type == ts.shortArrayType)
|| (type == ts.doubleArrayType) || (type == ts.longArrayType));
}
public boolean isIntArrayType(Type type) {
return (type == this.svd.casMetadata.ts.intArrayType);
}
public boolean isFloatArrayType(Type type) {
return (type == this.svd.casMetadata.ts.floatArrayType);
}
public boolean isStringArrayType(Type type) {
return (type == this.svd.casMetadata.ts.stringArrayType);
}
public boolean isBooleanArrayType(Type type) {
return (type == this.svd.casMetadata.ts.booleanArrayType);
}
public boolean isByteArrayType(Type type) {
return (type == this.svd.casMetadata.ts.byteArrayType);
}
public boolean isShortArrayType(Type type) {
return (type == this.svd.casMetadata.ts.shortArrayType);
}
public boolean isLongArrayType(Type type) {
return (type == this.svd.casMetadata.ts.longArrayType);
}
public boolean isDoubleArrayType(Type type) {
return (type == this.svd.casMetadata.ts.doubleArrayType);
}
public boolean isFSArrayType(Type type) {
return (type == this.svd.casMetadata.ts.fsArrayType);
}
public boolean isIntType(Type type) {
return (type == this.svd.casMetadata.ts.intType);
}
public boolean isFloatType(Type type) {
return (type == this.svd.casMetadata.ts.floatType);
}
public boolean isStringType(int type) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
return ts.subsumes(TypeSystemImpl.stringTypeCode, type);
}
public boolean isByteType(Type type) {
return (type == this.svd.casMetadata.ts.byteType);
}
public boolean isBooleanType(Type type) {
return (type == this.svd.casMetadata.ts.booleanType);
}
public boolean isShortType(Type type) {
return (type == this.svd.casMetadata.ts.shortType);
}
public boolean isLongType(Type type) {
return (type == this.svd.casMetadata.ts.longType);
}
public boolean isDoubleType(Type type) {
return (type == this.svd.casMetadata.ts.doubleType);
}
public boolean isAbstractArrayType(int type) {
return this.svd.casMetadata.ts.subsumes(TypeSystemImpl.arrayBaseTypeCode, type);
}
public boolean isArrayType(int type) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
return ts.ll_isArrayType(type);
}
public boolean isIntArrayType(int type) {
return (type == TypeSystemImpl.intArrayTypeCode);
}
public boolean isFloatArrayType(int type) {
return (type == TypeSystemImpl.floatArrayTypeCode);
}
public boolean isStringArrayType(int type) {
return (type == TypeSystemImpl.stringArrayTypeCode);
}
public boolean isByteArrayType(int type) {
return (type == TypeSystemImpl.byteArrayTypeCode);
}
public boolean isBooleanArrayType(int type) {
return (type == TypeSystemImpl.booleanArrayTypeCode);
}
public boolean isShortArrayType(int type) {
return (type == TypeSystemImpl.shortArrayTypeCode);
}
public boolean isLongArrayType(int type) {
return (type == TypeSystemImpl.longArrayTypeCode);
}
public boolean isDoubleArrayType(int type) {
return (type == TypeSystemImpl.doubleArrayTypeCode);
}
public boolean isFSArrayType(int type) {
return (type == TypeSystemImpl.fsArrayTypeCode);
}
public boolean isIntType(int type) {
return (type == TypeSystemImpl.intTypeCode);
}
public boolean isFloatType(int type) {
return (type == TypeSystemImpl.floatTypeCode);
}
public boolean isByteType(int type) {
return (type == TypeSystemImpl.byteTypeCode);
}
public boolean isBooleanType(int type) {
return (type == TypeSystemImpl.booleanTypeCode);
}
public boolean isShortType(int type) {
return (type == TypeSystemImpl.shortTypeCode);
}
public boolean isLongType(int type) {
return (type == TypeSystemImpl.longTypeCode);
}
public boolean isDoubleType(int type) {
return (type == TypeSystemImpl.doubleTypeCode);
}
public Heap getHeap() {
return this.svd.heap;
}
ByteHeap getByteHeap() {
return this.svd.byteHeap;
}
ShortHeap getShortHeap() {
return this.svd.shortHeap;
}
LongHeap getLongHeap() {
return this.svd.longHeap;
}
StringHeap getStringHeap() {
return this.svd.stringHeap;
}
public int getFeatureOffset(int feat) {
if ((feat < 1) || (feat >= this.svd.casMetadata.featureOffset.length)) {
return -1;
}
return this.svd.casMetadata.featureOffset[feat];
}
public static void setupTSDefault(TypeSystemImpl ts) {
// because historically this method was public, protect
// against user code calling multiple times
if (ts.areBuiltInTypesSetup) {
return;
}
synchronized (ts) {
if (ts.areBuiltInTypesSetup) {
return;
}
// W A R N I N G (July 2007)
// C++ code has "hard-wired" the type code numbers for the
// built-in types, so you cannot change the order of the types
// Also, the complete serialization depends on the type-code numbers
// for the client and the server for the built-in types being
// the same.
// The initialization code for types cannot depend on the type system
// having already been set up, because, obviously, it isn't set up (yet).
// It is important to add types in a particular order and to set
// ts.xxx<type-name> and ts.xxx<type-name>code values so they are
// set before they're used. Some of the add-type logic is written
// to depend on the built-in types already having these values set.
// For example: addType ( ARRAY_BASE ) calls, eventually,
// ts.ll_isPrimitiveType -> ll_isRefType ->ll_getTypeClass -> ll_subsumes
// and along the way these are testing / comparing against type codes
// for built-in types which need to have been set.
// Create top type.
Type top = ts.addTopType(CAS.TYPE_NAME_TOP);
// Add basic data types.
Type intT = ts.addType(CAS.TYPE_NAME_INTEGER, top);
ts.intType = (TypeImpl) intT;
if (TypeSystemImpl.intTypeCode != ts.intType.getCode()) throw new RuntimeException();
Type floatT = ts.addType(CAS.TYPE_NAME_FLOAT, top);
ts.floatType = (TypeImpl) floatT;
if (TypeSystemImpl.floatTypeCode != ts.floatType.getCode()) throw new RuntimeException();
Type stringT = ts.addType(CAS.TYPE_NAME_STRING, top);
ts.stringType = (TypeImpl) stringT;
if (TypeSystemImpl.stringTypeCode != ts.stringType.getCode()) throw new RuntimeException();
// Add arrays.
Type array = ts.addType(CAS.TYPE_NAME_ARRAY_BASE, top);
ts.arrayBaseType = (TypeImpl) array; // do here - used in next
if (TypeSystemImpl.arrayBaseTypeCode != ts.arrayBaseType.getCode()) throw new RuntimeException();
TypeImpl fsArray = ts.fsArrayType = (TypeImpl) ts.addType(CAS.TYPE_NAME_FS_ARRAY, array);
if (TypeSystemImpl.fsArrayTypeCode != fsArray.getCode()) throw new RuntimeException();
TypeImpl floatArray = ts.floatArrayType = (TypeImpl) ts.addType(CAS.TYPE_NAME_FLOAT_ARRAY, array);
if (TypeSystemImpl.floatArrayTypeCode != floatArray.getCode()) throw new RuntimeException();
TypeImpl intArray = ts.intArrayType = (TypeImpl) ts.addType(CAS.TYPE_NAME_INTEGER_ARRAY, array);
if (TypeSystemImpl.intArrayTypeCode != intArray.getCode()) throw new RuntimeException();
TypeImpl stringArray = ts.stringArrayType = (TypeImpl) ts.addType(CAS.TYPE_NAME_STRING_ARRAY, array);
if (TypeSystemImpl.stringArrayTypeCode != stringArray.getCode()) throw new RuntimeException();
// Add lists.
Type list = ts.addType(CAS.TYPE_NAME_LIST_BASE, top);
// FS lists.
Type fsList = ts.addType(CAS.TYPE_NAME_FS_LIST, list);
Type fsEList = ts.addType(CAS.TYPE_NAME_EMPTY_FS_LIST, fsList);
Type fsNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_FS_LIST, fsList);
ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, fsNeList, top, true);
ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, fsNeList, fsList, true);
// Float lists.
Type floatList = ts.addType(CAS.TYPE_NAME_FLOAT_LIST, list);
Type floatEList = ts.addType(CAS.TYPE_NAME_EMPTY_FLOAT_LIST, floatList);
Type floatNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_FLOAT_LIST, floatList);
ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, floatNeList, floatT, false);
ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, floatNeList, floatList, true);
// Integer lists.
Type intList = ts.addType(CAS.TYPE_NAME_INTEGER_LIST, list);
Type intEList = ts.addType(CAS.TYPE_NAME_EMPTY_INTEGER_LIST, intList);
Type intNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_INTEGER_LIST, intList);
ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, intNeList, intT, false);
ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, intNeList, intList, true);
// String lists.
Type stringList = ts.addType(CAS.TYPE_NAME_STRING_LIST, list);
Type stringEList = ts.addType(CAS.TYPE_NAME_EMPTY_STRING_LIST, stringList);
Type stringNeList = ts.addType(CAS.TYPE_NAME_NON_EMPTY_STRING_LIST, stringList);
ts.addFeature(CAS.FEATURE_BASE_NAME_HEAD, stringNeList, stringT, false);
ts.addFeature(CAS.FEATURE_BASE_NAME_TAIL, stringNeList, stringList, true);
Type booleanT = ts.addType(CAS.TYPE_NAME_BOOLEAN, top);
ts.booleanType = (TypeImpl) booleanT;
if (TypeSystemImpl.booleanTypeCode != ts.booleanType.getCode()) throw new RuntimeException();
Type byteT = ts.addType(CAS.TYPE_NAME_BYTE, top);
ts.byteType = (TypeImpl) byteT;
if (TypeSystemImpl.byteTypeCode != ts.byteType.getCode()) throw new RuntimeException();
Type shortT = ts.addType(CAS.TYPE_NAME_SHORT, top);
ts.shortType = (TypeImpl) shortT;
if (TypeSystemImpl.shortTypeCode != ts.shortType.getCode()) throw new RuntimeException();
Type longT = ts.addType(CAS.TYPE_NAME_LONG, top);
ts.longType = (TypeImpl) longT;
if (TypeSystemImpl.longTypeCode != ts.longType.getCode()) throw new RuntimeException();
Type doubleT = ts.addType(CAS.TYPE_NAME_DOUBLE, top);
ts.doubleType = (TypeImpl) doubleT;
if (TypeSystemImpl.doubleTypeCode != ts.doubleType.getCode()) throw new RuntimeException();
// array type initialization must follow the component type it's based on
TypeImpl booleanArray = ts.booleanArrayType = (TypeImpl) ts.addType(CAS.TYPE_NAME_BOOLEAN_ARRAY, array);
if (TypeSystemImpl.booleanArrayTypeCode != booleanArray.getCode()) throw new RuntimeException();
TypeImpl byteArray = ts.byteArrayType = (TypeImpl) ts.addType(CAS.TYPE_NAME_BYTE_ARRAY, array);
if (TypeSystemImpl.byteArrayTypeCode != byteArray.getCode()) throw new RuntimeException();
TypeImpl shortArray = ts.shortArrayType = (TypeImpl) ts.addType(CAS.TYPE_NAME_SHORT_ARRAY, array);
if (TypeSystemImpl.shortArrayTypeCode != shortArray.getCode()) throw new RuntimeException();
TypeImpl longArray = ts.longArrayType = (TypeImpl) ts.addType(CAS.TYPE_NAME_LONG_ARRAY, array);
if (TypeSystemImpl.longArrayTypeCode != longArray.getCode()) throw new RuntimeException();
TypeImpl doubleArray = ts.doubleArrayType = (TypeImpl) ts.addType(CAS.TYPE_NAME_DOUBLE_ARRAY, array);
if (TypeSystemImpl.doubleArrayTypeCode != doubleArray.getCode()) throw new RuntimeException();
// Sofa Stuff
Type sofa = ts.addType(CAS.TYPE_NAME_SOFA, top);
ts.sofaType = (TypeImpl) sofa;
if (TypeSystemImpl.sofaTypeCode != ts.sofaType.getCode()) throw new RuntimeException();
ts.addFeature(CAS.FEATURE_BASE_NAME_SOFANUM, sofa, intT, false);
ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAID, sofa, stringT, false);
ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAMIME, sofa, stringT, false);
// Type localSofa = ts.addType(CAS.TYPE_NAME_LOCALSOFA, sofa);
ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAARRAY, sofa, top, true);
ts.addFeature(CAS.FEATURE_BASE_NAME_SOFASTRING, sofa, stringT, false);
// Type remoteSofa = ts.addType(CAS.TYPE_NAME_REMOTESOFA, sofa);
ts.addFeature(CAS.FEATURE_BASE_NAME_SOFAURI, sofa, stringT, false);
// Annotations
Type annotBaseType = ts.addType(CAS.TYPE_NAME_ANNOTATION_BASE, top);
ts.annotBaseType = (TypeImpl) annotBaseType;
if (TypeSystemImpl.annotBaseTypeCode != ts.annotBaseType.getCode()) throw new RuntimeException();
ts.addFeature(CAS.FEATURE_BASE_NAME_SOFA, annotBaseType, sofa, false);
Type annotType = ts.addType(CAS.TYPE_NAME_ANNOTATION, annotBaseType);
ts.annotType = (TypeImpl) annotType;
if (TypeSystemImpl.annotTypeCode != ts.annotType.getCode()) throw new RuntimeException();
ts.addFeature(CAS.FEATURE_BASE_NAME_BEGIN, annotType, intT, false);
ts.addFeature(CAS.FEATURE_BASE_NAME_END, annotType, intT, false);
Type docType = ts.addType(CAS.TYPE_NAME_DOCUMENT_ANNOTATION, annotType);
ts.docType = (TypeImpl) docType;
ts.addFeature(CAS.FEATURE_BASE_NAME_LANGUAGE, docType, stringT, false);
// Lock individual types.
setTypeFinal(intT);
setTypeFinal(floatT);
setTypeFinal(stringT);
((TypeImpl) top).setFeatureFinal();
setTypeFinal(array);
setTypeFinal(fsArray);
setTypeFinal(intArray);
setTypeFinal(floatArray);
setTypeFinal(stringArray);
setTypeFinal(sofa);
setTypeFinal(byteT);
setTypeFinal(booleanT);
setTypeFinal(shortT);
setTypeFinal(longT);
setTypeFinal(doubleT);
setTypeFinal(booleanArray);
setTypeFinal(byteArray);
setTypeFinal(shortArray);
setTypeFinal(longArray);
setTypeFinal(doubleArray);
((TypeImpl) list).setFeatureFinal();
((TypeImpl) fsList).setFeatureFinal();
((TypeImpl) fsEList).setFeatureFinal();
((TypeImpl) fsNeList).setFeatureFinal();
((TypeImpl) floatList).setFeatureFinal();
((TypeImpl) floatEList).setFeatureFinal();
((TypeImpl) floatNeList).setFeatureFinal();
((TypeImpl) intList).setFeatureFinal();
((TypeImpl) intEList).setFeatureFinal();
((TypeImpl) intNeList).setFeatureFinal();
((TypeImpl) stringList).setFeatureFinal();
((TypeImpl) stringEList).setFeatureFinal();
((TypeImpl) stringNeList).setFeatureFinal();
((TypeImpl) annotType).setFeatureFinal();
((TypeImpl) annotBaseType).setFeatureFinal();
// because this is volatile, there's a memory barrier that insures
// the things before happen before other reads
// see http://stackoverflow.com/questions/13688697/is-a-write-to-a-volatile-a-memory-barrier-in-java
ts.areBuiltInTypesSetup = true;
} // end of sync block
}
private static void setTypeFinal(Type type) {
TypeImpl t = (TypeImpl) type;
t.setFeatureFinal();
t.setInheritanceFinal();
}
/*
* Only called on base CAS
*/
/**
* @see org.apache.uima.cas.admin.CASMgr#initCASIndexes()
*/
public void initCASIndexes() throws CASException {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
if (!ts.isCommitted()) {
throw new CASException(CASException.MUST_COMMIT_TYPE_SYSTEM, null);
}
FSIndexComparator comp = this.indexRepository.createComparator();
comp.setType(ts.sofaType);
comp.addKey(ts.sofaNum, FSIndexComparator.STANDARD_COMPARE);
this.indexRepository.createIndex(comp, CAS.SOFA_INDEX_NAME, FSIndex.BAG_INDEX);
comp = this.indexRepository.createComparator();
comp.setType(ts.annotType);
comp.addKey(ts.startFeat, FSIndexComparator.STANDARD_COMPARE);
comp.addKey(ts.endFeat, FSIndexComparator.REVERSE_STANDARD_COMPARE);
comp.addKey(this.indexRepository.getDefaultTypeOrder(), FSIndexComparator.STANDARD_COMPARE);
this.indexRepository.createIndex(comp, CAS.STD_ANNOTATION_INDEX);
}
ArrayList<String> getStringTable() {
// return this.stringList;
return this.svd.baseCAS.getStringList();
}
// ///////////////////////////////////////////////////////////////////////////
// CAS support ... create CAS view of aSofa
// For internal use only
public CAS getView(int sofaNum) {
return getViewFromSofaNbr(sofaNum);
}
public CAS getCurrentView() {
return getView(CAS.NAME_DEFAULT_SOFA);
}
// ///////////////////////////////////////////////////////////////////////////
// JCas support
public JCas getJCas() throws CASException {
if (this.jcas == null) {
this.jcas = JCasImpl.getJCas(this);
}
return this.jcas;
}
/**
* Internal use only
*
* @return corresponding JCas, assuming it exists
*/
public JCas getExistingJCas() {
return this.jcas;
}
// Create JCas view of aSofa
public JCas getJCas(SofaFS aSofa) throws CASException {
// Create base JCas, if needed
this.svd.baseCAS.getJCas();
return getView(aSofa).getJCas();
/*
* // If a JCas already exists for this Sofa, return it JCas aJCas = (JCas)
* this.svd.baseCAS.sofa2jcasMap.get(Integer.valueOf(aSofa.getSofaRef())); if
* (null != aJCas) { return aJCas; } // Get view of aSofa CASImpl view =
* (CASImpl) getView(aSofa); // wrap in JCas aJCas = view.getJCas();
* this.sofa2jcasMap.put(Integer.valueOf(aSofa.getSofaRef()), aJCas); return
* aJCas;
*/
}
/**
* @deprecated
*/
@Deprecated
public JCas getJCas(SofaID aSofaID) throws CASException {
SofaFS sofa = getSofa(aSofaID);
// sofa guaranteed to be non-null by above method.
return getJCas(sofa);
}
private CAS getViewFromSofaNbr(int nbr) {
final ArrayList<CAS> sn2v = this.svd.sofaNbr2ViewMap;
if (nbr < sn2v.size()) {
return sn2v.get(nbr);
}
return null;
}
private void setViewForSofaNbr(int nbr, CAS view) {
ArrayList<CAS> sn2v = this.svd.sofaNbr2ViewMap;
// cant use ensure capacity here
while (sn2v.size() <= nbr) {
sn2v.add(null);
}
sn2v.set(nbr, view);
}
// For internal platform use only
CAS getInitialView() {
CAS couldBeThis = getViewFromSofaNbr(1);
if (couldBeThis != null) {
return couldBeThis;
}
// create the initial view, without a Sofa
CAS aView = new CASImpl(this.svd.baseCAS, null, this.isUsedJcasCache);
setViewForSofaNbr(1, aView);
assert (this.svd.viewCount <= 1);
this.svd.viewCount = 1;
return aView;
}
public CAS createView(String aSofaID) {
// do sofa mapping for current component
String absoluteSofaName = null;
if (getCurrentComponentInfo() != null) {
absoluteSofaName = getCurrentComponentInfo().mapToSofaID(aSofaID);
}
if (absoluteSofaName == null) {
absoluteSofaName = aSofaID;
}
// Can't use name of Initial View
if (CAS.NAME_DEFAULT_SOFA.equals(absoluteSofaName)) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.SOFANAME_ALREADY_EXISTS,
new String[] { aSofaID });
throw e;
}
SofaFS newSofa = createSofa(absoluteSofaName, null);
CAS newView = getView(newSofa);
((CASImpl) newView).registerView(newSofa);
return newView;
}
public CAS getView(String aSofaID) {
// do sofa mapping for current component
String absoluteSofaName = null;
if (getCurrentComponentInfo() != null) {
absoluteSofaName = getCurrentComponentInfo().mapToSofaID(aSofaID);
}
if (absoluteSofaName == null) {
absoluteSofaName = aSofaID;
}
// if this resolves to the Initial View, return view(1)...
// ... as the Sofa for this view may not exist yet
if (CAS.NAME_DEFAULT_SOFA.equals(absoluteSofaName)) {
return getInitialView();
}
// get Sofa and switch to view
SofaFS sofa = getSofa(absoluteSofaName);
// sofa guaranteed to be non-null by above method
// unless sofa doesn't exist, which will cause a throw.
return getView(sofa);
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.CAS#getView(org.apache.uima.cas.SofaFS)
*
* Callers of this can have created Sofas in the CAS without views: using the
* old deprecated createSofa apis (this is being fixed so these will create
* the views) via deserialization, which will put the sofaFSs into the CAS
* without creating the views, and then call this to create the views. - for
* deserialization: there are 2 kinds: 1 is xmi the other is binary. - for
* xmi: there is 1.4.x compatible and 2.1 compatible. The older format can
* have sofaNbrs in the order 2, 3, 4, 1 (initial sofa), 5, 6, 7 The newer
* format has them in order. For deserialized sofas, we insure here that there
* are no duplicates. This is not done in the deserializers - they use either
* heap dumping (binary) or generic fs creators (xmi).
*
* Goal is to detect case where check is needed (sofa exists, but view not yet
* created). This is done by looking for cases where sofaNbr &gt; curViewCount.
* This only works if the sofaNbrs go up by 1 (except for the initial sofa) in
* the input sequence of calls.
*/
public CAS getView(SofaFS aSofa) {
final int sofaNbr = aSofa.getSofaRef();
// final Integer sofaNbrInteger = Integer.valueOf(sofaNbr);
CASImpl aView = (CASImpl) getViewFromSofaNbr(sofaNbr);
if (null == aView) {
// This is the deserializer case, or the case where an older API created a
// sofa,
// which is now creating the associated view
// create a new CAS view
aView = new CASImpl(this.svd.baseCAS, aSofa, this.isUsedJcasCache);
setViewForSofaNbr(sofaNbr, aView);
verifySofaNameUniqueIfDeserializedViewAdded(sofaNbr, aSofa);
return aView;
}
// for deserialization - might be reusing a view, and need to tie new Sofa
// to old View
if (0 == aView.mySofaRef) {
aView.mySofaRef = ((FeatureStructureImpl) aSofa).getAddress();
}
verifySofaNameUniqueIfDeserializedViewAdded(sofaNbr, aSofa);
return aView;
}
boolean isSofaView(int sofaAddr) {
if (mySofaRef == -1) {
// don't create initial sofa
return false;
}
return mySofaRef == sofaAddr;
}
/*
* for Sofas being added (determined by sofaNbr &gt; curViewCount): verify sofa
* name is not already present, and record it for future tests
*
* Only should do the name test & update in the case of deserialized new sofas
* coming in. These will come in, in order. Exception is "_InitialView" which
* could come in the middle. If it comes in the middle, no test will be done
* for duplicates, and it won't be added to set of known names. This is ok
* because the createVIew special cases this test. Users could corrupt an xmi
* input, which would make this logic fail.
*/
private void verifySofaNameUniqueIfDeserializedViewAdded(int sofaNbr, SofaFS aSofa) {
final int curViewCount = this.svd.viewCount;
if (curViewCount < sofaNbr) {
// Only true for deserialized sofas with new views being either created,
// or
// hooked-up from CASes that were freshly reset, which have multiple
// views.
// Assume sofa numbers are incrementing by 1
assert (sofaNbr == curViewCount + 1);
this.svd.viewCount = sofaNbr;
String id = aSofa.getSofaID();
// final Feature idFeat =
// getTypeSystem().getFeatureByFullName(CAS.FEATURE_FULL_NAME_SOFAID);
// String id =
// ll_getStringValue(((FeatureStructureImpl)aSofa).getAddress(),
// ((FeatureImpl) idFeat).getCode());
if (this.svd.sofaNameSet.contains(id)) {
CASRuntimeException e = new CASRuntimeException(
CASRuntimeException.SOFANAME_ALREADY_EXISTS, new String[] { id });
throw e;
}
this.svd.sofaNameSet.add(id);
}
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelCAS#ll_getTypeSystem()
*/
public LowLevelTypeSystem ll_getTypeSystem() {
return this.svd.casMetadata.ts.getLowLevelTypeSystem();
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelCAS#ll_getIndexRepository()
*/
public LowLevelIndexRepository ll_getIndexRepository() {
return this.indexRepository;
}
private final void checkLowLevelParams(int fsRef, int domType, int ranType, int feat) {
checkTypeAt(domType, fsRef);
checkFeature(feat);
checkTypingConditions(domType, ranType, feat);
}
private final void checkLowLevelParams(int fsRef, int domType, int feat) {
checkTypeAt(domType, fsRef);
checkFeature(feat);
checkDomTypeConditions(domType, feat);
}
private final void checkDomTypeConditions(int domTypeCode, int featCode) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
if (!ts.isApprop(domTypeCode, featCode)) {
LowLevelException e = new LowLevelException(LowLevelException.FEAT_DOM_ERROR);
e.addArgument(Integer.toString(domTypeCode));
e.addArgument(ts.ll_getTypeForCode(domTypeCode).getName());
e.addArgument(Integer.toString(featCode));
e.addArgument(ts.ll_getFeatureForCode(featCode).getName());
throw e;
}
}
/**
* Check the range is appropriate for this type/feature. Throws
* LowLevelException if it isn't.
*
* @param domType
* domain type
* @param ranType
* range type
* @param feat
* feature
*/
public final void checkTypingConditions(Type domType, Type ranType, Feature feat) {
checkTypingConditions(((TypeImpl) domType).getCode(), ((TypeImpl) ranType).getCode(),
((FeatureImpl) feat).getCode());
}
// Assumes that parameters are valid type system codes, so check that first.
private final void checkTypingConditions(int domTypeCode, int ranTypeCode, int featCode) {
checkDomTypeConditions(domTypeCode, featCode);
final TypeSystemImpl ts = this.svd.casMetadata.ts;
if (!ts.subsumes(ts.range(featCode), ranTypeCode)) {
LowLevelException e = new LowLevelException(LowLevelException.FEAT_RAN_ERROR);
e.addArgument(Integer.toString(featCode));
e.addArgument(ts.ll_getFeatureForCode(featCode).getName());
e.addArgument(Integer.toString(ranTypeCode));
e.addArgument(ts.ll_getTypeForCode(ranTypeCode).getName());
throw e;
}
}
private final void checkFsRan(int featCode) throws LowLevelException {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
final int rangeTypeCode = ts.range(featCode);
if (!ll_isRefType(rangeTypeCode)) {
LowLevelException e = new LowLevelException(LowLevelException.FS_RAN_TYPE_ERROR);
e.addArgument(Integer.toString(featCode));
e.addArgument(ts.ll_getFeatureForCode(featCode).getName());
e.addArgument(ts.ll_getTypeForCode(rangeTypeCode).getName());
throw e;
}
}
private final void checkFeature(int featureCode) {
if (!this.svd.casMetadata.ts.isFeature(featureCode)) {
LowLevelException e = new LowLevelException(LowLevelException.INVALID_FEATURE_CODE);
e.addArgument(Integer.toString(featureCode));
throw e;
}
}
private final void checkTypeAt(int typeCode, int fsRef) {
if (!this.svd.casMetadata.ts.isType(typeCode)) {
LowLevelException e = new LowLevelException(LowLevelException.VALUE_NOT_A_TYPE);
e.addArgument(Integer.toString(typeCode));
e.addArgument(Integer.toString(fsRef));
throw e;
}
}
final void checkFsRef(int fsRef) {
if ((fsRef <= NULL_FS_REF) || (fsRef >= this.getHeap().heap.length)) {
LowLevelException e = new LowLevelException(LowLevelException.INVALID_FS_REF);
e.addArgument(Integer.toString(fsRef));
throw e;
}
}
public final boolean ll_isRefType(int typeCode) {
if ((typeCode == TypeSystemImpl.intTypeCode) || (typeCode == TypeSystemImpl.floatTypeCode)
|| (typeCode == TypeSystemImpl.stringTypeCode) || (typeCode == TypeSystemImpl.byteTypeCode)
|| (typeCode == TypeSystemImpl.booleanTypeCode) || (typeCode == TypeSystemImpl.shortTypeCode)
|| (typeCode == TypeSystemImpl.longTypeCode) || (typeCode == TypeSystemImpl.doubleTypeCode)) {
return false;
}
if (ll_getTypeSystem().ll_isStringSubtype(typeCode)) {
return false;
}
return true;
}
public final int ll_getTypeClass(int typeCode) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
if (typeCode == TypeSystemImpl.intTypeCode) {
return TYPE_CLASS_INT;
}
if (typeCode == TypeSystemImpl.floatTypeCode) {
return TYPE_CLASS_FLOAT;
}
if (ts.subsumes(TypeSystemImpl.stringTypeCode, typeCode)) {
return TYPE_CLASS_STRING;
}
if (typeCode == TypeSystemImpl.intArrayTypeCode) {
return TYPE_CLASS_INTARRAY;
}
if (typeCode == TypeSystemImpl.floatArrayTypeCode) {
return TYPE_CLASS_FLOATARRAY;
}
if (typeCode == TypeSystemImpl.stringArrayTypeCode) {
return TYPE_CLASS_STRINGARRAY;
}
if (typeCode == TypeSystemImpl.fsArrayTypeCode) {
return TYPE_CLASS_FSARRAY;
}
if (typeCode == TypeSystemImpl.booleanTypeCode) {
return TYPE_CLASS_BOOLEAN;
}
if (typeCode == TypeSystemImpl.byteTypeCode) {
return TYPE_CLASS_BYTE;
}
if (typeCode == TypeSystemImpl.shortTypeCode) {
return TYPE_CLASS_SHORT;
}
if (typeCode == TypeSystemImpl.longTypeCode) {
return TYPE_CLASS_LONG;
}
if (typeCode == TypeSystemImpl.doubleTypeCode) {
return TYPE_CLASS_DOUBLE;
}
if (typeCode == TypeSystemImpl.booleanArrayTypeCode) {
return TYPE_CLASS_BOOLEANARRAY;
}
if (typeCode == TypeSystemImpl.byteArrayTypeCode) {
return TYPE_CLASS_BYTEARRAY;
}
if (typeCode == TypeSystemImpl.shortArrayTypeCode) {
return TYPE_CLASS_SHORTARRAY;
}
if (typeCode == TypeSystemImpl.longArrayTypeCode) {
return TYPE_CLASS_LONGARRAY;
}
if (typeCode == TypeSystemImpl.doubleArrayTypeCode) {
return TYPE_CLASS_DOUBLEARRAY;
}
if (isArrayType(typeCode)) {
return TYPE_CLASS_FSARRAY;
}
return TYPE_CLASS_FS;
}
public final int ll_createFS(int typeCode) {
final int fsAddr = this.getHeap().add(this.svd.casMetadata.fsSpaceReq[typeCode], typeCode);
svd.cache_not_in_index = fsAddr;
if (traceFSs) {
traceFSCreate((FeatureStructureImpl) ll_getFSForRef(fsAddr));
}
return fsAddr;
}
public final int ll_createFS(int typeCode, boolean doCheck) {
if (doCheck) {
if (!this.svd.casMetadata.ts.isType(typeCode) || !isCreatableType(typeCode)) {
LowLevelException e = new LowLevelException(LowLevelException.CREATE_FS_OF_TYPE_ERROR);
e.addArgument(Integer.toString(typeCode));
throw e;
}
}
return ll_createFS(typeCode);
}
// never called, not used May 2007
// /**
// * Create an instance of a subtype of AnnotationBase.
// *
// * @param typeCode
// * @return An annotation?
// */
// public final int ll_createAnnotationBaseFS(int typeCode) {
// int addr = ll_createFS(typeCode);
// setSofaFeat(addr, this.mySofaRef);
// return addr;
// }
// never called, not used May 2007
// public final int ll_createAnnotationBaseFS(int typeCode, boolean doCheck) {
// if (doCheck) {
// final TypeSystemImpl ts = this.svd.casMetadata.ts;
// if (!ts.isType(typeCode) || !isCreatableType(typeCode)
// || ts.ll_subsumes(ts.annotBaseTypeCode, typeCode)) {
// LowLevelException e = new
// LowLevelException(LowLevelException.CREATE_FS_OF_TYPE_ERROR);
// e.addArgument(Integer.toString(typeCode));
// throw e;
// }
// }
// return ll_createFS(typeCode);
// }
/**
* Create a temporary (i.e., per document) array FS on the heap.
*
* @param type
* The type code of the array to be created.
* @param len
* The length of the array to be created.
* @return -
* @exception ArrayIndexOutOfBoundsException
* If <code>type</code> is not a type.
*/
public int createTempArray(int type, int len) {
return ll_createArray(type, len);
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelCAS#ll_createArray(int, int)
*/
public int ll_createArray(int typeCode, int arrayLength) {
final int addr = this.getHeap().add(arrayContentOffset + arrayLength, typeCode);
this.getHeap().heap[(addr + arrayLengthFeatOffset)] = arrayLength;
svd.cache_not_in_index = addr;
if (traceFSs) {
traceFSCreate((FeatureStructureImpl) ll_getFSForRef(addr));
}
return addr;
}
public int ll_createAuxArray(int typeCode, int arrayLength) {
final int addr = this.getHeap().add(arrayContentOffset + 1, typeCode);
this.getHeap().heap[(addr + arrayLengthFeatOffset)] = arrayLength;
svd.cache_not_in_index = addr;
if (traceFSs) {
traceFSCreate((FeatureStructureImpl) ll_getFSForRef(addr));
}
return addr;
}
public int ll_createByteArray(int arrayLength) {
final int addr = ll_createAuxArray(TypeSystemImpl.byteArrayTypeCode, arrayLength);
this.getHeap().heap[addr + arrayContentOffset] = this.getByteHeap().reserve(arrayLength);
return addr;
}
public int ll_createBooleanArray(int arrayLength) {
final int addr = ll_createAuxArray(TypeSystemImpl.booleanArrayTypeCode, arrayLength);
this.getHeap().heap[addr + arrayContentOffset] = this.getByteHeap().reserve(arrayLength);
return addr;
}
public int ll_createShortArray(int arrayLength) {
final int addr = ll_createAuxArray(TypeSystemImpl.shortArrayTypeCode, arrayLength);
this.getHeap().heap[addr + arrayContentOffset] = this.getShortHeap().reserve(arrayLength);
return addr;
}
public int ll_createLongArray(int arrayLength) {
final int addr = ll_createAuxArray(TypeSystemImpl.longArrayTypeCode, arrayLength);
this.getHeap().heap[addr + arrayContentOffset] = this.getLongHeap().reserve(arrayLength);
return addr;
}
public int ll_createDoubleArray(int arrayLength) {
final int addr = ll_createAuxArray(TypeSystemImpl.doubleArrayTypeCode, arrayLength);
this.getHeap().heap[addr + arrayContentOffset] = this.getLongHeap().reserve(arrayLength);
return addr;
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelCAS#ll_createArray(int, int, boolean)
*/
public int ll_createArray(int typeCode, int arrayLength, boolean doChecks) {
if (doChecks) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
// Check typeCode, arrayLength
if (!ts.isType(typeCode)) {
LowLevelException e = new LowLevelException(LowLevelException.INVALID_TYPE_ARGUMENT);
e.addArgument(Integer.toString(typeCode));
throw e;
}
if (!isCreatableArrayType(typeCode)) {
LowLevelException e = new LowLevelException(LowLevelException.CREATE_ARRAY_OF_TYPE_ERROR);
e.addArgument(Integer.toString(typeCode));
e.addArgument(ts.ll_getTypeForCode(typeCode).getName());
throw e;
}
if (arrayLength < 0) {
LowLevelException e = new LowLevelException(LowLevelException.ILLEGAL_ARRAY_LENGTH);
e.addArgument(Integer.toString(arrayLength));
throw e;
}
}
return ll_createArray(typeCode, arrayLength);
}
private final boolean isCreatableArrayType(int typeCode) {
final int tc = ll_getTypeClass(typeCode);
return ((tc == TYPE_CLASS_INTARRAY) || (tc == TYPE_CLASS_FLOATARRAY)
|| (tc == TYPE_CLASS_STRINGARRAY) || (tc == TYPE_CLASS_FSARRAY)
|| (tc == TYPE_CLASS_BOOLEANARRAY) || (tc == TYPE_CLASS_BYTEARRAY)
|| (tc == TYPE_CLASS_SHORTARRAY) || (tc == TYPE_CLASS_LONGARRAY) || (tc == TYPE_CLASS_DOUBLEARRAY));
}
public final int ll_getFSRef(FeatureStructure fsImpl) {
if (null == fsImpl) {
return NULL;
}
final FeatureStructureImpl fsi = (FeatureStructureImpl) fsImpl;
if (this != fsi.getCASImpl()) {
if (this.getBaseCAS() != fsi.getCASImpl().getBaseCAS()) {
// https://issues.apache.org/jira/browse/UIMA-3429
throw new CASRuntimeException(CASRuntimeException.DEREF_FS_OTHER_CAS,
new Object[] {fsi.toString(), this.toString() } );
}
}
return fsi.getAddress();
}
@SuppressWarnings("unchecked")
public <T extends FeatureStructure> T ll_getFSForRef(int fsRef) {
// return this.svd.casMetadata.fsClassRegistry.createFS(fsRef, this);
if (fsRef == 0) {
return null;
}
if (this.svd.useFSCache) {
// FS object cache code.
// ***** NOTE: This code has not been maintained and may not work ******
T fs = null;
try {
fs = (T) this.svd.fsArray[fsRef];
} catch (ArrayIndexOutOfBoundsException e) {
// Do nothing. Code below will expand array as needed.
}
if (fs == null) {
fs = (T) this.svd.localFsGenerators[getHeap().heap[fsRef]].createFS(fsRef, this);
// fs =
// this.svd.casMetadata.fsClassRegistry.createFSusingGenerator(fsRef,
// this);
if (fsRef >= this.svd.fsArray.length) {
int newLen = this.svd.fsArray.length * 2;
while (newLen <= fsRef) {
newLen *= 2;
}
FeatureStructure[] newArray = new FeatureStructure[newLen];
System.arraycopy(this.svd.fsArray, 0, newArray, 0, this.svd.fsArray.length);
this.svd.fsArray = newArray;
}
this.svd.fsArray[fsRef] = fs;
}
return fs;
}
return (T) this.svd.localFsGenerators[getHeap().heap[fsRef]].createFS(fsRef, this);
// return this.svd.casMetadata.fsClassRegistry.createFSusingGenerator(fsRef,
// this);
}
public final int ll_getIntValue(int fsRef, int featureCode) {
return this.getHeap().heap[(fsRef + this.svd.casMetadata.featureOffset[featureCode])];
}
public final int ll_getIntValueFeatOffset(int fsRef, int featureOffset) {
return this.getHeap().heap[fsRef + featureOffset];
}
public final float ll_getFloatValue(int fsRef, int featureCode) {
return int2float(ll_getIntValue(fsRef, featureCode));
}
public final String ll_getStringValue(int fsRef, int featureCode) {
return this.getStringHeap().getStringForCode(ll_getIntValue(fsRef, featureCode));
}
public final String ll_getStringValueFeatOffset(int fsRef, int featureOffset) {
return this.getStringHeap().getStringForCode(ll_getIntValueFeatOffset(fsRef, featureOffset));
}
public final int ll_getRefValue(int fsRef, int featureCode) {
return ll_getIntValue(fsRef, featureCode);
}
public final int ll_getRefValueFeatOffset(int fsRef, int featureOffset) {
return ll_getIntValueFeatOffset(fsRef, featureOffset);
}
public final int ll_getIntValue(int fsRef, int featureCode, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.intTypeCode, featureCode);
}
return ll_getIntValue(fsRef, featureCode);
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelCAS#ll_getFloatValue(int, int,
* boolean)
*/
public final float ll_getFloatValue(int fsRef, int featureCode, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.floatTypeCode, featureCode);
}
return ll_getFloatValue(fsRef, featureCode);
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelCAS#ll_getStringValue(int, int,
* boolean)
*/
public final String ll_getStringValue(int fsRef, int featureCode, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.stringTypeCode, featureCode);
}
return ll_getStringValue(fsRef, featureCode);
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelCAS#ll_getRefValue(int, int, boolean)
*/
public final int ll_getRefValue(int fsRef, int featureCode, boolean doTypeChecks) {
if (doTypeChecks) {
checkFsRefConditions(fsRef, featureCode);
}
return ll_getIntValue(fsRef, featureCode);
}
public int ll_getAnnotBegin(int fsRef) {
return ll_getIntValueFeatOffset(fsRef, svd.annotFeatOffset_begin);
}
public int ll_getAnnotEnd(int fsRef) {
return ll_getIntValueFeatOffset(fsRef, svd.annotFeatOffset_end);
}
/**
* This is the method all normal FS feature "setters" call before doing the set operation.
* <p style="margin-left:2em">
* The binary deserializers bypass these setters, and directly update the heap values, so they have
* a different impl to avoid index corruption.
* <p>
* It may do nothing (for performance, it needs to be enabled by a JVM property).
* <p>
* If enabled, it will check if the update may corrupt any index in any view. The check tests
* whether the feature is being used as a key in one or more indexes and if the FS is in one or more
* corruptable view indexes.
* <p>
* If true, then:
* <ul>
* <li>it may remove and remember (for later adding-back) the FS from all corruptable indexes
* (bag indexes are not corruptable via updating, so these are skipped).
* The addback occurs later either via an explicit call to do so, or the end of a protectIndex block, or.
* (if autoIndexProtect is enabled) after the individual feature update is completed.</li>
* <li>it may give a WARN level message to the log. This enables users to
* implement their own optimized handling of this for "high performance"
* applications which do not want the overhead of runtime checking. </li></ul>
* <p>
*
* @param fsRef - the FS to test if it is in the indexes
* @param featureCode - the feature being tested
* @return true if something may need to be added back
*/
private boolean checkForInvalidFeatureSetting(int fsRef, int featureCode) {
if (fsRef == svd.cache_not_in_index) {
return false;
}
final int ssz = svd.fssTobeAddedback.size();
// skip if protection is disabled, an no explicit protection block
if (IS_DISABLED_PROTECT_INDEXES && ssz == 0) {
return false;
}
// next method skips if the fsRef is not in the index (cache)
final boolean wasRemoved = removeFromCorruptableIndexAnyView(
fsRef,
(ssz > 0) ? svd.fssTobeAddedback.get(ssz - 1) :
svd.fsTobeAddedbackSingle,
featureCode);
// skip message if wasn't removed
// skip message if protected in explicit block
if (wasRemoved && IS_REPORT_FS_UPDATE_CORRUPTS_INDEX && ssz == 0) {
featModWhileInIndexReport(fsRef, featureCode);
}
return wasRemoved;
}
private void featModWhileInIndexReport(int fsRef, int featureCode) {
// prepare a message which includes the feature which is a key, the fs, and
// the call stack.
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
new Throwable().printStackTrace(pw);
pw.close();
String msg = String.format(
"While FS was in the index, the feature \"%s\""
+ ", which is used as a key in one or more indexes, "
+ "was modified\n FS = \"%s\"\n%s%n",
this.getTypeSystemImpl().ll_getFeatureForCode(featureCode).getName(),
new FeatureStructureImplC(this, fsRef).toString(),
sw.toString());
UIMAFramework.getLogger().log(Level.WARNING, msg);
if (IS_THROW_EXCEPTION_CORRUPT_INDEX) {
throw new UIMARuntimeException(UIMARuntimeException.ILLEGAL_FS_FEAT_UPDATE, new Object[]{});
}
}
/**
* Do the individual feat update addback if
* a) not in a block mode, and
* b) running with auto protect indexes
* c) not in block-single mode
*
* if running in block mode, the add back is delayed until the end of the block
*
* @param fsRef the fs to add back
*/
private void maybeAddback(int fsRef) {
if (!svd.fsTobeAddedbackSingleInUse && (!IS_DISABLED_PROTECT_INDEXES) && svd.fssTobeAddedback.size() == 0) {
svd.fsTobeAddedbackSingle.addback(fsRef);
}
}
// next two methods dropped - rather than seeing if something is in the index, and then
// later removing it (two lookups), we just conditionally remove it
// /**
// * test if this feature is in a key and the FS is in the index
// * side effect - if the fsRef is determined not to be in the index, this is remembered.
// * @param fsRef - a feature structure which may be in the index
// * @param featCode the feature to test if it is in any key
// * @return true if the fsRef is in the index, and the featureCode is used as a key
// */
// boolean isFeatureAKeyInIndexedFS(int fsRef, int featCode) {
// if (svd.cache_not_in_index == fsRef) { // keep, needed for bin compr deser calls
// return false;
// }
// if (svd.featureCodesInIndexKeys.contains(featCode)) {
// if (isFsInCorruptableIndexAnyView(fsRef)) {
// return true;
// }
// svd.cache_not_in_index = fsRef;
// return false;
// }
// return false;
// }
//
// private boolean isFsInCorruptableIndexAnyView(final int fsRef) {
// final int typeCode = getTypeCode(fsRef);
// final TypeSystemImpl tsi = getTypeSystemImpl();
// if (tsi.isAnnotationBaseOrSubtype(typeCode)) {
// // only need to check one view
// return ll_getSofaCasView(fsRef).indexRepository.isInSetOrSortedIndexInThisView(fsRef);
// }
// // not a subtype of AnnotationBase, need to check all views (except base)
// final Iterator<CAS> viewIterator = getViewIterator();
// while (viewIterator.hasNext()) {
// final CAS view = viewIterator.next();
// if (((FSIndexRepositoryImpl)view.getIndexRepository()).isInSetOrSortedIndexInThisView(fsRef)) {
// return true;
// }
// }
// return false; // not in any view's indexes
// }
/**
* A conditional remove, depends on the featCode being used as a key
* Skip tests if the FS is known not to be in the indexes in any view
*
* @param fsRef the fs
* @param toBeAdded the place to record removal actions
* @param featCode the feature code to test if it's used as a key in some index
* @return true if the fs was removed
*/
boolean removeFromCorruptableIndexAnyView(final int fsRef, FSsTobeAddedback toBeAdded, int featCode) {
if (fsRef != svd.cache_not_in_index && svd.featureCodesInIndexKeys.contains(featCode)) {
boolean wasRemoved = removeFromCorruptableIndexAnyView(fsRef, toBeAdded);
svd.cache_not_in_index = fsRef; // because will remove it if its in the index.
return wasRemoved;
}
return false;
}
/**
* Remove the fsRef from any corruptable index in any view, and remember
* per view whether it was actually in the index.
* @param fsRef -
* @param toBeAdded -
* @return true if it was removed (one or more times)
*/
boolean removeFromCorruptableIndexAnyView(final int fsRef, FSsTobeAddedback toBeAdded) {
final int typeCode = getTypeCode(fsRef);
final TypeSystemImpl tsi = getTypeSystemImpl();
if (tsi.isAnnotationBaseOrSubtype(typeCode)) {
// only need to check one view
// get that view carefully, in case things are not yet properly initialized
final int addrOfSofaFS = this.getSofaFeat(fsRef);
if (addrOfSofaFS == 0) {
return false; // uninitialized sofa ref- can't be indexed
}
CASImpl view;
if (addrOfSofaFS == this.getSofaRef()) {
view = this;
} else {
int sofaNum = ll_getSofaNum(addrOfSofaFS);
view = (CASImpl) getViewFromSofaNbr(sofaNum);
if (null == view) {
return false;
}
}
return removeAndRecord(fsRef, view.indexRepository, toBeAdded);
}
// not a subtype of AnnotationBase, need to check all views (except base)
// sofas indexed in the base view are not corruptable.
final Iterator<CAS> viewIterator = getViewIterator();
boolean wasRemoved = false;
while (viewIterator.hasNext()) {
wasRemoved |= removeAndRecord(fsRef, (FSIndexRepositoryImpl) viewIterator.next().getIndexRepository(), toBeAdded);
}
return wasRemoved;
}
boolean removeFromCorruptableIndexAnyViewSetCache(final int fsRef, FSsTobeAddedback toBeAdded) {
if (fsRef != svd.cache_not_in_index) {
svd.cache_not_in_index = fsRef;
return removeFromCorruptableIndexAnyView(fsRef, toBeAdded);
}
return false;
}
/**
* remove a FS from corruptable indexes in this view
* @param fsRef the fs to be removed
* @param ir the view
* @param toBeAdded the place to record how many times it was in the index, per view
* @return true if it was removed, false if it wasn't in any corruptable index.
*/
private boolean removeAndRecord(int fsRef, FSIndexRepositoryImpl ir, FSsTobeAddedback toBeAdded) {
int nbrRemoved = ir.removeIfInCorrputableIndexInThisView(fsRef);
if (0 < nbrRemoved) {
((FSsTobeAddedback) toBeAdded).recordRemove(fsRef, ir, nbrRemoved);
}
return (0 < nbrRemoved);
}
public final void ll_setIntValue(int fsRef, int featureCode, int value) {
setFeatureValue(fsRef, featureCode, value);
}
public final void ll_setFloatValue(int fsRef, int featureCode, float value) {
setFeatureValue(fsRef, featureCode, float2int(value));
}
// public final void ll_setFloatValueNoIndexCorruptionCheck(int fsRef, int featureCode, float value) {
// setFeatureValueNoIndexCorruptionCheck(fsRef, featureCode, float2int(value));
// }
public final void ll_setStringValue(int fsRef, int featureCode, String value) {
if (null != value) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
String[] stringSet = ts.ll_getStringSet(ts.ll_getRangeType(featureCode));
if (stringSet != null) {
final int rc = Arrays.binarySearch(stringSet, value);
if (rc < 0) {
// Not a legal value.
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.ILLEGAL_STRING_VALUE,
new String[] { value, ts.ll_getTypeForCode(ts.ll_getRangeType(featureCode)).getName() });
throw e;
}
}
}
final int stringAddr = (value == null) ? NULL : this.getStringHeap().addString(value);
setFeatureValue(fsRef, featureCode, stringAddr);
}
public final void ll_setRefValue(int fsRef, int featureCode, int value) {
// no index check because refs can't be keys
setFeatureValueNoIndexCorruptionCheck(fsRef, featureCode, value);
}
public final void ll_setIntValue(int fsRef, int featureCode, int value, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.intTypeCode, featureCode);
}
ll_setIntValue(fsRef, featureCode, value);
}
public final void ll_setFloatValue(int fsRef, int featureCode, float value, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.floatTypeCode, featureCode);
}
ll_setFloatValue(fsRef, featureCode, value);
}
public final void ll_setStringValue(int fsRef, int featureCode, String value, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.stringTypeCode, featureCode);
}
ll_setStringValue(fsRef, featureCode, value);
}
public final void ll_setCharBufferValue(int fsRef, int featureCode, char[] buffer, int start,
int length, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.stringTypeCode, featureCode);
}
ll_setCharBufferValue(fsRef, featureCode, buffer, start, length);
}
public final void ll_setCharBufferValue(int fsRef, int featureCode, char[] buffer, int start,
int length) {
// don't do any index check here, done by inner call
final int stringCode = this.getStringHeap().addCharBuffer(buffer, start, length);
ll_setIntValue(fsRef, featureCode, stringCode);
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelCAS#ll_copyCharBufferValue(int, int,
* char, int)
*/
public int ll_copyCharBufferValue(int fsRef, int featureCode, char[] buffer, int start) {
final int stringCode = ll_getIntValue(fsRef, featureCode);
if (stringCode == NULL) {
return -1;
}
return this.getStringHeap().copyCharsToBuffer(stringCode, buffer, start);
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.impl.LowLevelCAS#ll_getCharBufferValueSize(int,
* int)
*/
public int ll_getCharBufferValueSize(int fsRef, int featureCode) {
final int stringCode = ll_getIntValue(fsRef, featureCode);
if (stringCode == NULL) {
return -1;
}
return this.getStringHeap().getCharArrayLength(stringCode);
}
public final void ll_setRefValue(int fsRef, int featureCode, int value, boolean doTypeChecks) {
if (doTypeChecks) {
checkFsRefConditions(fsRef, featureCode);
checkFsRef(value);
}
ll_setRefValue(fsRef, featureCode, value);
}
public final int ll_getIntArrayValue(int fsRef, int position) {
final int pos = getArrayStartAddress(fsRef) + position;
return this.getHeap().heap[pos];
}
public final float ll_getFloatArrayValue(int fsRef, int position) {
final int pos = getArrayStartAddress(fsRef) + position;
return int2float(this.getHeap().heap[pos]);
}
public final String ll_getStringArrayValue(int fsRef, int position) {
final int pos = getArrayStartAddress(fsRef) + position;
return getStringForCode(this.getHeap().heap[pos]);
}
public final int ll_getRefArrayValue(int fsRef, int position) {
final int pos = getArrayStartAddress(fsRef) + position;
return this.getHeap().heap[pos];
}
// private final void checkTypeSubsumptionAt(int fsRef, int typeCode) {
// if (!this.svd.casMetadata.ts.subsumes(typeCode, ll_getFSRefType(fsRef))) {
// throwAccessTypeError(fsRef, typeCode);
// }
// }
private void throwAccessTypeError(int fsRef, int typeCode) {
LowLevelException e = new LowLevelException(LowLevelException.ACCESS_TYPE_ERROR);
e.addArgument(Integer.toString(fsRef));
e.addArgument(Integer.toString(typeCode));
e.addArgument(this.svd.casMetadata.ts.ll_getTypeForCode(typeCode).getName());
e.addArgument(this.svd.casMetadata.ts.ll_getTypeForCode(ll_getFSRefType(fsRef)).getName());
throw e;
}
public final void checkArrayBounds(int fsRef, int pos) {
final int arrayLength = ll_getArraySize(fsRef);
if ((pos < 0) || (pos >= arrayLength)) {
throw new ArrayIndexOutOfBoundsException(pos);
// LowLevelException e = new LowLevelException(
// LowLevelException.ARRAY_INDEX_OUT_OF_RANGE);
// e.addArgument(Integer.toString(pos));
// throw e;
}
}
public final void checkArrayBounds(int fsRef, int pos, int length) {
final int arrayLength = ll_getArraySize(fsRef);
if ((pos < 0) || (length < 0) || ((pos + length) > arrayLength)) {
LowLevelException e = new LowLevelException(LowLevelException.ARRAY_INDEX_LENGTH_OUT_OF_RANGE);
e.addArgument(Integer.toString(pos));
e.addArgument(Integer.toString(length));
throw e;
}
}
private final void checkNonArrayConditions(int fsRef, int typeCode, int featureCode) {
checkFsRef(fsRef);
// It is now safe to do this.
final int domTypeCode = this.getHeap().heap[fsRef];
checkLowLevelParams(fsRef, domTypeCode, typeCode, featureCode);
checkFsRef(fsRef + this.svd.casMetadata.featureOffset[featureCode]);
}
private final void checkFsRefConditions(int fsRef, int featureCode) {
checkFsRef(fsRef);
final int domTypeCode = this.getHeap().heap[fsRef];
checkLowLevelParams(fsRef, domTypeCode, featureCode);
checkFsRan(featureCode);
checkFsRef(fsRef + this.svd.casMetadata.featureOffset[featureCode]);
}
// private final void checkArrayConditions(int fsRef, int typeCode,
// int position) {
// checkTypeSubsumptionAt(fsRef, typeCode);
// // skip this next test because
// // a) it's done implicitly in the bounds check and
// // b) it fails for arrays stored outside of the main heap (e.g.,
// byteArrays, etc.)
// // checkFsRef(getArrayStartAddress(fsRef) + position);
// checkArrayBounds(fsRef, position);
// }
private final void checkPrimitiveArrayConditions(int fsRef, int typeCode, int position) {
if (typeCode != ll_getFSRefType(fsRef)) {
throwAccessTypeError(fsRef, typeCode);
}
checkArrayBounds(fsRef, position);
}
public final int ll_getIntArrayValue(int fsRef, int position, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.intArrayTypeCode, position);
}
return ll_getIntArrayValue(fsRef, position);
}
public float ll_getFloatArrayValue(int fsRef, int position, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.floatArrayTypeCode, position);
}
return ll_getFloatArrayValue(fsRef, position);
}
public String ll_getStringArrayValue(int fsRef, int position, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.stringArrayTypeCode, position);
}
return ll_getStringArrayValue(fsRef, position);
}
public int ll_getRefArrayValue(int fsRef, int position, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.fsArrayTypeCode, position);
}
return ll_getRefArrayValue(fsRef, position);
}
public void ll_setIntArrayValue(int fsRef, int position, int value, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.intArrayTypeCode, position);
}
ll_setIntArrayValue(fsRef, position, value);
}
public void ll_setFloatArrayValue(int fsRef, int position, float value, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.floatArrayTypeCode, position);
}
ll_setFloatArrayValue(fsRef, position, value);
}
public void ll_setStringArrayValue(int fsRef, int position, String value, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.stringArrayTypeCode, position);
}
ll_setStringArrayValue(fsRef, position, value);
}
public void ll_setRefArrayValue(int fsRef, int position, int value, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.fsArrayTypeCode, position);
checkFsRef(value);
}
ll_setRefArrayValue(fsRef, position, value);
}
public void ll_setIntArrayValue(int fsRef, int position, int value) {
final int pos = getArrayStartAddress(fsRef) + position;
this.getHeap().heap[pos] = value;
if (this.svd.trackingMark != null) {
this.logFSUpdate(fsRef, pos, ModifiedHeap.FSHEAP, 1);
}
}
public void ll_setFloatArrayValue(int fsRef, int position, float value) {
final int pos = getArrayStartAddress(fsRef) + position;
this.getHeap().heap[pos] = float2int(value);
if (this.svd.trackingMark != null) {
this.logFSUpdate(fsRef, pos,ModifiedHeap.FSHEAP, 1);
}
}
public void ll_setStringArrayValue(int fsRef, int position, String value) {
final int pos = getArrayStartAddress(fsRef) + position;
final int stringCode = (value == null) ? NULL : addString(value);
this.getHeap().heap[pos] = stringCode;
if (this.svd.trackingMark != null) {
this.logFSUpdate(fsRef, pos, ModifiedHeap.FSHEAP, 1);
}
}
public void ll_setRefArrayValue(int fsRef, int position, int value) {
final int pos = getArrayStartAddress(fsRef) + position;
this.getHeap().heap[pos] = value;
if (this.svd.trackingMark != null) {
this.logFSUpdate(fsRef, pos, ModifiedHeap.FSHEAP, 1);
}
}
public int ll_getFSRefType(int fsRef) {
return this.getHeap().heap[fsRef];
}
public int ll_getFSRefType(int fsRef, boolean doChecks) {
if (doChecks) {
checkFsRef(fsRef);
checkTypeAt(ll_getFSRefType(fsRef), fsRef);
}
return ll_getFSRefType(fsRef);
}
public LowLevelCAS getLowLevelCAS() {
return this;
}
public int size() {
return this.getHeap().heap.length * 6;
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.admin.CASMgr#getJCasClassLoader()
*/
public ClassLoader getJCasClassLoader() {
return this.svd.jcasClassLoader;
}
/*
* Called to set the overall jcas class loader to use.
*
* @see org.apache.uima.cas.admin.CASMgr#setJCasClassLoader(java.lang.ClassLoader)
*/
public void setJCasClassLoader(ClassLoader classLoader) {
this.svd.previousJCasClassLoader = classLoader;
this.svd.jcasClassLoader = classLoader;
}
// Internal use only, public for cross package use
// Assumes: The JCasClassLoader for a CAS is set up initially when the CAS is
// created
// and not switched (other than by this code) once it is set.
// Callers of this method always code the "restoreClassLoaderUnlockCAS" in
// pairs,
// protected as needed with try - finally blocks.
//
// Special handling is needed for CAS Mulipliers - they can modify a cas up to
// the point they no longer "own" it.
// So the try / finally approach doesn't fit
public void switchClassLoaderLockCas(Object userCode) {
switchClassLoaderLockCasCL(userCode.getClass().getClassLoader());
}
public void switchClassLoaderLockCasCL(ClassLoader newClassLoader) {
// lock out CAS functions to which annotator should not have access
enableReset(false);
switchClassLoader(newClassLoader);
}
// switches ClassLoader but does not lock CAS
public void switchClassLoader(ClassLoader newClassLoader) {
if (null == newClassLoader) { // is null if no cl set
return;
}
if (newClassLoader != this.svd.jcasClassLoader) {
// System.out.println("Switching to new class loader");
this.svd.jcasClassLoader = newClassLoader;
if (null != this.jcas) {
((JCasImpl) this.jcas).switchClassLoader(newClassLoader);
}
}
}
// internal use, public for cross-package ref
public boolean usingBaseClassLoader() {
return (this.svd.jcasClassLoader == this.svd.previousJCasClassLoader);
}
public void restoreClassLoaderUnlockCas() {
// unlock CAS functions
enableReset(true);
// this might be called without the switch ever being called
if (null == this.svd.previousJCasClassLoader) {
return;
}
if (this.svd.previousJCasClassLoader != this.svd.jcasClassLoader) {
// System.out.println("Switching back to previous class loader");
this.svd.jcasClassLoader = this.svd.previousJCasClassLoader;
if (null != this.jcas) {
((JCasImpl) this.jcas).switchClassLoader(this.svd.previousJCasClassLoader);
}
}
}
public FeatureValuePath createFeatureValuePath(String featureValuePath)
throws CASRuntimeException {
return FeatureValuePathImpl.getFeaturePath(featureValuePath);
}
public void setOwner(CasOwner aCasOwner) {
CASImpl baseCas = getBaseCAS();
if (baseCas != this) {
baseCas.setOwner(aCasOwner);
} else {
super.setOwner(aCasOwner);
}
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.AbstractCas_ImplBase#release()
*/
public void release() {
CASImpl baseCas = getBaseCAS();
if (baseCas != this) {
baseCas.release();
} else {
super.release();
}
}
public ByteArrayFS createByteArrayFS(int length) throws CASRuntimeException {
checkArrayPreconditions(length);
return (ByteArrayFS) createFS(ll_createByteArray(length));
}
public BooleanArrayFS createBooleanArrayFS(int length) throws CASRuntimeException {
checkArrayPreconditions(length);
return (BooleanArrayFS) createFS(ll_createBooleanArray(length));
}
public ShortArrayFS createShortArrayFS(int length) throws CASRuntimeException {
checkArrayPreconditions(length);
return (ShortArrayFS) createFS(ll_createShortArray(length));
}
public LongArrayFS createLongArrayFS(int length) throws CASRuntimeException {
checkArrayPreconditions(length);
return (LongArrayFS) createFS(ll_createLongArray(length));
}
public DoubleArrayFS createDoubleArrayFS(int length) throws CASRuntimeException {
checkArrayPreconditions(length);
return (DoubleArrayFS) createFS(ll_createDoubleArray(length));
}
public byte ll_getByteValue(int fsRef, int featureCode) {
return (byte) ll_getIntValue(fsRef, featureCode);
}
public byte ll_getByteValue(int fsRef, int featureCode, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.byteTypeCode, featureCode);
}
return ll_getByteValue(fsRef, featureCode);
}
public boolean ll_getBooleanValue(int fsRef, int featureCode) {
return CASImpl.TRUE == ll_getIntValue(fsRef, featureCode);
}
public boolean ll_getBooleanValue(int fsRef, int featureCode, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.booleanTypeCode, featureCode);
}
return ll_getBooleanValue(fsRef, featureCode);
}
public short ll_getShortValue(int fsRef, int featureCode) {
return (short) (ll_getIntValue(fsRef, featureCode));
}
public short ll_getShortValue(int fsRef, int featureCode, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.shortTypeCode, featureCode);
}
return ll_getShortValue(fsRef, featureCode);
}
public long ll_getLongValue(int offset) {
return this.getLongHeap().getHeapValue(offset);
}
public long ll_getLongValue(int fsRef, int featureCode) {
final int offset = this.getHeap().heap[fsRef + this.svd.casMetadata.featureOffset[featureCode]];
long val = this.getLongHeap().getHeapValue(offset);
return (val);
}
public long ll_getLongValueFeatOffset(int fsRef, int featureOffset) {
final int offset = this.getHeap().heap[fsRef + featureOffset];
long val = this.getLongHeap().getHeapValue(offset);
return (val);
}
public long ll_getLongValue(int fsRef, int featureCode, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.longTypeCode, featureCode);
}
return ll_getLongValue(fsRef, featureCode);
}
public double ll_getDoubleValue(int fsRef, int featureCode) {
final int offset = this.getHeap().heap[fsRef + this.svd.casMetadata.featureOffset[featureCode]];
long val = this.getLongHeap().getHeapValue(offset);
return Double.longBitsToDouble(val);
}
public double ll_getDoubleValueFeatOffset(int fsRef, int featureOffset) {
final int offset = this.getHeap().heap[fsRef + featureOffset];
long val = this.getLongHeap().getHeapValue(offset);
return Double.longBitsToDouble(val);
}
public double ll_getDoubleValue(int fsRef, int featureCode, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.doubleTypeCode, featureCode);
}
return ll_getDoubleValue(fsRef, featureCode);
}
public void ll_setBooleanValue(int fsRef, int featureCode, boolean value) {
setFeatureValue(fsRef, featureCode, value ? CASImpl.TRUE : CASImpl.FALSE);
}
public void ll_setBooleanValue(int fsRef, int featureCode, boolean value, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.booleanTypeCode, featureCode);
}
ll_setBooleanValue(fsRef, featureCode, value);
}
public final void ll_setByteValue(int fsRef, int featureCode, byte value) {
setFeatureValue(fsRef, featureCode, value);
}
public void ll_setByteValue(int fsRef, int featureCode, byte value, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.byteTypeCode, featureCode);
}
ll_setByteValue(fsRef, featureCode, value);
}
public final void ll_setShortValue(int fsRef, int featureCode, short value) {
setFeatureValue(fsRef, featureCode, value);
}
public void ll_setShortValue(int fsRef, int featureCode, short value, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.booleanTypeCode, featureCode);
}
ll_setShortValue(fsRef, featureCode, value);
}
public void ll_setLongValue(int fsRef, int featureCode, long value) {
final int offset = this.getLongHeap().addLong(value);
setFeatureValue(fsRef, featureCode, offset);
}
public void ll_setLongValue(int fsRef, int featureCode, long value, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.longTypeCode, featureCode);
}
ll_setLongValue(fsRef, featureCode, value);
}
public void ll_setDoubleValue(int fsRef, int featureCode, double value) {
long val = Double.doubleToLongBits(value);
final int offset = this.getLongHeap().addLong(val);
setFeatureValue(fsRef, featureCode, offset);
}
public void ll_setDoubleValue(int fsRef, int featureCode, double value, boolean doTypeChecks) {
if (doTypeChecks) {
checkNonArrayConditions(fsRef, TypeSystemImpl.doubleTypeCode, featureCode);
}
ll_setDoubleValue(fsRef, featureCode, value);
}
public byte ll_getByteArrayValue(int fsRef, int position) {
final int pos = this.getHeap().heap[getArrayStartAddress(fsRef)];
return this.getByteHeap().getHeapValue(pos + position);
}
public byte ll_getByteArrayValue(int fsRef, int position, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.byteArrayTypeCode, position);
}
return ll_getByteArrayValue(fsRef, position);
}
public boolean ll_getBooleanArrayValue(int fsRef, int position) {
final int pos = this.getHeap().heap[getArrayStartAddress(fsRef)];
return CASImpl.TRUE == this.getByteHeap().getHeapValue(pos + position);
}
public boolean ll_getBooleanArrayValue(int fsRef, int position, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.booleanArrayTypeCode, position);
}
return ll_getBooleanArrayValue(fsRef, position);
}
public short ll_getShortArrayValue(int fsRef, int position) {
final int pos = this.getHeap().heap[getArrayStartAddress(fsRef)];
return this.getShortHeap().getHeapValue(pos + position);
}
public short ll_getShortArrayValue(int fsRef, int position, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.shortArrayTypeCode, position);
}
return ll_getShortArrayValue(fsRef, position);
}
public long ll_getLongArrayValue(int fsRef, int position) {
final int pos = this.getHeap().heap[getArrayStartAddress(fsRef)];
return this.getLongHeap().getHeapValue(pos + position);
}
public long ll_getLongArrayValue(int fsRef, int position, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.longArrayTypeCode, position);
}
return ll_getLongArrayValue(fsRef, position);
}
public double ll_getDoubleArrayValue(int fsRef, int position) {
final int pos = this.getHeap().heap[getArrayStartAddress(fsRef)];
long val = this.getLongHeap().getHeapValue(pos + position);
return Double.longBitsToDouble(val);
}
public double ll_getDoubleArrayValue(int fsRef, int position, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.doubleArrayTypeCode, position);
}
return ll_getDoubleArrayValue(fsRef, position);
}
public void ll_setByteArrayValue(int fsRef, int position, byte value) {
final int offset = this.getHeap().heap[getArrayStartAddress(fsRef)];
this.getByteHeap().setHeapValue(value, offset + position);
if (this.svd.trackingMark != null) {
this.logFSUpdate(fsRef, offset+position, ModifiedHeap.BYTEHEAP, 1);
}
}
public void ll_setByteArrayValue(int fsRef, int position, byte value, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.byteArrayTypeCode, position);
}
ll_setByteArrayValue(fsRef, position, value);
}
public void ll_setBooleanArrayValue(int fsRef, int position, boolean b) {
byte value = (byte) (b ? CASImpl.TRUE : CASImpl.FALSE);
final int offset = this.getHeap().heap[getArrayStartAddress(fsRef)];
this.getByteHeap().setHeapValue(value, offset + position);
if (this.svd.trackingMark != null) {
this.logFSUpdate(fsRef, offset+position, ModifiedHeap.BYTEHEAP, 1);
}
}
public void ll_setBooleanArrayValue(int fsRef, int position, boolean value, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.booleanArrayTypeCode, position);
}
ll_setBooleanArrayValue(fsRef, position, value);
}
public void ll_setShortArrayValue(int fsRef, int position, short value) {
final int offset = this.getHeap().heap[getArrayStartAddress(fsRef)];
this.getShortHeap().setHeapValue(value, offset + position);
if (this.svd.trackingMark != null) {
this.logFSUpdate(fsRef, offset+position, ModifiedHeap.SHORTHEAP, 1);
}
}
public void ll_setShortArrayValue(int fsRef, int position, short value, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.shortArrayTypeCode, position);
}
ll_setShortArrayValue(fsRef, position, value);
}
public void ll_setLongArrayValue(int fsRef, int position, long value) {
final int offset = this.getHeap().heap[getArrayStartAddress(fsRef)];
this.getLongHeap().setHeapValue(value, offset + position);
if (this.svd.trackingMark != null) {
this.logFSUpdate(fsRef, offset+position, ModifiedHeap.LONGHEAP, 1);
}
}
public void ll_setLongArrayValue(int fsRef, int position, long value, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.longArrayTypeCode, position);
}
ll_setLongArrayValue(fsRef, position, value);
}
public void ll_setDoubleArrayValue(int fsRef, int position, double d) {
final int offset = this.getHeap().heap[getArrayStartAddress(fsRef)];
long value = Double.doubleToLongBits(d);
this.getLongHeap().setHeapValue(value, offset + position);
if (this.svd.trackingMark != null) {
this.logFSUpdate(fsRef, offset+position, ModifiedHeap.LONGHEAP, 1);
}
}
public void ll_setDoubleArrayValue(int fsRef, int position, double value, boolean doTypeChecks) {
if (doTypeChecks) {
checkPrimitiveArrayConditions(fsRef, TypeSystemImpl.doubleArrayTypeCode, position);
}
ll_setDoubleArrayValue(fsRef, position, value);
}
public boolean isAnnotationType(Type t) {
return getTypeSystem().subsumes(getAnnotationType(), t);
}
/**
* @param t the type code to test
* @return true if that type is subsumed by AnnotationBase type
*/
public boolean isSubtypeOfAnnotationBaseType(int t) {
return this.svd.casMetadata.ts.subsumes(TypeSystemImpl.annotBaseTypeCode, t);
}
public AnnotationFS createAnnotation(Type type, int begin, int end) {
if (this == this.svd.baseCAS) {
// Can't create annotation on base CAS
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.INVALID_BASE_CAS_METHOD,
new String[] { "createAnnotation(Type, int, int)" });
throw e;
}
FeatureStructure fs = createFS(type);
final int addr = ll_getFSRef(fs);
// setSofaFeat(addr, this.mySofaRef); // already done by createFS
setFeatureValueNotJournaled(addr, TypeSystemImpl.startFeatCode, begin); // because it's a create - not in index
// setStartFeat(addr, begin);
setFeatureValueNotJournaled(addr, TypeSystemImpl.endFeatCode, end); // because it's a create - not in index
// setEndFeat(addr, end);
return (AnnotationFS) fs;
}
public int ll_createAnnotation(int typeCode, int begin, int end) {
int addr = ll_createFSAnnotCheck(typeCode);
setFeatureValueNotJournaled(addr, TypeSystemImpl.startFeatCode, begin); // because it's a create - not in index
// setStartFeat(addr, begin);
setFeatureValueNotJournaled(addr, TypeSystemImpl.endFeatCode, end); // because it's a create - not in index
return addr;
}
/**
* The generic spec T extends AnnotationFS (rather than AnnotationFS) allows the method
* JCasImpl getAnnotationIndex to return Annotation instead of AnnotationFS
* @param <T> the Java class associated with the annotation index
* @return the annotation index
*/
public <T extends AnnotationFS> AnnotationIndex<T> getAnnotationIndex() {
return new AnnotationIndexImpl<T>(
getIndexRepository().<T>getIndex(
CAS.STD_ANNOTATION_INDEX));
}
/**
* @see org.apache.uima.cas.CAS#getAnnotationIndex(Type)
*/
public <T extends AnnotationFS> AnnotationIndex<T> getAnnotationIndex(Type type) {
return new AnnotationIndexImpl<T>(
getIndexRepository().<T>getIndex(
CAS.STD_ANNOTATION_INDEX, type));
}
/**
* @see org.apache.uima.cas.CAS#getAnnotationType()
*/
public Type getAnnotationType() {
return this.svd.casMetadata.ts.annotType;
}
/**
* @see org.apache.uima.cas.CAS#getEndFeature()
*/
public Feature getEndFeature() {
return this.svd.casMetadata.ts.endFeat;
}
/**
* @see org.apache.uima.cas.CAS#getBeginFeature()
*/
public Feature getBeginFeature() {
return this.svd.casMetadata.ts.startFeat;
}
private <T extends AnnotationFS> T createDocumentAnnotation(int length) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
// Remove any existing document annotations.
FSIterator<T> it = this.<T>getAnnotationIndex(ts.docType).iterator();
List<T> list = new ArrayList<T>();
while (it.isValid()) {
list.add(it.get());
it.moveToNext();
}
for (int i = 0; i < list.size(); i++) {
getIndexRepository().removeFS(list.get(i));
}
return this.<T>ll_getFSForRef(ll_createDocumentAnnotation(length));
}
public int ll_createDocumentAnnotation(int length) {
final int fsRef = ll_createDocumentAnnotationNoIndex(0, length);
ll_getIndexRepository().ll_addFS(fsRef);
return fsRef;
}
public int ll_createDocumentAnnotationNoIndex(int begin, int end) {
final TypeSystemImpl ts = this.svd.casMetadata.ts;
int fsRef = ll_createAnnotation(ts.docType.getCode(), begin, end);
ll_setStringValue(fsRef, ts.langFeat.getCode(), CAS.DEFAULT_LANGUAGE_NAME);
return fsRef;
}
// For the "built-in" instance of Document Annotation, set the
// "end" feature to be the length of the sofa string
public void updateDocumentAnnotation() {
if (!mySofaIsValid() || this == this.svd.baseCAS) {
return;
}
String newDoc = ll_getSofaDataString(this.mySofaRef);
if (null != newDoc) {
final int docAnnot = ll_getDocumentAnnotation();
if (docAnnot != 0) {
boolean wasRemoved = this.removeFromCorruptableIndexAnyViewSetCache(docAnnot, this.getAddbackSingle());
setFeatureValueNoIndexCorruptionCheck(docAnnot, TypeSystemImpl.endFeatCode, newDoc.length());
if (wasRemoved) {
this.addbackSingle(docAnnot);
} else {
this.svd.fsTobeAddedbackSingleInUse = false;
}
} else {
// not in the index (yet)
createDocumentAnnotation(newDoc.length());
}
}
}
/**
* Generic issue: The returned document annotation could be either an instance of
* DocumentAnnotation or an instance of AnnotationImpl - the Java cover class used for
* annotations when JCas is not being used.
*/
public <T extends AnnotationFS> T getDocumentAnnotation() {
if (this == this.svd.baseCAS) {
// base CAS has no document
return null;
}
FSIterator<T> it = this.<T>getAnnotationIndex(this.svd.casMetadata.ts.docType).iterator();
if (it.isValid()) {
return it.get();
}
return createDocumentAnnotation(0);
}
/**
*
* @return the fs addr of the document annotation found via the index, or 0 if not there
*/
public int ll_getDocumentAnnotation() {
if (this == this.svd.baseCAS) {
// base CAS has no document
return 0;
}
LowLevelIterator it = ll_getIndexRepository().
ll_getIndex(CAS.STD_ANNOTATION_INDEX, this.svd.casMetadata.ts.docType.getCode()).
ll_iterator();
if (it.isValid()) {
return it.ll_get();
}
return 0;
}
public String getDocumentLanguage() {
if (this == this.svd.baseCAS) {
// base CAS has no document
return null;
}
final int docAnnotAddr = ll_getFSRef(getDocumentAnnotation());
return ll_getStringValue(docAnnotAddr, TypeSystemImpl.langFeatCode);
}
public String getDocumentText() {
return this.getSofaDataString();
}
public String getSofaDataString() {
if (this == this.svd.baseCAS) {
// base CAS has no document
return null;
}
if (mySofaIsValid()) {
return ll_getSofaDataString(this.mySofaRef);
}
return null;
}
public FeatureStructure getSofaDataArray() {
if (this == this.svd.baseCAS) {
// base CAS has no Sofa
return null;
}
if (mySofaIsValid()) {
return ll_getFSForRef(ll_getRefValue(mySofaRef, TypeSystemImpl.sofaArrayFeatCode));
// return this.getSofa(this.mySofaRef).getLocalFSData();
}
return null;
}
public String getSofaDataURI() {
if (this == this.svd.baseCAS) {
// base CAS has no Sofa
return null;
}
if (mySofaIsValid()) {
return this.getSofa(this.mySofaRef).getSofaURI();
}
return null;
}
public InputStream getSofaDataStream() {
if (this == this.svd.baseCAS) {
// base CAS has no Sofa nothin
return null;
}
return this.getSofaDataStream(this.getSofa());
}
public String getSofaMimeType() {
if (this == this.svd.baseCAS) {
// base CAS has no Sofa
return null;
}
if (mySofaIsValid()) {
return this.getSofa(this.mySofaRef).getSofaMime();
}
return null;
}
public SofaFS getSofa() {
if (this.mySofaRef > 0) {
return getSofa(this.mySofaRef);
}
return null;
}
/**
* @return the addr of the sofaFS associated with this view, or 0
*/
public int ll_getSofa() {
return (mySofaRef > 0) ? mySofaRef : 0;
}
public String getViewName() {
if (this == getViewFromSofaNbr(1)) {
return CAS.NAME_DEFAULT_SOFA;
} else if (this.mySofaRef > 0) {
return ll_getSofaID(mySofaRef);
// return this.getSofa().getSofaID();
} else {
return null;
}
}
private boolean mySofaIsValid() {
return this.mySofaRef > 0;
}
void setDocTextFromDeserializtion(String text) {
if (mySofaIsValid()) {
final int SofaStringCode = ll_getTypeSystem().ll_getCodeForFeature(
this.getTypeSystem().getFeatureByFullName(CAS.FEATURE_FULL_NAME_SOFASTRING));
ll_setStringValue(this.getSofaRef(), SofaStringCode, text);
}
}
public void setDocumentLanguage(String languageCode) {
if (this == this.svd.baseCAS) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.INVALID_BASE_CAS_METHOD,
new String[] { "setDocumentLanguage(String)" });
throw e;
}
// LowLevelCAS llc = getLowLevelCAS();
LowLevelCAS llc = this;
final int docAnnotAddr = llc.ll_getFSRef(getDocumentAnnotation());
languageCode = Language.normalize(languageCode);
llc.ll_setStringValue(docAnnotAddr, TypeSystemImpl.langFeatCode, languageCode);
}
public void setDocumentText(String text) {
if (this == this.svd.baseCAS) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.INVALID_BASE_CAS_METHOD,
new String[] { "setDocumentText(String)" });
throw e;
}
setSofaDataString(text, "text");
}
public void setSofaDataString(String text, String mime) throws CASRuntimeException {
if (this == this.svd.baseCAS) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.INVALID_BASE_CAS_METHOD,
new String[] { "setDocumentText(String)" });
throw e;
}
if (!mySofaIsValid()) {
this.createInitialSofa(null);
}
// try to put the document into the SofaString ...
// ... will fail if previously set
getSofa(this.mySofaRef).setLocalSofaData(text);
ll_setStringValue(this.mySofaRef, TypeSystemImpl.sofaMimeFeatCode,
mime);
}
public void setSofaDataArray(FeatureStructure array, String mime) throws CASRuntimeException {
if (this == this.svd.baseCAS) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.INVALID_BASE_CAS_METHOD,
new String[] { "setSofaDataArray(FeatureStructure, mime)" });
throw e;
}
if (!mySofaIsValid()) {
this.createInitialSofa(null);
}
// try to put the document into the SofaString ...
// ... will fail if previously set
getSofa(this.mySofaRef).setLocalSofaData(array);
ll_setStringValue(this.mySofaRef, TypeSystemImpl.sofaMimeFeatCode,
mime);
}
public void setSofaDataURI(String uri, String mime) throws CASRuntimeException {
if (this == this.svd.baseCAS) {
CASRuntimeException e = new CASRuntimeException(CASRuntimeException.INVALID_BASE_CAS_METHOD,
new String[] { "setSofaDataURI(String, String)" });
throw e;
}
if (!mySofaIsValid()) {
this.createInitialSofa(null);
}
// try to put the document into the SofaString ...
// ... will fail if previously set
getSofa(this.mySofaRef).setRemoteSofaURI(uri);
ll_setStringValue(this.mySofaRef, TypeSystemImpl.sofaMimeFeatCode,
mime);
}
public void setCurrentComponentInfo(ComponentInfo info) {
// always store component info in base CAS
this.svd.componentInfo = info;
}
ComponentInfo getCurrentComponentInfo() {
return this.svd.componentInfo;
}
/**
* @see org.apache.uima.cas.CAS#addFsToIndexes(FeatureStructure fs)
*/
public void addFsToIndexes(FeatureStructure fs) {
// if (fs instanceof AnnotationBaseFS) {
// final CAS sofaView = ((AnnotationBaseFS) fs).getView();
// if (sofaView != this) {
// CASRuntimeException e = new CASRuntimeException(
// CASRuntimeException.ANNOTATION_IN_WRONG_INDEX, new String[] { fs.toString(),
// sofaView.getSofa().getSofaID(), this.getSofa().getSofaID() });
// throw e;
// }
// }
this.indexRepository.addFS(fs);
}
/**
* @see org.apache.uima.cas.CAS#removeFsFromIndexes(FeatureStructure fs)
*/
public void removeFsFromIndexes(FeatureStructure fs) {
this.indexRepository.removeFS(fs);
}
/**
* @param addr the heap address of a feature structure which is a subtype of AnnotationBase
* @return the view associated with this FS where it could be indexed
*/
public CASImpl ll_getSofaCasView(int addr) {
// if the sofa feature for this annotation is not 0
int addrOfSofaFS = this.getSofaFeat(addr);
if (addrOfSofaFS > 0) {
// check if same as that of current CAS view
// if (!(this instanceof CASImpl) || (sofaId != ((CASImpl)
// this).getSofaRef())) {
if (addrOfSofaFS != this.getSofaRef()) {
// Does not match. get CAS for the sofaRef feature found in
// annotation
// getSofaRef gets the feature which is the dense sofa number
return (CASImpl) this.getView(ll_getSofaNum(addrOfSofaFS));
}
} else {// annotation created from low-level APIs, without setting sofa
// feature
// Ignore it for backwards compatibility
}
return this;
}
// public Iterator<CAS> getViewIterator() {
// List<CAS> viewList = new ArrayList<CAS>();
// // add initial view if it has no sofa
// if (!((CASImpl) getInitialView()).mySofaIsValid()) {
// viewList.add(getInitialView());
// }
// // add views with Sofas
// FSIterator<SofaFS> sofaIter = getSofaIterator();
// while (sofaIter.hasNext()) {
// viewList.add(getView(sofaIter.next()));
// }
// return viewList.iterator();
// }
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.CAS#getViewIterator()
*/
public Iterator<CAS> getViewIterator() {
return new Iterator<CAS>() {
final CASImpl initialView = (CASImpl) getInitialView(); // creates one if not existing, w/o sofa
boolean testInitView = !initialView.mySofaIsValid(); // true if has no Sofa in initial view
// but is reset to false once iterater moves
// off of initial view.
// if initial view has a sofa, we just use the
// sofa iterator instead.
final FSIterator<SofaFS> sofaIter = getSofaIterator();
@Override
public boolean hasNext() {
if (testInitView) {
return true;
}
return sofaIter.hasNext();
}
@Override
public CAS next() {
if (testInitView) {
testInitView = false;
return initialView;
}
return getView(sofaIter.next());
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
/*
* (non-Javadoc)
*
* @see org.apache.uima.cas.CAS#getViewIterator(java.lang.String)
*/
public Iterator<CAS> getViewIterator(String localViewNamePrefix) {
// do sofa mapping for current component
String absolutePrefix = null;
if (getCurrentComponentInfo() != null) {
absolutePrefix = getCurrentComponentInfo().mapToSofaID(localViewNamePrefix);
}
if (absolutePrefix == null) {
absolutePrefix = localViewNamePrefix;
}
// find Sofas with this prefix
List<CAS> viewList = new ArrayList<CAS>();
FSIterator<SofaFS> sofaIter = getSofaIterator();
while (sofaIter.hasNext()) {
SofaFS sofa = sofaIter.next();
String sofaId = sofa.getSofaID();
if (sofaId.startsWith(absolutePrefix)) {
if ((sofaId.length() == absolutePrefix.length())
|| (sofaId.charAt(absolutePrefix.length()) == '.')) {
viewList.add(getView(sofa));
}
}
}
return viewList.iterator();
}
public final boolean doUseJcasCache() {
return this.isUsedJcasCache;
}
/**
* protectIndexes
*
* Within the scope of protectIndexes,
* feature updates are checked, and if found to be a key, and the FS is in a corruptable index,
* then the FS is removed from the indexes (in all necessary views) (perhaps multiple times
* if the FS was added to the indexes multiple times), and this removal is recorded on
* an new instance of FSsTobeReindexed appended to fssTobeAddedback.
*
* Later, when the protectIndexes is closed, the tobe items are added back to the indies.
*/
@Override
public AutoCloseable protectIndexes() {
FSsTobeAddedback r = FSsTobeAddedback.createMultiple(this);
svd.fssTobeAddedback.add(r);
return r;
}
void dropProtectIndexesLevel () {
svd.fssTobeAddedback.remove(svd.fssTobeAddedback.size() -1);
}
/**
* This design is to support normal operations where the
* addbacks could be nested
* It also handles cases where nested ones were inadvertently left open
* Three cases:
* 1) the addbacks are the last element in the stack
* - remove it from the stack
* 2) the addbacks are (no longer) in the list
* - leave stack alone
* 3) the addbacks are in the list but not at the end
* - remove it and all later ones
*
* If the "withProtectedindexes" approach is used, it guarantees proper
* nesting, but the Runnable can't throw checked exceptions.
*
* You can do your own try-finally blocks (or use the try with resources
* form in Java 8 to do a similar thing with no restrictions on what the
* body can contain.
*
* @param addbacks
*/
void addbackModifiedFSs (FSsTobeAddedback addbacks) {
final List<FSsTobeAddedback> s = svd.fssTobeAddedback;
if (s.get(s.size() - 1) == addbacks) {
s.remove(s.size());
} else {
int pos = s.indexOf(addbacks);
if (pos >= 0) {
for (int i = s.size() - 1; i > pos; i--) {
FSsTobeAddedback toAddBack = s.remove(i);
toAddBack.addback();
}
}
}
addbacks.addback();
}
/**
*
* @param r an inner block of code to be run with
*/
@Override
public void protectIndexes(Runnable r) {
AutoCloseable addbacks = protectIndexes();
try {
r.run();
} finally {
addbackModifiedFSs((FSsTobeAddedback) addbacks);
}
}
/**
* The current implementation only supports 1 marker call per
* CAS. Subsequent calls will throw an error.
*
* The design is intended to support (at some future point)
* multiple markers; for this to work, the intent is to
* extend the MarkerImpl to keep track of indexes into
* these IntVectors specifying where that marker starts/ends.
*/
public Marker createMarker() {
if (!this.svd.flushEnabled) {
throw new CASAdminException(CASAdminException.FLUSH_DISABLED);
}
this.svd.trackingMark = new MarkerImpl(this.getHeap().getNextId(),
this.getStringHeap().getSize(),
this.getByteHeap().getSize(),
this.getShortHeap().getSize(),
this.getLongHeap().getSize(),
this);
if (this.svd.modifiedPreexistingFSs == null) {
this.svd.modifiedPreexistingFSs = new IntVector();
} else {errorMultipleMarkers();}
if (this.svd.modifiedFSHeapCells == null) {
this.svd.modifiedFSHeapCells = new IntVector();
} else {errorMultipleMarkers();}
if (this.svd.modifiedByteHeapCells == null) {
this.svd.modifiedByteHeapCells = new IntVector();
} else {errorMultipleMarkers();}
if (this.svd.modifiedShortHeapCells == null) {
this.svd.modifiedShortHeapCells = new IntVector();
} else {errorMultipleMarkers();}
if (this.svd.modifiedLongHeapCells == null) {
this.svd.modifiedLongHeapCells = new IntVector();
} else {errorMultipleMarkers();}
if (this.svd.trackingMarkList == null) {
this.svd.trackingMarkList = new ArrayList<MarkerImpl>();
} else {errorMultipleMarkers();}
this.svd.trackingMarkList.add(this.svd.trackingMark);
return this.svd.trackingMark;
}
private void errorMultipleMarkers() {
throw new CASRuntimeException(CASRuntimeException.MULTIPLE_CREATE_MARKER);
}
private void logFSUpdate(int fsaddr, int position, ModifiedHeap whichheap, int howmany) {
if (this.svd.trackingMark != null && !this.svd.trackingMark.isNew(fsaddr)) {
//log the FS
int lastModifiedFS = -1;
if (this.svd.modifiedPreexistingFSs.size() > 0) {
lastModifiedFS = this.svd.modifiedPreexistingFSs.get(this.svd.modifiedPreexistingFSs.size()-1);
}
//only log if the last one logged is not the same fs.s
if (lastModifiedFS != fsaddr) {
this.svd.modifiedPreexistingFSs.add(fsaddr);
}
//log cells that were updated
switch (whichheap) {
case FSHEAP:
for (int i=0; i < howmany;i++) {
this.svd.modifiedFSHeapCells.add(position+i);
}
break;
case BYTEHEAP:
for (int i=0; i < howmany;i++) {
this.svd.modifiedByteHeapCells.add(position+i);
}
break;
case SHORTHEAP:
for (int i=0; i < howmany;i++) {
this.svd.modifiedShortHeapCells.add(position+i);
}
break;
case LONGHEAP:
for (int i=0; i < howmany;i++) {
this.svd.modifiedLongHeapCells.add(position+i);
}
break;
}
}
}
// made public https://issues.apache.org/jira/browse/UIMA-2478
public MarkerImpl getCurrentMark() {
return this.svd.trackingMark;
}
IntVector getModifiedFSList() {
return this.svd.modifiedPreexistingFSs;
}
IntVector getModifiedFSHeapAddrs() {
return this.svd.modifiedFSHeapCells;
}
IntVector getModifiedByteHeapAddrs() {
return this.svd.modifiedByteHeapCells;
}
IntVector getModifiedShortHeapAddrs() {
return this.svd.modifiedShortHeapCells;
}
IntVector getModifiedLongHeapAddrs() {
return this.svd.modifiedLongHeapCells;
}
@Override
public String toString() {
String sofa = (mySofaRef == -1) ? "_InitialView" :
(mySofaRef == 0) ? "no Sofa" :
getSofa(this.mySofaRef).getSofaID();
return "CASImpl [view: " + sofa + "]";
}
int getCasResets() {
return svd.casResets.get();
}
int getCasId() {
return svd.casId;
}
/******************************************
* DEBUGGING and TRACING
*
******************************************/
void traceFSCreate(FeatureStructureImpl fs) {
StringBuilder b = svd.traceFScreationSb;
if (b.length() > 0) {
traceFSflush();
}
traceFSfs(fs);
svd.traceFSisCreate = true;
if (fs.getType().isArray()) {
int arraySize = ll_getArraySize(((FeatureStructureImpl)fs).getAddress());
b.append(" l:").append(arraySize);
}
if (fs.getAddress() > 190000 && fs.getAddress() < 200000 && fs.getType().getShortName().equals("Passage")) {
traceOut.println("Passage callback: " + MiscImpl.getCallers(3, 10));
}
}
void traceFSfs(FeatureStructureImpl fs) {
StringBuilder b = svd.traceFScreationSb;
svd.traceFSid = fs.getAddress();
b.append("c:").append(String.format("%-3d", getCasId()));
String viewName = fs.getCAS().getViewName();
if (null == viewName) {
viewName = "base";
}
b.append(" v:").append(MiscImpl.elide(viewName, 8));
b.append(" i:").append(String.format("%-5s", fs.getAddress()));
b.append(" t:").append(MiscImpl.elide(fs.getType().getShortName(), 10));
}
void traceFSfeat(FeatureStructure fs, FeatureImpl fi, int v) {
StringBuilder b = svd.traceFScreationSb;
// assert (b.length() > 0); // may be 0 if fs created via deserialization
FeatureStructureImpl fsi = (FeatureStructureImpl) fs;
if (fsi.getAddress() != svd.traceFSid) {
traceFSfeatUpdate(fsi);
}
String fn = fi.getShortName();
String fv = getTraceRepOfObj(fi, v);
int i_v = Math.max(0, 10 - fn.length());
int i_n = Math.max(0, 10 - fv.length());
fn = MiscImpl.elide(fn, 10 + i_n, false);
fv = MiscImpl.elide(fv, 10 + i_v, false);
// debug
// if (!svd.traceFSisCreate && fn.equals("uninf.dWord") && fv.equals("XsgTokens")) {
// traceOut.println("debug uninf.dWord:XsgTokens: updated by " + MiscImpl.getCallers(3, 10));
// }
b.append(' ').append(MiscImpl.elide(fn + ':' + fv, 21));
}
private String getTraceRepOfObj( FeatureImpl fi, int v) {
TypeImpl range = (TypeImpl) fi.getRange();
int rangeCode = range.getCode();
if (ll_isRefType(rangeCode)) {
if (v == 0) return "null";
// FeatureStructureImpl fs = ll_getFSForRef(v);
Type type = getTypeSystemImpl().ll_getTypeForCode(getTypeCode(v));
return ((type == null) ? "unknwn"
: MiscImpl.elide(type.getShortName(), 5, false))
+ ':' + v;
} else if (isStringType(rangeCode)){
String s = this.getStringHeap().getStringForCode(v);
s = MiscImpl.elide(s, 50, false);
return MiscImpl.replaceWhiteSpace(s, "_");
} else if (isFloatType(rangeCode)) {
return Float.toString(int2float(v));
} else if (isBooleanType(rangeCode)) {
return (v == 1) ? "true" : "false";
} else if (isLongType(rangeCode)) {
return Long.toString(this.getLongHeap().getHeapValue(v));
} else if (isDoubleType(rangeCode)) {
return Double.toString(long2double(this.getLongHeap().getHeapValue(v)));
} else {
return Integer.toString(v);
}
}
void traceFSfeatUpdate(FeatureStructureImpl fs) {
StringBuilder b = traceFSflush();
traceFSfs(fs);
svd.traceFSisCreate = false;
}
StringBuilder traceFSflush() {
StringBuilder b = svd.traceFScreationSb;
// assert (b.length() > 0); // may be 0 if fs created via deserialization
if (b.length() > 0) {
traceOut.println((svd.traceFSisCreate ? "cr: " :
"up: ") + b);
b.setLength(0);
}
return b;
}
}