/** @name xmideserializer_handler.cpp
-----------------------------------------------------------------------------

 * 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.

-----------------------------------------------------------------------------


   10/18/2005  Initial creation

-------------------------------------------------------------------------- */

//TODO support multiple indexed FS

// ---------------------------------------------------------------------------
//  Includes
// ---------------------------------------------------------------------------

#include "uima/pragmas.hpp"
#include <iostream>
#include <sstream>
#include <algorithm>
using namespace std;

#include "xercesc/sax2/Attributes.hpp"
#include "xercesc/sax/SAXParseException.hpp"
#include "xercesc/sax/SAXException.hpp"
#include "uima/msg.h"
#include "uima/exceptions.hpp"
#include "uima/lowlevel_typesystem.hpp"
#include "uima/lowlevel_indexrepository.hpp"

#include "uima/xmideserializer_handler.hpp"
#include "uima/internal_fspromoter.hpp"
#include "uima/internal_typeshortcuts.hpp"
#include "uima/internal_casimpl.hpp"
#include "uima/fsindexrepository.hpp"
#include "uima/arrayfs.hpp"
#include "uima/listfs.hpp"
#include "uima/annotator_context.hpp"
#include "uima/resmgr.hpp"


namespace uima {

// ---------------------------------------------------------------------------
//  XmiDeserialiserHandler: Constructors and Destructor
// ---------------------------------------------------------------------------

	XmiDeserializerHandler::XmiDeserializerHandler(CAS & cas,
		XmiSerializationSharedData * xmiSharedData, bool len) : iv_cas(cas.getBaseCas() ),
		iv_locator(NULL), iv_casimpl( uima::internal::CASImpl::promoteCAS(*iv_cas)),
		sharedData(xmiSharedData), ownsSharedData(false), outOfTypeSystemElement(NULL) {
	        lenient = len;
			if (this->sharedData==NULL) {
				this->sharedData = new XmiSerializationSharedData();
				ownsSharedData=true;
			} else {
				lenient=true;
			}
			//cout << " XmiDeserializerHandler::constructor " << endl;
			currentContentFeat.append(DEFAULT_CONTENT_FEATURE);
			sofaTypeCode = uima::internal::gs_tySofaType;
			FSIndexRepository * fsidx = &iv_cas->getBaseIndexRepository();
			indexRepositories.push_back((lowlevel::IndexRepository*)fsidx);
			// There should always be another index for the Initial View
			fsidx = &iv_cas->getView(CAS::NAME_DEFAULT_SOFA)->getIndexRepository();
			indexRepositories.push_back((lowlevel::IndexRepository*)fsidx);

			// get temp heap handle for checking if an FS is an annotation
			lowlevel::FSHeap const & crHeap = iv_casimpl.getHeap();
			//       uima::lowlevel::FSHeap::TyFSHeap const & tyTempHeap = crHeap.iv_clTemporaryHeap;
			iv_typesystem = &crHeap.getTypeSystem();

			ignoreDepth=0;
			nextSofaNum=2;
		}

		XmiDeserializerHandler::~XmiDeserializerHandler()   {
			//cout << " XmiDeserializerHandler::destructor " << endl;

			if (ownsSharedData)  {
				delete sharedData;
			}
			//cout << " XmiDeserializerHandler::destructor done " << endl;
		}


// ---------------------------------------------------------------------------
//  XmiDeserializerHandler: Implementation of the SAX2 ContentHandler interface
// ---------------------------------------------------------------------------

  void  XmiDeserializerHandler::setDocumentLocator(const Locator* const locator) {
    //cout << " XmiDeserializerHandler::setDocumentLocator() " << endl;
    iv_locator = locator;
  }

  void XmiDeserializerHandler::startDocument() {
    //cout << " XmiDeserializerHandler::startDocument() " << endl;
    iv_state = DOC_STATE;
  }

	void XmiDeserializerHandler::startElement(const   XMLCh* const    uri,
		const   XMLCh* const    localname,
		const   XMLCh* const    qname,
		const Attributes & attrs) {
			//cout << " XmiDeserializerHandler::startElement() qname " << icu::UnicodeString((UChar*)qname, XMLString::stringLen(qname)) << endl;
			//cout << "startElement localname " << icu::UnicodeString(localname) << " uri " << icu::UnicodeString(uri) << endl;
			//cout << "startElement attrs " << attrs.getLength() << endl;


			assert(sizeof(XMLCh) == sizeof(UChar));

			icu::UnicodeString qualifiedName(qname);
			buffer.remove(); 

			switch (iv_state) {
		case DOC_STATE: {
			//cout << "startElement DOC_STATE " <<  attrs.getLength() << endl;
			// allow any root element name
			// extract xmlns:prefix=uri attributes into a map, which we can use to
			// resolve the prefixes even with a non-namespace-aware parser
			if (attrs.getLength() != 0) {
				for (size_t i = 0; i < attrs.getLength(); i++) {
					icu::UnicodeString attrName(attrs.getQName(i));
					//cout << "xmlns attrName " << attrName << endl;
					if (attrName.indexOf("xmlns:") > -1 ) {
						icu::UnicodeString prefix;
						attrName.extract(6, attrName.length()-6, prefix);
						icu::UnicodeString uri(attrs.getValue(i));
						nsPrefixToUriMap[prefix]= uri;
					}
				}
			}
			iv_state = FS_STATE;
			break;
										}
		case FS_STATE: {
			// ignore elements with XMI prefix (such as XMI annotations)  
			if (qualifiedName.indexOf("xmi") > 0) {
				this->iv_state = IGNORING_XMI_ELEMENTS_STATE;
				this->ignoreDepth++;
				return;
			}

			icu::UnicodeString unsuri(uri);
			icu::UnicodeString ulocalname(localname);
			// parser not namespace-enabled, so try to resolve NS ourselves
			// TODO test with non namespace-enabled
			/**
			int colonIndex = qualifiedName.indexOf(":");
			if (colonIndex != -1) {
			icu::UnicodeString prefix;
			qualifiedName.extract(0, colonIndex,prefix);
			map<icu::UnicodeString,icu::UnicodeString>::iterator uriite = nsPrefixToUriMap.find(prefix);
			if (uriite != nsPrefixToUriMap.end()) { 
			nameSpaceURI = uriite->second;
			} else {
			// unbound namespace. Rather than failing, just assume a reasonable default.
			nameSpaceURI.append("http:///");
			nameSpaceURI.append(prefix);
			nameSpaceURI.append(".ecore");
			}
			colonIndex++;
			qualifiedName.extract(colonIndex, qualifiedName.length()-colonIndex,localName );
			} else { // no prefix. Use default URI 
			nameSpaceURI = DEFAULT_NAMESPACE_URI;
			}
			**/
			//cout << "startElement FS_STATE calling readFS " << typeName << endl; 
			//readFS(typeName, attrs);
			readFS(unsuri, ulocalname, qualifiedName, attrs);

			map<icu::UnicodeString, vector<icu::UnicodeString>*>::iterator mite;
            for (mite=multiValuedFeatures.begin();
				mite != multiValuedFeatures.end(); mite++) {
					if (mite->second != NULL) {
						delete mite->second;
					}
			}
			multiValuedFeatures.clear();
			iv_state = FEAT_STATE;
			break;	   
									 }
		case FEAT_STATE: {
			iv_state = FEAT_CONTENT_STATE;
			break;				 
										 }
		case IGNORING_XMI_ELEMENTS_STATE: {
			ignoreDepth++;
			break;								 
																			}
		default: {
			// If we're not in an element expecting state, raise an error.
			ErrorInfo errInfo;
			errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
			ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
			assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
			msg.addParam( qualifiedName );
			errInfo.setMessage(msg);
			errInfo.setSeverity(ErrorInfo::unrecoverable);
			ExcIllFormedInputError exc(errInfo);
			throw exc;
						 }
			} //switch
		}

	void XmiDeserializerHandler::characters(
					const   XMLCh* const  cpwsz,
					const XMLSize_t    uiLength) {
		assert(sizeof(XMLCh) == sizeof(UChar));

		if (this->iv_state == FEAT_CONTENT_STATE) {
			buffer.append( (UChar const *) cpwsz, 0, uiLength );
		}
		/**
		switch (this->iv_state)  {
			case FEAT_CONTENT_STATE:
				buffer.append( (UChar const *) cpwsz, 0, uiLength );
				break;
			default:
				break;
		}**/
	}

	void XmiDeserializerHandler::endElement(const XMLCh* const nsuri,
						const XMLCh* const localname,
						const XMLCh* const qname) {
		/**
		cout << " XmiDeserializerHandler::endElement() qname " 
		<< icu::UnicodeString( (UChar*) qname, XMLString::stringLen(qname) ) << endl;
		cout << " XmiDeserializerHandler::endElement() uri " 
		<< icu::UnicodeString( (UChar*) nsuri, XMLString::stringLen(nsuri) ) << endl;
		**/

		assert(sizeof(XMLCh) == sizeof(UChar));
		icu::UnicodeString qualifiedName( (UChar const *) qname, XMLString::stringLen(qname));
		//cout << "endElement qualifiedname " << qualifiedName << endl;
		switch (iv_state) {
		case DOC_STATE: {
			// Do nothing.
			break; 
		}
		case FS_STATE: {
			iv_state = DOC_STATE;
			break;
		}
		case FEAT_CONTENT_STATE: {
			// We have just processed one of possibly many values for a feature.
			// Store this value in the multiValuedFeatures map for later use.
			//cout << "endELement FEAT_CONTENT_STATE " << buffer << endl;
			map<icu::UnicodeString, vector<icu::UnicodeString>*>::iterator ite =
				multiValuedFeatures.find(qualifiedName);
			vector<icu::UnicodeString> * valuesList=0; 
			if (ite == multiValuedFeatures.end()) {
				valuesList = new vector<icu::UnicodeString>;
				multiValuedFeatures[qualifiedName] = valuesList;
			} else {
				valuesList = ite->second;
			}
			if (valuesList==0) {
				cout << "endELement()FEAT_CONTENT_STATE valuesList not created" << endl;
			}
			else valuesList->push_back(buffer);

			// go back to the state where we're expecting a feature
			iv_state = FEAT_STATE;
			break;
		}
		case FEAT_STATE: {
			// end of FS. Process multi-valued features or array elements that were
			// encoded as subelements
			if (this->outOfTypeSystemElement != NULL) {
				if (this->multiValuedFeatures.size() > 0) {
					map<icu::UnicodeString,vector<icu::UnicodeString>*>::iterator ite;
					for (ite=multiValuedFeatures.begin(); ite != multiValuedFeatures.end();ite++) {
						icu::UnicodeString featName = ite->first;
						vector<icu::UnicodeString>* featVals = ite->second;
						addOutOfTypeSystemFeature(outOfTypeSystemElement, featName, *featVals);
					}
				}
				this->outOfTypeSystemElement = NULL;
			}
			//process the multivalued feature or array elements that 
			//were encoded as subelements.
			//cout << "endElement FEAT_STATE " << qualifiedName << endl;
			else if (currentType.isValid()) {
				int typecode = internal::FSPromoter::demoteType(currentType);
				if ( iv_cas->getTypeSystem().isArrayType(typecode) && 
					typecode != internal::gs_tyByteArrayType) {
						// create the array now. elements may have been provided either as
						// attributes or child elements, but not both.
						// BUT - not byte arrays! They are created immediately, to avoid
						// the overhead of parsing into a String array first
						vector<string> featVals;
						// cout << "endElement FEAT_STATE currentArrayElements " <<
						//	    currentArrayElements.length() << endl;
						if (currentArrayElements.length()==0) // were not specified as attributes
						{
							map<icu::UnicodeString, vector<icu::UnicodeString>*>::iterator ite =
								multiValuedFeatures.find(icu::UnicodeString("elements"));
							if (ite != multiValuedFeatures.end()) {
								vector<icu::UnicodeString>* vals = ite->second;
								for (size_t i=0; i<vals->size(); i++) {
									featVals.push_back( ((UnicodeStringRef)vals->at(i)).asUTF8()); 
								}
							}
						} else {
							tokenize(currentArrayElements,featVals);
						}         
						createArray(internal::FSPromoter::demoteType(currentType), featVals, currentArrayId);
					} else {
						map<icu::UnicodeString,vector<icu::UnicodeString>*>::iterator ite;
						for (ite=multiValuedFeatures.begin(); ite != multiValuedFeatures.end();ite++) {
							icu::UnicodeString featName = ite->first;
							vector<icu::UnicodeString>* featVals = ite->second;
							vector<string> stringList;
							for (size_t i=0; i< featVals->size();i++) {
								stringList.push_back( ((UnicodeStringRef)featVals->at(i)).asUTF8());
							}
							handleFeature(currentAddr, featName, stringList);
						}
					}
			}
			iv_state = FS_STATE;
			break;
		} 
		case IGNORING_XMI_ELEMENTS_STATE: {
			ignoreDepth--;
			if (ignoreDepth == 0) {
				iv_state = FS_STATE;
			}
			break;
		}
	}
}


	void XmiDeserializerHandler::endDocument() {

		//cout << " XmiDeserializerHandler::endDocument() " << endl;

		//fix up deserialized FSs
		for (size_t i = 0; i < this->deserializedFsAddrs.size(); i++) {
			//cout << "finalize fs " << deserializedFsAddrs.at(i) << endl;
			finalizeFS(deserializedFsAddrs.at(i));
		}

		//fix up lists
		for (size_t i = 0; i < fsListNodesFromMultivaluedProperties.size(); i++) {
			this->remapFSListHeads(fsListNodesFromMultivaluedProperties.at(i));
		}

		//cout << " XmiDeserializerHandler::endDocument() tcasInstance " << endl;
		//update document annotation info in tcas
		for (size_t i = 0; i < tcasInstances.size(); i++) {
			CAS * tcas = (CAS *) tcasInstances[i];
			if (tcas != 0) {
				tcas->pickupDocumentAnnotation();
			}
		}
		//cout << " XmiDeserializerHandler::endDocument() " << endl;
	}


  void XmiDeserializerHandler::ignorableWhitespace(const  XMLCh* const cpwsz,
      const unsigned int length) {
    //cout << " XmiDeserializerHandler::ignorableWhitespace() " << endl;
  }


/**
   * Converts an XMI element name to a UIMA-style dotted type name.
   * 
   */
	icu::UnicodeString XmiDeserializerHandler::xmiElementName2uimaTypeName(icu::UnicodeString& nsUri, icu::UnicodeString& localName) {
		// check map first to see if we've already computed the namespace mapping
		map<icu::UnicodeString,icu::UnicodeString>::iterator ite = xmiNamespaceToUimaNamespaceMap.find(nsUri);
		icu::UnicodeString uimaNamespace;
		if (ite != xmiNamespaceToUimaNamespaceMap.end()) {
			uimaNamespace = ite->second;
		} else {
			// check for the special "no-namespace" URI, which is used for UIMA types with no namespace
			if (nsUri.compare(DEFAULT_NAMESPACE_URI) == 0) {
				//uimaNamespace = "";
			} else {
				// Our convention is that the UIMA namespace is the URI path format e.g:
				// http:///uima/cas.ecore.
				// remove http:/// and trailing .ecore
				// replace remaining slashes with dot.
				nsUri.extractBetween(8, nsUri.length()-6, uimaNamespace); 
				//cout << "uimanamespace " << uimaNamespace << endl;
				uimaNamespace.findAndReplace("/", ".");
				uimaNamespace.append("."); // include trailing dot for convenience
			}
			xmiNamespaceToUimaNamespaceMap[nsUri]= uimaNamespace;
		}
		//cout << "uimaNamespace final " << uimaNamespace << endl;
		uimaNamespace.append(localName);
		return uimaNamespace;
	}


// Create a new FS.
	void XmiDeserializerHandler::readFS(icu::UnicodeString & nsUri, icu::UnicodeString & localName,
		icu::UnicodeString & qualifiedName, const Attributes & attrs) {
			icu::UnicodeString typeName = xmiElementName2uimaTypeName(nsUri, localName);
			Type type = iv_cas->getTypeSystem().getType(typeName);
			currentType=type;
			
			if (!type.isValid()) {
				if (typeName.compare(icu::UnicodeString("uima.cas.NULL"))==0) {
					//cout << "readFS ignore " << typeName << endl;
					return; //ignore
				}
				if (typeName.compare(icu::UnicodeString("uima.cas.View"))==0) {
					//cout << "readFS  " << typeName << endl;
					icu::UnicodeString attrName; 
					int sofaXmiId=0;
					icu::UnicodeString members;
					for (size_t i = 0; i < attrs.getLength(); i++) {
						attrName =  attrs.getQName(i);
						if (attrName.compare(CAS::FEATURE_BASE_NAME_SOFA) == 0) {
							icu::UnicodeString ustr(attrs.getValue(i));
							sofaXmiId = atoi( ((UnicodeStringRef)ustr).asUTF8().c_str());
						} else if (attrName.compare("members") == 0) {
							members = attrs.getValue(i);
						} 
					}
					processView(sofaXmiId, members);
					return;
				} 
				// type is not in our type system
				if (!lenient) {
					ErrorInfo errInfo;
					errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
					ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
					assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
					msg.addParam(typeName);
					errInfo.setMessage(msg);
					errInfo.setSeverity(ErrorInfo::unrecoverable);
					ExcIllFormedInputError exc(errInfo);
					throw exc; 
				} else {
					this->addToOutOfTypeSystemData(
						new XmlElementName( ((UnicodeStringRef)nsUri).asUTF8(),
						((UnicodeStringRef)localName).asUTF8(),
						((UnicodeStringRef)qualifiedName).asUTF8()), attrs );   
					return;
				}
			} else if (iv_cas->getTypeSystem().isArrayType(internal::FSPromoter::demoteType(type)) ) {
				
        icu::UnicodeString attrName; 
				int xmiId=0;
				icu::UnicodeString elements;
				for (size_t i = 0; i < attrs.getLength(); i++) {
						attrName =  attrs.getQName(i);
						if (attrName.compare(XMI_ID_ATTR_NAME) == 0) {
							icu::UnicodeString ustr(attrs.getValue(i));
							currentArrayId = atoi( ((UnicodeStringRef)ustr).asUTF8().c_str());
						} else if (attrName.compare("elements") == 0) {
							currentArrayElements = attrs.getValue(i);
						} 
				}

        //cout << "xmiId " << currentArrayId << " type=" << typeName << " elements=" << currentArrayElements << endl;
				if (internal::FSPromoter::demoteType(type) == internal::gs_tyByteArrayType) {
					int addr = createByteArray(currentArrayElements, currentArrayId);
				} 

			} else {
				//cout << "readFS() create FS and read attributes " << typeName << endl;
				uima::lowlevel::TyFS addr = uima::internal::FSPromoter::demoteFS(iv_cas->createFS(type));
				readFS(addr, attrs, true);
			}

		}



	/**
	* Handles the processing of a cas:View element in the XMI. The cas:View element encodes indexed
	* FSs.
	* 
	* @param sofa
	*          xmi:id of the sofa for this view, null indicates base CAS "view"
	* @param membersString
	*          whitespace-separated string of FS addresses. Each FS is to be added to the specified
	*          sofa's index repository
	*/
	void XmiDeserializerHandler::processView(int sofaXmiId, icu::UnicodeString & members) {
		// TODO: this requires View to come AFTER all of its members
		//cout << "processView start " << sofaXmiId << "members=" << membersString << endl;
		if (members.length() > 0) { 
			// a view with no Sofa will be added to the 1st, _InitialView, index
			int sofaNum = 1;
			if (sofaXmiId != 0) {
				// translate sofa's xmi:id into its sofanum
				//cout << __LINE__ << " calling getFsAddrForXmiId " << sofaXmiId << endl;
				int sofaAddr = getFsAddrForXmiId(sofaXmiId);

				sofaNum = iv_cas->getHeap()->getIntValue(sofaAddr, internal::gs_tySofaNumFeature);
			}
			lowlevel::IndexRepository * indexRep =  indexRepositories.at(sofaNum);

			vector<string> memberList;
			tokenize(members, memberList);

			for (size_t i = 0; i < memberList.size(); i++) {
				// have to map each ID to its "real" address
				int addr=0;
        int amember = atoi(memberList.at(i).c_str());
				try {
					//cout << __LINE__ << " calling getFsAddrForXmiId " << members.at(i) << endl;
					addr = getFsAddrForXmiId(amember);
					indexRep->addFS(internal::FSPromoter::promoteFS(addr,*iv_cas));
				} catch (Exception e) {
					if (!lenient) {
						throw e;
					}
					else {
						//unknown view member may be an OutOfTypeSystem FS
						//cout << "calling sharedData->addOutOfTypeSystemViewMember" << endl;
						this->sharedData->addOutOfTypeSystemViewMember(sofaXmiId, amember);
					}
				}
			}
		}
	}


	int XmiDeserializerHandler::createByteArray(icu::UnicodeString& currentArrayElements, int currentArrayId) {
		string elemStr = ( (UnicodeStringRef) currentArrayElements).asUTF8();
		int arrayLen = elemStr.length() / 2;
		ByteArrayFS fs = iv_cas->createByteArrayFS(arrayLen);
		size_t j=0;
		for (int i = 0; i < arrayLen; i++) {
			char hex[5], *stop;
			hex[0] = '0';
			hex[1] = 'x';
			if (j < elemStr.length() ) {
				hex[2] = elemStr.at(j++);
				if (j < elemStr.length()) {
					hex[3] = elemStr.at(j++);
					hex[4] = 0;
					char val = strtol(hex, &stop, 16);
					fs.set(i,val);
				}
			}
		}  
		int arrayAddr = internal::FSPromoter::demoteFS(fs);
		deserializedFsAddrs.push_back(arrayAddr);
		if (currentArrayId > 0) {
			sharedData->addIdMapping(arrayAddr,currentArrayId);
		}

		return arrayAddr;
	}

	void XmiDeserializerHandler::readFS(lowlevel::TyFS addr, const Attributes  & attrs, bool toIndex) {
		// Hang on address for setting content feature
		currentAddr = addr;

		int id = -1;
		//       int sofaRef = -1; // 0 ==> baseCas indexRepository
		////vector<int>* sofaRef = new vector<int>;
		icu::UnicodeString attrName;
		icu::UnicodeString attrValue;
		bool nameMapping = false;
		UChar ubuff[256];
		UErrorCode errorCode = U_ZERO_ERROR;
		int thisSofaNum;
		lowlevel::TyFS heapValue = iv_casimpl.getHeap().getType(addr);


		if (sofaTypeCode == heapValue) {
			int extsz = icu::UnicodeString(CAS::FEATURE_BASE_NAME_SOFAID).extract(ubuff, 256, errorCode);
			if (extsz > 256) {
				cout << "ACK!" << endl;
			}
			// Xerces deals with char type XMLCh so cast from/to our UChar (both are 16-bits)
			const UChar* sofaID = (UChar*)attrs.getValue((XMLCh*)ubuff);

			if (0==UnicodeStringRef(sofaID).compare(icu::UnicodeString("_DefaultTextSofaName"))) {  
				// initial view Sofa always has sofaNum = 1
				thisSofaNum = 1;
			} else if (0==UnicodeStringRef(sofaID).compare(icu::UnicodeString(CAS::NAME_DEFAULT_SOFA))) {   
				thisSofaNum = 1;
			}  else {
				thisSofaNum = this->nextSofaNum++;
			}
		}

		Type type = uima::internal::FSPromoter::promoteType(heapValue, iv_cas->getTypeSystem().getLowlevelTypeSystem());
		for (size_t i = 0; i < attrs.getLength(); i++) {
			assertWithMsg( sizeof(XMLCh) == sizeof(UChar), "Port required!");
			attrName = (UChar*)attrs.getQName(i);
			attrValue = (UChar*)attrs.getValue(i);

			if (attrName.compare(icu::UnicodeString(XMI_ID_ATTR_NAME)) == 0) {
				id = atoi(UnicodeStringRef(attrValue).asUTF8().c_str());
				//cout << "got " << XMI_ID_ATTR_NAME << " " << id << endl;
			} else {       
				if (sofaTypeCode == heapValue && attrName.compare(CAS::FEATURE_BASE_NAME_SOFAID)==0) {
					if (attrValue.compare(icu::UnicodeString("_DefaultTextSofaName"))==0 ) {
						// First change old default Sofa name into the new one
						attrValue = icu::UnicodeString(CAS::NAME_DEFAULT_SOFA);
					}
				} else if (sofaTypeCode == heapValue 
					&& attrName.compare(icu::UnicodeString(CAS::FEATURE_BASE_NAME_SOFANUM))==0) {
						stringstream str;
						str << thisSofaNum << endl;
						attrValue = icu::UnicodeString(str.str().c_str());
					}
					//cout << "readFS calling handleFeature " << attrName << " attrvalue= "
					//	<< attrValue << endl;
					handleFeature(addr, attrName, attrValue, true);
			}
		}

		if (sofaTypeCode == heapValue) {
			// If a Sofa, create CAS view to get new indexRepository
			SofaFS sofa = (SofaFS) uima::internal::FSPromoter::promoteFS(addr, *iv_cas);
			//also add to indexes so we can retrieve the Sofa later
			iv_cas->getBaseIndexRepository().addFS(sofa);
			CAS * tcas = iv_cas->getView(sofa);
			assert ( EXISTS(tcas) );
			if (sofa.getSofaRef() == 1) {
				iv_cas->registerInitialSofa();
			} else {
				// add indexRepo for views other than the initial view
				lowlevel::IndexRepository * indexRep = iv_cas->getIndexRepositoryForSofa(sofa);
				assert ( EXISTS(indexRep) );
				indexRepositories.push_back(indexRep);
			}
			tcasInstances.push_back(tcas);
		}

		deserializedFsAddrs.push_back(addr);
		if (id > 0) {
			sharedData->addIdMapping(addr, id);
		}

	}

  

  
  void XmiDeserializerHandler::addArrayElement(lowlevel::TyFS addr,
											lowlevel::TyFSType arrayType, 
											int arrayPos, 
											string & buffer) {

    if (arrayPos >= (int) iv_casimpl.getHeap().getArraySize(addr) ) {
      ErrorInfo errInfo;
      errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
      ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
      assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
      msg.addParam("Invalid array FS in the CAS" );
      errInfo.setMessage(msg);
      errInfo.setSeverity(ErrorInfo::unrecoverable);
      ExcIllFormedInputError exc(errInfo);
      throw exc;
    }

    FeatureStructure fs = uima::internal::FSPromoter::promoteFS(addr, *iv_cas);

    switch (arrayType) {
    case internal::gs_tyIntArrayType: {
		//cout << "add intarray element at " << arrayPos << " " << buffer << endl;
        int val = atoi(buffer.c_str());
        IntArrayFS intFS(fs);
        intFS.set( (size_t) arrayPos, val);
        break;
      }
    case internal::gs_tyFloatArrayType: {
        float val = atof(buffer.c_str());
        FloatArrayFS floatFS(fs);
        floatFS.set( (size_t) arrayPos, val);
        break;
      }
    case internal::gs_tyStringArrayType: {
        //add the striug
				StringArrayFS strFS(fs);
				icu::UnicodeString strval(buffer.c_str());
				strFS.set( (size_t) arrayPos,strval);
				break;
    }
    case internal::gs_tyByteArrayType: {
        short intval = atoi(buffer.c_str());
        char charval[2];
        sprintf(charval,"%c",intval);
        ByteArrayFS byteFS(fs);
        byteFS.set( (size_t) arrayPos, charval[0]);
        break;
    }
    case internal::gs_tyBooleanArrayType: {
        BooleanArrayFS booleanFS(fs);
        if (buffer.compare("true") == 0)  {
          booleanFS.set( (size_t) arrayPos, true);
          //cout << "bool buffer " << buffer << " val= " << val << "set " << true << endl;
        } else {
          booleanFS.set ( (size_t) arrayPos, false);
          //cout << arrayPos << " bool buffer " << buffer << " val= " << val << "set " << false << endl;
        }
        break;
      }
    case internal::gs_tyShortArrayType: {
        short val;
        //string strval;
        //UnicodeStringRef(buffer).extractUTF8(strval);
        stringstream s;
        s << buffer.c_str();
        s >> val;
        ShortArrayFS shortFS(fs);
        shortFS.set( (size_t) arrayPos, val);
        break;
      }
    case internal::gs_tyLongArrayType: {
        INT64 val;
        stringstream s;
        s << buffer;
        s >> val;
        LongArrayFS longFS(fs);
        longFS.set( (size_t) arrayPos, val);
        break;
      }
    case internal::gs_tyDoubleArrayType: {
        DoubleArrayFS doubleFS(fs);
        stringstream s;
        s << buffer;
        long double doubleval;
        s >> doubleval;
        doubleFS.set((size_t) arrayPos, doubleval);
        break;
      }
    default: {    //array of FSs
      lowlevel::TyFS fsid = atoi(buffer.c_str());
      FeatureStructure fsitem(fsid, *iv_cas);
      ArrayFS fsArrayfs(fs);
      fsArrayfs.set((size_t) arrayPos, fsitem);
    }
    } //swithch
  }



	// Create a feature value from a string representation.
	void XmiDeserializerHandler::handleFeature(lowlevel::TyFS addr, icu::UnicodeString & featName, icu::UnicodeString & featVal, bool lenient) {
		lowlevel::TyFSType fstype = iv_casimpl.getHeap().getType(addr);
		Type type = uima::internal::FSPromoter::promoteType(fstype, iv_cas->getTypeSystem().getLowlevelTypeSystem());
		Feature feat = type.getFeatureByBaseName(featName);
		if (!feat.isValid()) {
			if (!lenient) {
				ErrorInfo errInfo;
				errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
				ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
				assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
				msg.addParam("Unknown Feature");
				msg.addParam(featName);
				errInfo.setMessage(msg);
				errInfo.setSeverity(ErrorInfo::unrecoverable);
				ExcIllFormedInputError exc(errInfo);
				throw exc; 
			}
			else {
				sharedData->addOutOfTypeSystemAttribute(addr, featName, featVal);
			}
			return;
		}

		lowlevel::TyFSFeature featCode = internal::FSPromoter::demoteFeature(feat);
		handleFeature(type, addr, featCode, featVal, lenient);
	}

  void XmiDeserializerHandler::handleFeature(Type & type, 
    lowlevel::TyFS addr,
    lowlevel::TyFSFeature featCode, 
    icu::UnicodeString & featVal,
    bool lenient) {

    FeatureStructure fs = uima::internal::FSPromoter::promoteFS(addr, *iv_cas);
    if (!fs.isValid() ) {
      cerr << "handle feature of Invalid FS " << type.getName() << endl;
      ErrorInfo errInfo;
      errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
      ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
      assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
      msg.addParam("Invalid FeatureStructure");
      msg.addParam(type.getName());
      errInfo.setMessage(msg);
      errInfo.setSeverity(ErrorInfo::unrecoverable);
      ExcIllFormedInputError exc(errInfo);
      throw exc; 
    }

    ///Feature feat = type.getFeatureByBaseName(featName);
	  Feature feat =  internal::FSPromoter::promoteFeature(featCode, *iv_typesystem);

    Type rtype;
    feat.getRangeType(rtype);
    lowlevel::TyFSType rangeType = uima::internal::FSPromoter::demoteType(rtype);
    switch (rangeType) {
      case internal::gs_tyIntegerType: {
        if (featVal.length()>0) {
          if (featCode == internal::gs_tySofaRefFeature) {
            // special handling for "sofa" feature of annotation. Need to change
            // it from a sofa reference into a sofa number
            int sofaXmiId = atoi(UnicodeStringRef(featVal).asUTF8().c_str());
            //cout << __LINE__ << " calling getFsAddrForXmiId " << sofaXmiId << endl; 
            int sofaAddr = getFsAddrForXmiId(sofaXmiId); 
            int sofaNum = iv_cas->getHeap()->getFSValue(sofaAddr, internal::gs_tySofaNumFeature);
            iv_cas->getHeap()->setFSValue(addr,featCode,sofaNum);

          } else {             
            fs.setIntValue(feat, atoi(UnicodeStringRef(featVal).asUTF8().c_str()));
          }
        }
        break;
      }
      case internal::gs_tyFloatType: { 
        if ( featVal.length() > 0)  {
          fs.setFloatValue(feat, atof(UnicodeStringRef(featVal).asUTF8().c_str()));
        }
        break;
      }
      case internal::gs_tyStringType: {
       // if (featVal.length() > 0) {
          fs.setStringValue(feat, featVal);
        //}
        break;
      }
      case internal::gs_tyByteType: {
        if (featVal.length() > 0) {
          string val = UnicodeStringRef(featVal).asUTF8();
          short intval = atoi(val.c_str());
          char charval[2];
          sprintf(charval,"%c",intval);
          fs.setByteValue(feat, charval[0] );
        }
        break;
      }
      case internal::gs_tyBooleanType: {
        if (featVal.length() > 0) {
          string val = UnicodeStringRef(featVal).asUTF8();
          if (val.compare("1")==0 || val.compare("true") == 0)
            fs.setBooleanValue(feat, true );
          else fs.setBooleanValue(feat, false);
        }
        break;
      }
      case internal::gs_tyShortType: {
        if (featVal.length() > 0) {
          string strval = UnicodeStringRef(featVal).asUTF8();
          short shortval;
          stringstream s;
          s << strval.c_str();
          s >> shortval;
          fs.setShortValue(feat, shortval);
        }
        break;
      }
      case internal::gs_tyLongType: {
        if (featVal.length() > 0) {
          string strval = UnicodeStringRef(featVal).asUTF8();
          INT64 longval;
          stringstream s;
          s << strval.c_str();
          s >> longval;
          fs.setLongValue(feat, longval);
        }
        break;
      }
      case internal::gs_tyDoubleType: {
        if (featVal.length() > 0) {
          string strval = UnicodeStringRef(featVal).asUTF8();
          long double doubleval;
          stringstream s;
          s << strval.c_str();
          s >> doubleval;
          fs.setDoubleValue(feat, doubleval );
        }
        break;
      }	  
      case internal::gs_tyBooleanArrayType:
      case internal::gs_tyByteArrayType:
      case internal::gs_tyIntArrayType: 
      case internal::gs_tyFloatArrayType: 
      case internal::gs_tyStringArrayType: 
      case internal::gs_tyLongArrayType:
      case internal::gs_tyShortArrayType:
      case internal::gs_tyDoubleArrayType: 
      case internal::gs_tyFSArrayType: {
        //cout << "handleFeature " << feat.getName() << " " << featVal << endl;
        if (feat.isMultipleReferencesAllowed()) {
          // do the usual FS deserialization
          //cout << "  multiplerefsallowed " << endl;
          if (featVal.length() > 0) {
            int val = atoi(UnicodeStringRef(featVal).asUTF8().c_str());
            //cout << " setting fsvalue " << "fsaddr " << addr << " value "<< val << endl;
            iv_cas->getHeap()->setFeatureInternal(addr,featCode,val);
          }
        } else {
          // Do the multivalued property deserialization.
          // However, byte arrays have a special serialization (as hex digits)
          //cout << " not multiplerefsallowed " << endl;
          if (rangeType == internal::gs_tyByteArrayType) {
            int arrayAddr = createByteArray(featVal, -1);
            iv_cas->getHeap()->setFSValue(addr,featCode,arrayAddr);
          } else {
            //cout << "tokenizing array values " << endl;
            vector<string> stringList;
            tokenize(featVal, stringList);
            handleFeature(addr, featCode, rangeType, stringList);
          }
        }
        break;
      }
      case internal::gs_tyFloatListType:
      case internal::gs_tyIntListType:
      case internal::gs_tyStringListType: 
      case internal::gs_tyFSListType: {
        //cout << "GOT A LIST FEATURE " << endl;
        if (feat.isMultipleReferencesAllowed()) {
          // do the usual FS deserialization
          if (featVal.length() > 0) {
            int val = atoi(UnicodeStringRef(featVal).asUTF8().c_str());
            iv_cas->getHeap()->setFeatureInternal(addr,featCode,val);
          }
        } else {
          // Do the multivalued property deserialization.
          ////handleFeature(addr,featCode,featVal);
          vector<string> stringList;
          tokenize(featVal, stringList);
          handleFeature(addr, featCode, rangeType, stringList);
        }
        break;
      }
      default: {
        if (rtype.isStringSubType()) {
          if (featVal.length() > 0) {
            fs.setStringValue(feat, featVal);
          }
        } else if (featVal.length() > 0) {
          lowlevel::TyFS val = (lowlevel::TyFS) atoi(UnicodeStringRef(featVal).asUTF8().c_str());
          iv_casimpl.getHeap().setFeatureInternal(addr, uima::internal::FSPromoter::demoteFeature(feat), val);
        }
        break;
      }
    }
  }
 
  void XmiDeserializerHandler::handleFeature(lowlevel::TyFS addr, 
                          icu::UnicodeString & featName,
                          vector<string> & featVal) {
    lowlevel::TyFSType fstype = iv_casimpl.getHeap().getType(addr);
    Type type = uima::internal::FSPromoter::promoteType(fstype, iv_cas->getTypeSystem().getLowlevelTypeSystem());
    Feature feat = type.getFeatureByBaseName(featName);
    if (!feat.isValid()) {
      if (!lenient) {
        ErrorInfo errInfo;
        errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
        ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
        assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
        msg.addParam("Unknown Feature");
        msg.addParam(featName);
        errInfo.setMessage(msg);
        errInfo.setSeverity(ErrorInfo::unrecoverable);
        ExcIllFormedInputError exc(errInfo);
        throw exc; 
      }
      else {
        sharedData->addOutOfTypeSystemChildElements(addr, ( (UnicodeStringRef)featName).asUTF8(), featVal);
      }
      return;
    }
    lowlevel::TyFSFeature featCode = internal::FSPromoter::demoteFeature(feat);
    Type rtype;
    feat.getRangeType(rtype);
    handleFeature(addr, featCode,internal::FSPromoter::demoteType(rtype), featVal);
}

void XmiDeserializerHandler::handleFeature(lowlevel::TyFS addr, 
		                lowlevel::TyFSFeature featCode,
					          lowlevel::TyFSType rangeTypeCode,
					          vector<string> & featVals)  {
    //cout << "handleFeature array/list  " << featVals.size() << endl;
	 switch(rangeTypeCode) {
	   case internal::gs_tyBooleanArrayType:
	   case internal::gs_tyByteArrayType:
	   case internal::gs_tyIntArrayType: 
	   case internal::gs_tyFloatArrayType: 
	   case internal::gs_tyLongArrayType:
	   case internal::gs_tyShortArrayType:
	   case internal::gs_tyDoubleArrayType:
	   case internal::gs_tyFSArrayType: {
		   int arrayFS = createArray(rangeTypeCode, featVals, -1);  
		   iv_cas->getHeap()->setFSValue(addr,featCode,arrayFS);
		   break;
	   }
	   case internal::gs_tyStringArrayType: {
		   //cout << "handleFeature of type string array" << endl;
		   int arrayFS = createArray(rangeTypeCode, featVals, -1);  
		   iv_cas->getHeap()->setFSValue(addr,featCode,arrayFS);
		   break;
	   }
	   case internal::gs_tyIntListType: {
		   int arrayFS = createIntList(featVals);
           iv_cas->getHeap()->setFSValue(addr,featCode,arrayFS);
		   break;
	   }
	   case internal::gs_tyFloatListType: {
		   int arrayFS = createFloatList(featVals);
           iv_cas->getHeap()->setFSValue(addr,featCode,arrayFS);
		   break;
	   }
	   case internal::gs_tyStringListType: {
		   int arrayFS = createStringList(featVals);
           iv_cas->getHeap()->setFSValue(addr,featCode,arrayFS);
		   break;
	   }
	   case internal::gs_tyFSListType: {
		   int arrayFS = createFSList(featVals);
           iv_cas->getHeap()->setFSValue(addr,featCode,arrayFS);
		   break;
	   }   
	   default: {
		//scalar and FS type
		   if (featVals.size() != 1) {
				 //TODO log
			   cerr << "one feature value expected " << endl;
		   } else {
			   Type type = internal::FSPromoter::promoteType(rangeTypeCode,
				   iv_cas->getTypeSystem().getLowlevelTypeSystem());
				 icu::UnicodeString val(featVals.at(0).c_str());
			   handleFeature(type,		   
				   addr, featCode,val, true);
		   }
	  	break;	
	   }
	  }
  }

  void XmiDeserializerHandler::tokenize(icu::UnicodeString & ustr, vector<string> & stringList ) {

	  string str = (UnicodeStringRef(ustr)).asUTF8();
	  string::size_type lastPos = str.find_first_not_of(" ", 0); 
	  string::size_type pos = str.find_first_of(" ",lastPos);
    
	  while (string::npos != pos || string::npos != lastPos) {
        // Found a token, add it to the vector.
        stringList.push_back(str.substr(lastPos, pos - lastPos));
        // Skip blanks and find next non blank
        lastPos = str.find_first_not_of(" ", pos);
        // Find next blank
        pos = str.find_first_of(" ",lastPos);
    }
  }


  int XmiDeserializerHandler::createArray(  lowlevel::TyFSType typeCode,
		               vector<string>& stringList,
					          int xmiId)		{
    int arrayAddr;
  
	  switch (typeCode) {
      case internal::gs_tyBooleanArrayType:
	    case internal::gs_tyByteArrayType:
	    case internal::gs_tyIntArrayType: 
	    case internal::gs_tyFloatArrayType: 
	    case internal::gs_tyLongArrayType:
	    case internal::gs_tyShortArrayType:
	    case internal::gs_tyDoubleArrayType:
	    case internal::gs_tyStringArrayType:
	    case internal::gs_tyFSArrayType: {
	      //cout << "createArray() type " << typeCode << " size " << stringList.size() << endl;
		    arrayAddr = iv_cas->getHeap()->createArrayFS(typeCode, stringList.size());
		    //cout << "created array FS now adding element values at address " << arrayAddr << endl;
		    for (size_t i=0; i < stringList.size();i++) {		
			    addArrayElement(arrayAddr, typeCode,i,stringList.at(i));
		    }		 
		    break;
		  }        
	    default: {
	      cerr << "Invalid Array type" << endl;
		    ErrorInfo errInfo;
		    errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
		    ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
		    assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
		    msg.addParam("createArray failed.");
		    stringstream str;
		    str << "xmiId=" << xmiId << " typecode= " << typeCode << endl;
		    msg.addParam(str.str().c_str());
		    errInfo.setMessage(msg);
		    errInfo.setSeverity(ErrorInfo::unrecoverable);
		    ExcIllFormedInputError exc(errInfo);
		    throw exc; 
		    break;
	    }
	  }
		//cout << "createArray " << xmiId << " addr=" << arrayAddr << endl;
	  deserializedFsAddrs.push_back(arrayAddr);
	  if (xmiId > 0) {
		  sharedData->addIdMapping(arrayAddr, xmiId);
	  }
	  return arrayAddr;
  }
    
  int XmiDeserializerHandler::createIntList(vector<string>& stringList)	{
	  IntListFS listFS =   iv_cas->createIntListFS();
    for (size_t i = 0; i < stringList.size(); i++ ) {
      int value = atoi (stringList.at(i).c_str()); 
	    listFS.addLast(value);
    }
	  return internal::FSPromoter::demoteFS(listFS);
  }

  int XmiDeserializerHandler::createFloatList(vector<string>& stringList)	{
	  FloatListFS listFS =   iv_cas->createFloatListFS();
    for (size_t i = 0; i < stringList.size(); i++ ) {
      float value = atof (stringList.at(i).c_str()); 
	    listFS.addLast(value);
    }
	  return internal::FSPromoter::demoteFS(listFS);
  }

  int XmiDeserializerHandler::createFSList(vector<string>& stringList)	{
	  int first = iv_cas->getHeap()->createFS(internal::gs_tyEListType);

	  size_t i = stringList.size();
	  for  (;i > 0;i--) {
		  int value = atoi(stringList.at(i-1).c_str());
		  int node = iv_cas->getHeap()->createFS(internal::gs_tyNEListType);
		  fsListNodesFromMultivaluedProperties.push_back(node);
		  iv_cas->getHeap()->setFeatureInternal(node, internal::gs_tyHeadFeature, value);
		  iv_cas->getHeap()->setFeatureInternal(node, internal::gs_tyTailFeature, first);
		  first = node;
	  }
	  return first;
  }

  int XmiDeserializerHandler::createStringList(vector<string>& stringList)	{   
    StringListFS listFS =   iv_cas->createStringListFS();
    for (size_t i = 0; i < stringList.size(); i++ ) {
      icu::UnicodeString value(stringList.at(i).c_str()); //use xmiId to look up addr
	    listFS.addLast(value);
    }
	  return internal::FSPromoter::demoteFS(listFS);
  }

  void XmiDeserializerHandler::remapFSListHeads(int addr) {
    int type = iv_cas->getHeap()->getType(addr);
	  if (type != internal::gs_tyIntListType &&
		  type != internal::gs_tyFloatListType &&
		  type != internal::gs_tyStringListType &&
		  type != internal::gs_tyFSListType &&
		  type != internal::gs_tyNEListType) {
      return;
	  }

	  int headFeat = internal::gs_tyHeadFeature;
    int featVal = iv_cas->getHeap()->getFeatureInternal(addr, headFeat);
    if (featVal != 0) {
      int fsValAddr = 0;
	  	try {
		  	  //cout << __LINE__ << " remap calling getFsAddrForXmiId " << featVal << endl;
		  	  fsValAddr = getFsAddrForXmiId(featVal);
		  } catch (Exception e) {
			  if (!lenient) {
			    throw e;
			  } else {
				  stringstream str;
				  str << featVal;
				  this->sharedData->addOutOfTypeSystemAttribute(addr, CAS::FEATURE_BASE_NAME_HEAD, str.str());
			  }
		  }
		  iv_cas->getHeap()->setFeatureInternal(addr, headFeat, fsValAddr);
    }
  }


  void XmiDeserializerHandler::finalizeFS(int deserializedfsaddr) {
    lowlevel::TyFS addr = deserializedfsaddr; 
    FeatureStructure fs = uima::internal::FSPromoter::promoteFS(addr, *iv_cas);
    Type type = fs.getType();
    if (iv_cas->getTypeSystem().isArrayType(uima::internal::FSPromoter::demoteType(type)) ) {    
      finalizeArray(type, addr); 
      return;
    }

    //update heap value of features that are references to other FS.
    vector<Feature> feats;
    type.getAppropriateFeatures(feats);

    for (size_t i = 0; i < feats.size(); i++) {
      Feature feat = (Feature) feats[i];
      Type rangeType;
      feat.getRangeType(rangeType);
      if (rangeType.isValid()) {
        lowlevel::TyFSType  rangetypecode = uima::internal::FSPromoter::demoteType(rangeType);
        lowlevel::TyFSFeature featcode = uima::internal::FSPromoter::demoteFeature(feat);

        //if not primitive
        if (iv_cas->getTypeSystem().isFSType(rangetypecode)  ||
          (iv_cas->getTypeSystem().isArrayType(rangetypecode) && 
          feat.isMultipleReferencesAllowed() ) || 
          (iv_cas->getTypeSystem().isListType(rangetypecode) && 
          feat.isMultipleReferencesAllowed()) ) {
            //get the current feature value which is the id
            lowlevel::TyFS featVal = iv_casimpl.getHeap().getFeatureInternal(addr, featcode);
            if (featVal != 0) {
              int fsValAddr = 0;
              try {
                //cout << __LINE__ << feat.getName() << " calling getFsAddrForXmiId " << featVal << endl;
                fsValAddr = getFsAddrForXmiId(featVal);		 
              } catch (Exception e) {
                if (!lenient) {
                  throw e;
                }
                else {
                  //this may be a reference to an out-of-typesystem FS
                  stringstream str;
                  str << featVal;
                  this->sharedData->addOutOfTypeSystemAttribute(addr, 
                      ((UnicodeStringRef)feat.getName()).asUTF8(), str.str());
                }       
              }
              iv_casimpl.getHeap().setFSValue(addr, featcode, fsValAddr);
            }
         }
      }
    }
  }


  void XmiDeserializerHandler::finalizeArray(Type & type, lowlevel::TyFS addr) {

    lowlevel::TyFSType typecode = uima::internal::FSPromoter::demoteType(type);
    if (!iv_cas->getTypeSystem().isFSArrayType(typecode)) {
      return;
    }
    // *** WARNING ***  *** WARNING ***  *** WARNING ***  *** WARNING ***
    // if implementation of ArrayFS on the heap changes, this code will be invalid
    int size = (int)iv_cas->getHeap()->getHeap().getHeapValue(addr + 1);
	
    for (int i=0; i<size; i++) {
      lowlevel::TyFS arrayVal = iv_cas->getHeap()->getHeap().getHeapValue(addr + 2 + i);
      if (arrayVal != 0) {
        int arrayValAddr = 0;
        try {
          //cout << __LINE__ << " calling getFsAddrForXmiId " << arrayVal << endl;
          arrayValAddr = getFsAddrForXmiId(arrayVal);
        } catch (Exception e) {
          if (!lenient) {
            throw e;
          }
          else {  
            // the array element may be out of typesystem.  In that case set it
            // to null, but record the id so we can add it back on next serialization.
            this->sharedData->addOutOfTypeSystemArrayElement(addr, i, arrayVal);
          }
        }
        iv_cas->getHeap()->getHeap().setHeapValue(addr + 2 + i, arrayValAddr);
      }
    }
  }

   /**
     * Gets the FS address into which the XMI element with the given ID
     * was deserialized.  This method supports merging multiple XMI documents
     * into a single CAS, by checking the XmiSerializationSharedData
     * structure to get the address of elements that were skipped during this
     * deserialization but were deserialized during a previous deserialization.
     * 
     * @param xmiId
     * @return
     */
  int XmiDeserializerHandler::getFsAddrForXmiId(int xmiId) {
    int addr = sharedData->getFsAddrForXmiId(xmiId);
		//cout << "xmiid=" << xmiId << "fsaddr=" << addr << endl;
    if (addr > 0)
        return addr;
	   else {  
      //cerr << __FILE__<<__LINE__ <<  " throw exc No such xmiid " << xmiId << endl;
		  ErrorInfo errInfo;
		  errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
		  ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
		  assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
		  msg.addParam("getFsAddrForXmiId");
		  msg.addParam(xmiId);
		  errInfo.setMessage(msg);
		  errInfo.setSeverity(ErrorInfo::unrecoverable);
		  ExcIllFormedInputError exc(errInfo);
		  throw exc; 
	  }
  }

	/**
   * Adds a feature sturcture to the out-of-typesystem data.  Also sets the
   * this->outOfTypeSystemElement field, which is referred to later if we have to
   * handle features recorded as child elements.
   */
  void XmiDeserializerHandler::addToOutOfTypeSystemData(XmlElementName * xmlElementName, const Attributes & attrs) {
    this->outOfTypeSystemElement = new OotsElementData();
    //this->outOfTypeSystemElement->elementName = xmlElementName->qualifiedName;
	  this->outOfTypeSystemElement->elementName = xmlElementName;
    icu::UnicodeString attrName;
	  icu::UnicodeString attrValue;
    for (size_t i = 0; i < attrs.getLength(); i++) {
      attrName = attrs.getQName(i);
      attrValue = attrs.getValue(i);
      if (attrName.compare(icu::UnicodeString(XMI_ID_ATTR_NAME))==0) {
		    UnicodeStringRef uref(attrValue);
        this->outOfTypeSystemElement->xmiId = atoi(uref.asUTF8().c_str());
      }
      else {
        this->outOfTypeSystemElement->attributes.push_back(
                  new XmlAttribute(attrName, attrValue));
      }
    }
    this->sharedData->addOutOfTypeSystemElement(this->outOfTypeSystemElement);
  }    

    /**
     * Adds a feature to the out-of-typesystem features list.
     * @param ootsElem object to which to add the feature
     * @param featName name of feature
     * @param featVals feature values, as a list of strings
     */
  void XmiDeserializerHandler::addOutOfTypeSystemFeature(OotsElementData * ootsElem, 
		icu::UnicodeString & featName, 
		vector<icu::UnicodeString> & featVals) {
	  vector<string> * pVals = new vector<string>;
    for (size_t i=0;i<featVals.size();i++) {
		  pVals->push_back(  ((UnicodeStringRef)featVals.at(i)).asUTF8());    
    }
	  ootsElem->childElements[ ((UnicodeStringRef)featName).asUTF8()] = pVals;
  } 
// ---------------------------------------------------------------------------
//  XmiDeserializerHandler: Overrides of the SAX ErrorHandler interface
// ---------------------------------------------------------------------------
  void XmiDeserializerHandler::error(const SAXParseException& e) {
    ErrorInfo errInfo;
    errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
    ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_ERROR);
    assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
    msg.addParam((UChar const *)e.getSystemId());
    msg.addParam(e.getLineNumber());
    msg.addParam(e.getColumnNumber());
    msg.addParam((UChar const *) e.getMessage());
    errInfo.setMessage(msg);
    errInfo.setSeverity(ErrorInfo::unrecoverable);
    ExcIllFormedInputError exc(errInfo);
    throw exc;
  }

  void XmiDeserializerHandler::fatalError(const SAXParseException& e) {
    ErrorInfo errInfo;
    errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
    ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_FATALERROR);
    assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
    msg.addParam((UChar const *)e.getSystemId());
    msg.addParam(e.getLineNumber());
    msg.addParam(e.getColumnNumber());
    msg.addParam((UChar const *) e.getMessage());
    errInfo.setMessage(msg);
    errInfo.setSeverity(ErrorInfo::unrecoverable);
    ExcIllFormedInputError exc(errInfo);
    throw exc;
  }

  void XmiDeserializerHandler::warning(const SAXParseException& e) {
    ErrorInfo errInfo;
    errInfo.setErrorId((TyErrorId)UIMA_ERR_RESOURCE_CORRUPTED);
    ErrorMessage msg(UIMA_MSG_ID_EXC_XML_SAXPARSE_WARNING);
    assertWithMsg(sizeof(XMLCh) == sizeof(UChar), "Port required");
    msg.addParam((UChar const *)e.getSystemId());
    msg.addParam(e.getLineNumber());
    msg.addParam(e.getColumnNumber());
    msg.addParam((UChar const *) e.getMessage());
    errInfo.setMessage(msg);
    errInfo.setSeverity(ErrorInfo::unrecoverable);
    ExcIllFormedInputError exc(errInfo);
    throw exc;
  }

  char const * XmiDeserializerHandler::XMI_ID_ATTR_NAME = "xmi:id";
  char const * XmiDeserializerHandler::TRUE_VALUE = "true";
  char const * XmiDeserializerHandler::DEFAULT_CONTENT_FEATURE = "value";
  char const * XmiDeserializerHandler::DEFAULT_NAMESPACE_URI = "http:///uima/noNamespace.ecore";


} // namespace uima



