diff options
author | dims <dims@13f79535-47bb-0310-9956-ffa450edef68> | 2008-06-17 00:23:01 +0000 |
---|---|---|
committer | dims <dims@13f79535-47bb-0310-9956-ffa450edef68> | 2008-06-17 00:23:01 +0000 |
commit | bdd0a41aed7edf21ec2a65cfa17a86af2ef8c48a (patch) | |
tree | 38a92061c0793434c4be189f1d70c3458b6bc41d /tags/cpp-sdo-1.0.incubating-M3/runtime/core/src/commonj/sdo/SDOSAX2Parser.cpp |
Move Tuscany from Incubator to top level.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@668359 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'tags/cpp-sdo-1.0.incubating-M3/runtime/core/src/commonj/sdo/SDOSAX2Parser.cpp')
-rw-r--r-- | tags/cpp-sdo-1.0.incubating-M3/runtime/core/src/commonj/sdo/SDOSAX2Parser.cpp | 1517 |
1 files changed, 1517 insertions, 0 deletions
diff --git a/tags/cpp-sdo-1.0.incubating-M3/runtime/core/src/commonj/sdo/SDOSAX2Parser.cpp b/tags/cpp-sdo-1.0.incubating-M3/runtime/core/src/commonj/sdo/SDOSAX2Parser.cpp new file mode 100644 index 0000000000..73ba050b34 --- /dev/null +++ b/tags/cpp-sdo-1.0.incubating-M3/runtime/core/src/commonj/sdo/SDOSAX2Parser.cpp @@ -0,0 +1,1517 @@ +/* + * 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. + */ + +/* $Rev$ $Date$ */ + +#include "commonj/sdo/SDOSAX2Parser.h" + +#include "commonj/sdo/SDORuntimeException.h" +#include "commonj/sdo/ChangeSummary.h" +#include "commonj/sdo/XSDPropertyInfo.h" +#include "commonj/sdo/XMLQName.h" +#include "commonj/sdo/DASProperty.h" +#include "commonj/sdo/Logging.h" +#include "commonj/sdo/DASType.h" +#include "commonj/sdo/XSDTypeInfo.h" +#include "commonj/sdo/TypeImpl.h" +#include "commonj/sdo/DataObjectImpl.h" +#include "commonj/sdo/DataFactoryImpl.h" +#include "commonj/sdo/SDOUtils.h" +#include <stdio.h> +using namespace std; + +namespace commonj +{ + namespace sdo + { + + SDOSAX2Parser::SDOSAX2Parser( + DataFactoryPtr df, + const SDOXMLString& targetNamespace, + DataObjectPtr& rootDO, + ParserErrorSetter* insetter + ) + + : dataFactory(df), + targetNamespaceURI(targetNamespace), + rootDataObject(rootDO), + currentDataObject(0), + isDataGraph(false), + ignoreEvents(false), + dealingWithChangeSummary(false), + csbuilder(0), + SAX2Parser(insetter) + + + { + reset(); + if (targetNamespace.isNull()) + { + targetNamespaceURI = ""; + } + rootDataObject = 0; + newSequence = true; + } + + SDOSAX2Parser::~SDOSAX2Parser() + { + } + + void SDOSAX2Parser::reset() + { + rootDataObject = 0; + currentDataObject = 0; + isDataGraph = false; + ignoreEvents = false; + changeSummary = false; + IDMap.empty(); + IDRefs.empty(); + } + + + void SDOSAX2Parser::startDocument() + { + LOGINFO(INFO,"SDOSAX2Parser: startDocument"); + setNamespaces = true; + reset(); + } + + void SDOSAX2Parser::endDocument() + { + LOGENTRY(INFO,"SDOSAX2Parser: endDocument"); + // Iterate over IDREFs list and set references + ID_REFS::iterator refsIter; + for (refsIter = IDRefs.begin(); refsIter != IDRefs.end(); refsIter++) + { + try + { + const Type& type = refsIter->dataObject->getType(); + const Property& prop = refsIter->dataObject->getProperty((const char*)refsIter->property); + const Type& propType = ((TypeImpl&)type).getRealPropertyType(refsIter->property); + + // Allowing referenes to DataObjects only + if (!propType.isDataType()) + { + DataObjectPtr reffedDO; + ID_MAP::iterator idIter = IDMap.find(refsIter->value); + if (idIter != IDMap.end()) + { + reffedDO = idIter->second; + } + else + { + // assume it is an XPath? + + // Remove #/ from front of XPATH as getDataObject doeesnt + // support this yet - it does now + //SDOXMLString xpath(refsIter->value); + //if (xpath.firstIndexOf('#') == 0) + // xpath = xpath.substring(1); + //if (xpath.firstIndexOf('/') == 0) + // xpath = xpath.substring(1); + + reffedDO = rootDataObject->getDataObject((const char*)refsIter->value); + } + + if (!reffedDO) + { + continue; + } + + if (prop.isMany()) + { + DataObjectList& dol = refsIter->dataObject->getList(prop); + dol.append(reffedDO); + } + else + { + refsIter->dataObject->setDataObject(prop, reffedDO); + } + } + + } + catch (const SDORuntimeException&) + { + } + } + try { + // Now rebuild the changeSummary + if (csbuilder != 0) + { + csbuilder->buildChangeSummary(changeSummaryDO); + delete csbuilder; + csbuilder = 0; + } + } + catch (SDORuntimeException&) + { + } + + LOGEXIT(INFO,"SDOSAX2Parser: endDocument"); + } + + + bool SDOSAX2Parser::setDO(DataObjectPtr newDO, + SDOXMLString& propertyName) + { + LOGENTRY(INFO,"SDOSAX2Parser: setDO"); + + if (currentDataObject) + { + const Type& type = currentDataObject->getType(); + // go lower level so we can find open properties w/o exception + DataObject* dob = currentDataObject; + const PropertyImpl* pprop = ((DataObjectImpl*)dob)->getPropertyImpl((const char*)propertyName); + if (pprop == 0) + { + + LOGEXIT(INFO,"SDOSAX2Parser: setDO - exit1"); + return false; + } + + const Property& property = (Property&)*pprop; + //const Type& propertyType = ((TypeImpl&)type).getRealPropertyType(propertyName); + if (currentDataObject->getType().isSequencedType()) + { + SequencePtr seq = currentDataObject->getSequence(); + seq->addDataObject(property, newDO); + } + else + { + if (!property.isMany()) + { + currentDataObject->setDataObject((const char*)propertyName, newDO); + } + else + { + DataObjectList& dol = currentDataObject->getList((const char*)propertyName); + dol.append(newDO); + } + } + } + + setCurrentDataObject(newDO); + + LOGEXIT(INFO,"SDOSAX2Parser: setDO - exit2"); + return true; + } + + void SDOSAX2Parser::handleOpenAttribute( + SDOXMLString& tns, + const SDOXMLString& propuri, + const SDOXMLString& propname, + const SDOXMLString& value) + { + // first, see if there is a global element or attribute corresponding... + try + { + DataFactory* df = dataFactory; + const PropertyImpl* prop = 0; + const TypeImpl* ti = + ((DataFactoryImpl*)df)->findTypeImpl(propuri,"RootType"); + + if (ti != 0) + { + prop = (const PropertyImpl*)ti->getPropertyImpl(propname); + } + else + { + ti = ((DataFactoryImpl*)df)->findTypeImpl(tns,"RootType"); + } + + if (ti != 0) + { + prop = (const PropertyImpl*)ti->getPropertyImpl(propname); + } + + if (prop == 0) + { + // need to use the sequence interface if it exists + if (currentDataObject->getType().isSequencedType()) + { + SequencePtr seq = currentDataObject->getSequence(); + seq->addCString(propname, value); + } + else + { + currentDataObject->setCString((const char*)propname,value); + } + return; + } + + DataObject* dob = currentDataObject; + + switch (prop->getTypeEnum()) + { + case Type::BooleanType: + ((DataObjectImpl*)dob)->defineBoolean(propname); + break; + case Type::ByteType: + ((DataObjectImpl*)dob)->defineByte(propname); + break; + case Type::CharacterType: + ((DataObjectImpl*)dob)->defineCharacter(propname); + break; + case Type::BytesType: + ((DataObjectImpl*)dob)->defineBytes(propname); + break; + case Type::StringType: + ((DataObjectImpl*)dob)->defineString(propname); + break; + case Type::ShortType: + ((DataObjectImpl*)dob)->defineShort(propname); + break; + case Type::IntegerType: + ((DataObjectImpl*)dob)->defineInteger(propname); + break; + case Type::LongType: + ((DataObjectImpl*)dob)->defineLong(propname); + break; + case Type::DoubleType: + ((DataObjectImpl*)dob)->defineDouble(propname); + break; + case Type::FloatType: + ((DataObjectImpl*)dob)->defineFloat(propname); + break; + case Type::DateType: + ((DataObjectImpl*)dob)->defineDate(propname); + break; + } // switch + + // regardless of what type the property now is, we can set CString , and the + // right conversion will happen + + // need to use the sequence interface if it exists. + if (currentDataObject->getType().isSequencedType()) + { + SequencePtr seq = currentDataObject->getSequence(); + seq->addCString(propname, value); + } + else + { + currentDataObject->setCString((const char*)propname,value); + } + } + catch (SDORuntimeException) + { + } + return; + } + + + void SDOSAX2Parser::setAttributes( + SDOXMLString& tns, + const SAX2Namespaces& namespaces, + const SAX2Attributes& attributes) + { + + LOGENTRY(INFO,"SDOSAX2Parser::setAttributes"); + + ////////////////////////////////////////////// + // The attributes are properties on the new DO + // Handle attributes + ////////////////////////////////////////////// + for (int i=0; i < attributes.size(); i++) + { + // Should ignore attributes like xsi:type + if (!(attributes[i].getUri().equalsIgnoreCase("http://www.w3.org/2001/XMLSchema-instance"))) + { + try + { + const SDOXMLString& propertyName = getSDOName(*currentDataObjectType, attributes[i].getName()); + DataObject* dob = currentDataObject; + const PropertyImpl* pprop = ((DataObjectImpl*)dob)->getPropertyImpl(propertyName); + if (pprop == 0 ) + { + if (currentDataObject->getType().isOpenType()) + { + // if its an open type, then attributes will be allowed to have + // an invalid name, and setCString will create them all as bytes + handleOpenAttribute(tns, attributes[i].getUri(), + attributes[i].getName(), + attributes[i].getValue()); + + } + else + { + LOGERROR_1(WARNING,"SDOSAX2Parser: Property not found on closed type (ignored):%s", + (const char*)(attributes[i].getName())); + } + } + else + { + const Property& prop = (Property&)*pprop; + SDOXMLString propValue; + + XSDPropertyInfo* pi = (XSDPropertyInfo*)((DASProperty*)&prop)->getDASValue("XMLDAS::PropertyInfo"); + if (pi && pi->getPropertyDefinition().isElement) + { + // xml instance is trying to set an attribute when schema defines property as element + LOGERROR_1(WARNING,"SDOSAX2Parser: Attribute %s should be an element. Attribute ignored", + (const char*)(attributes[i].getName())); + continue; + } + + if (pi && pi->getPropertyDefinition().isQName) + { + XMLQName qname(attributes[i].getValue(), + documentNamespaces, namespaces); + propValue = qname.getSDOName(); + } + else + { + propValue = attributes[i].getValue(); + } + + if ((pi && pi->getPropertyDefinition().isIDREF) + || prop.isReference()) + { + // remember this value to resolve later + IDRef ref(currentDataObject, attributes[i].getName(), propValue); + IDRefs.push_back(ref); + } + else + { + if (pi && pi->getPropertyDefinition().isID) + { + // add this ID to the map + IDMap[propValue] = currentDataObject; + } + // Always set the property as a String. SDO will do the conversion + currentDataObject->setCString((const char*)attributes[i].getName(), propValue); + } + } + } + catch (const SDOPropertyNotFoundException&) + { + LOGERROR_1(WARNING,"SDOSAX2Parser: Error processing attribute (ignored):%s", + (const char*)(attributes[i].getName())); + } + } + } // End iterate over attributes + + LOGEXIT(INFO,"SDOSAX2Parser:setAttributes"); + + } + + + const PropertyImpl* SDOSAX2Parser::handleOpenType( + SDOXMLString& tns, + const SDOXMLString& localname, + DataObjectImpl* dob, + const SAX2Namespaces& namespaces, + const SAX2Attributes& attributes, + SDOXMLString& xsitypeURI, + SDOXMLString& xsitypeName, + bool bToBeNull) + { + // first, see if there is a global element or attribute corresponding... + const PropertyImpl* pprop; + DataObjectPtr newDO = 0; + try + { + DataFactory* df = dataFactory; + const TypeImpl* ti = 0; + const PropertyImpl* prop = 0; + SDOXMLString propertyName; + + ti = ((DataFactoryImpl*)df)->findTypeImpl(tns,"RootType"); + if (ti != 0) + { + propertyName = getSDOName((Type&)*ti, localname); + prop = ti->getPropertyImpl(propertyName); + } + else + { + propertyName = localname; + } + + if (prop != 0) + { + if (prop->isMany()) + { + pprop = ((DataObjectImpl*)dob)->defineList(propertyName); + + // the type of the list needs to be set, as chars sets a CString + try + { + DataObjectList& dl = ((DataObjectImpl*)dob)->getList((const char*)propertyName); + ((DataObjectListImpl*)&dl)->setType(prop->getType().getURI(), + prop->getType().getName()); + } + catch (SDORuntimeException) + { + // let it pass - the type will be Bytes + } + + if (prop->getType().isDataType()) + { + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + } + else + { + newDO = dataFactory->create( + prop->getType().getURI(), + prop->getType().getName()); + // here we need to use the sequence interface if it exists. + if (dob->getType().isSequencedType()) + { + SequencePtr seq = currentPropertySetting.dataObject->getSequence(); + seq->addDataObject(propertyName,newDO); + } + else + { + DataObjectList& dol = dob->getList((const char*)propertyName); + dol.append(newDO); + } + setCurrentDataObject(newDO); + setAttributes(tns, namespaces,attributes); + } + return pprop; + } + else + { + switch (prop->getTypeEnum()) + { + case Type::BooleanType: + pprop = ((DataObjectImpl*)dob)->defineBoolean((const char*)propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::ByteType: + pprop = ((DataObjectImpl*)dob)->defineByte((const char*)propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::CharacterType: + pprop = ((DataObjectImpl*)dob)->defineCharacter(propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::BytesType: + pprop = ((DataObjectImpl*)dob)->defineBytes(propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::StringType: + pprop = ((DataObjectImpl*)dob)->defineString(propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::ShortType: + pprop = ((DataObjectImpl*)dob)->defineShort(propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::IntegerType: + pprop = ((DataObjectImpl*)dob)->defineInteger(propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::LongType: + pprop = ((DataObjectImpl*)dob)->defineLong(propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::DoubleType: + pprop = ((DataObjectImpl*)dob)->defineDouble(propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::FloatType: + pprop = ((DataObjectImpl*)dob)->defineFloat(propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::DateType: + pprop = ((DataObjectImpl*)dob)->defineDate(propertyName); + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + break; + case Type::DataObjectType: + pprop = ((DataObjectImpl*)dob)->defineDataObject(propertyName, + prop->getType().getURI(), prop->getType().getName()); + newDO = dataFactory->create( + prop->getType().getURI(), + prop->getType().getName()); + // here we need to use the sequence interface if it exists. + if (dob->getType().isSequencedType()) + { + SequencePtr seq = dob->getSequence(); + seq->addDataObject(propertyName, newDO); + } + else + { + dob->setDataObject((const char*)propertyName, newDO); + } + setCurrentDataObject(newDO); + setAttributes(tns,namespaces,attributes); + break; + } + } // else + } // if prop != 0 + else + { + // The type is open, and the property doesnt exist, so we are creating + // a property, and need to find out the type to create. + // As I cannot tell if its a single value or many valued, I create all + // as many valued + // could be data object or primitive. All primitives will appear + // as bytes. + // UPDATE: Spec says that all elements will appear as DataObjects which + // are sequenced - the text will come out as text elements in the sequence + + if (!xsitypeName.isNull()) + { + // it has a type from xsi:type + newDO = dataFactory->create((const char*)xsitypeURI, (const char*)xsitypeName); + } + else + { + newDO = dataFactory->create(Type::SDOTypeNamespaceURI, "OpenDataObject"); + } + pprop = ((DataObjectImpl*)dob)->defineList(propertyName); + // here we need to use the sequence interface if it exists. + if (dob->getType().isSequencedType()) + { + SequencePtr seq = dob->getSequence(); + seq->addDataObject(propertyName, newDO); + } + else + { + DataObjectList& dol = dob->getList((const char*)propertyName); + dol.append(newDO); + } + setCurrentDataObject(newDO); + setAttributes(tns,namespaces,attributes); + } + return pprop; + } + catch (SDORuntimeException) + { + // fail to find the property or create a dummy + return 0; + } + } + + void SDOSAX2Parser::startElementNs( + const SDOXMLString& localname, + const SDOXMLString& prefix, + const SDOXMLString& URI, + const SAX2Namespaces& namespaces, + const SAX2Attributes& attributes) + + { + LOGENTRY(INFO,"SDOSAX2Parser: startElementNs"); + + LOGINFO_1(INFO,"SDOSAX2Parser: startElementNs:%s", + (const char*)localname); + + newSequence = true; + + bool bToBeNull = false; + // Save the namespace information from the first element + if (setNamespaces) + { + documentNamespaces = namespaces; + setNamespaces = false; + } + else + { + documentNamespaces.merge(namespaces); + } + + if (ignoreEvents) + { + // Check for the tag we are waiting for + if ( (ignoreTag.localname.equals(localname)) + && (ignoreTag.uri.equals(URI)) + && (ignoreTag.prefix.equals(prefix)) ) + { + ignoreTag.tagCount++; + } + LOGEXIT(INFO,"SDOSAX2Parser: startElementNs - exit1"); + return; + } + + if (URI.equalsIgnoreCase("http://www.w3.org/2001/XMLSchema")) + { + // ignore anything within a schema + LOGINFO_1(INFO,"SDOSAX2Parser ignores schema element:%s", + (const char *)localname); + + // We need to ignore all events until the end tag for this element + ignoreEvents = true; + ignoreTag.localname = localname; + ignoreTag.uri = URI; + ignoreTag.prefix = prefix; + ignoreTag.tagCount = 0; + return; + } + + + + if (dealingWithChangeSummary) + { + if (csbuilder == 0) + { + LOGERROR(ERROR,"SDOSAX2Parser:Parser builds summary with no builder"); + LOGEXIT(INFO,"SDOSAX2Parser: startElementNs - exit2"); + return; + } + csbuilder->processStart( + localname, + prefix, + URI, + namespaces, + attributes); + LOGEXIT(INFO,"SDOSAX2Parser: startElementNs - exit3"); + return; + } + + + if (URI.equalsIgnoreCase(Type::SDOTypeNamespaceURI.c_str())) + { + /////////////////////////////////////////////////////////////////////// + // Handle datagraph + /////////////////////////////////////////////////////////////////////// + if (localname.equalsIgnoreCase("datagraph")) + { + // Remember this is a datagraph. The root DO will be created + // later when we can have a better guess at the namespaceURI + isDataGraph = true; + } // end handling sdo:datagraph + + //////////////////////////////////// + // Handle ChangeSummary on datagraph + //////////////////////////////////// + if (localname.equals("changeSummary")) + { + changeSummary = true; + changeSummaryDO = currentDataObject; + + csbuilder = new ChangeSummaryBuilder( + dataFactory, rootDataObject ); + + changeSummaryLogging = true; + + + SDOXMLString logging = attributes.getValue("logging"); + if (!logging.isNull()) + { + if (logging.equals("false")) + { + changeSummaryLogging = false; + } + } + + LOGINFO(INFO,"SDOSAX2Parser:Start change summary"); + dealingWithChangeSummary = true; + LOGEXIT(INFO,"SDOSAX2Parser: startElementNs - exit4"); + return; + + } + + } + else + { + /////////////////////////////////////////////////////////////////////// + // Each element is a DataObject or a Property on the current DO + /////////////////////////////////////////////////////////////////////// + DataObjectPtr newDO = 0; + + SDOXMLString typeURI, typeName, propertyName; + + /////////////////////////////////////////////////////////////////////// + // Determine the type. It is either specified by the xsi:type attribute + // or the localname is the name of a property on "RootType" + /////////////////////////////////////////////////////////////////////// + int i; + for (i=0; i < attributes.size(); i++) + { + if (attributes[i].getUri().equalsIgnoreCase("http://www.w3.org/2001/XMLSchema-instance")) + { + if (attributes[i].getName().equalsIgnoreCase("type")) + { + SDOXMLString fullTypeName = attributes[i].getValue(); + SDOXMLString pref; + + int index = fullTypeName.firstIndexOf(':'); + if (index < 0) + { + typeName = fullTypeName; + } + else + { + // Is the namespace prefix defined? + typeName = fullTypeName.substring(index+1); + pref = fullTypeName.substring(0, index); + } + + // Convert the prefix to a namespace URI + const SDOXMLString* namespaceURI = namespaces.find(pref); + if (namespaceURI == 0) + { + namespaceURI = documentNamespaces.find(pref); + } + if (namespaceURI != 0) + { + typeURI = *namespaceURI; + } + } + else if (attributes[i].getName().equalsIgnoreCase("nil")) + { + if (attributes[i].getValue().equalsIgnoreCase("true")) + { + // the current setting needs to be setNull + bToBeNull = true; + } + } + } + } // End - attribute loop + + if (typeURI.isNull()) + { + typeURI = ""; + } + + SDOXMLString tns = URI; + + if (tns.isNull()) + tns = ""; + + try + { + if (currentDataObject == 0) + { + // This element should become the root data object + + // Target namespace will be: + // the targetNamespaceURI if specified + // or the URI of xsi:type if specified + // or the URI of this element + if (!typeURI.equals("")) + { + tns = typeURI; + } + + if (!targetNamespaceURI.isNull() && !targetNamespaceURI.equals("")) + { + tns = targetNamespaceURI; + } + + // Check for localname as a property of the RootType + // if we do not already know the type + if (typeName.isNull()) + { + const Type& rootType = dataFactory->getType(tns, "RootType"); + propertyName = getSDOName(rootType, localname); + const Type& newType = + ((TypeImpl&)(rootType)).getRealPropertyType(propertyName); + + typeURI = newType.getURI(); + typeName = newType.getName(); + } + + // Create the root DataObject + if (isDataGraph) + { + DataObjectPtr rootdo = dataFactory->create(tns, "RootType"); + setCurrentDataObject(rootdo); + changeSummaryDO = currentDataObject; + } + else + { + DataFactory* df = dataFactory; + ((DataFactoryImpl*)df)->setRootElementName((const char*)localname); + } + + // NOTE: always creating DO doesn't cater for DataType as top element + + const Type& tp = dataFactory->getType((const char*)typeURI,typeName); + if (tp.isDataType()) + { + newDO = dataFactory->create(tns, "RootType"); + currentPropertySetting = PropertySetting(newDO, localname, + bToBeNull); + + // TODO - need instead to record the fact that its a primitive, not + // a real DO - and then present it as the root. + // newDO = dataFactory->create(tns, "RootType"); + // const Type& tpr = dataFactory->getType(tns,"RootType"); + // XSDTypeInfo* typeInfo = (XSDTypeInfo*) + // ((DASType*)&tpr)->getDASValue("XMLDAS::TypeInfo"); + // if (typeInfo) + // { + // TypeDefinitionImpl* td; + // td = (TypeDefinitionImpl*)&(typeInfo->getTypeDefinition()); + // if (td)td->isExtendedPrimitive = true; + // currentPropertySetting = PropertySetting(newDO, "value" /*localname*/, + // bToBeNull); + + // } + // else + // { + // currentPropertySetting = PropertySetting(newDO, localname, + // bToBeNull); + // } + + } + else + { + + newDO = dataFactory->create((const char*)typeURI, (const char*)typeName); + + // get the type definition, and see if its an extended primitive. + + XSDTypeInfo* typeInfo = (XSDTypeInfo*) + ((DASType*)&tp)->getDASValue("XMLDAS::TypeInfo"); + if (typeInfo) + { + const TypeDefinitionImpl& typeDefinition = typeInfo->getTypeDefinition(); + if (typeDefinition.isExtendedPrimitive) + { + // The name of this element is the name of a property on the current DO + currentPropertySetting = PropertySetting(newDO, localname, + bToBeNull); + } + } + } + + } // End - currentDataObject == 0 + + else + { // currentDataObject != 0 + + // Get the Property from the dataObject + propertyName = getSDOName(*currentDataObjectType, localname); + const Type& type = currentDataObject->getType(); + + + // go lower level so we can find open properties w/o exception + DataObject* dob = currentDataObject; + const PropertyImpl* pprop = ((DataObjectImpl*)dob)->getPropertyImpl(propertyName); + if (pprop == 0) + { + if (type.isOpenType()) + { + pprop = handleOpenType( + tns, + localname, + (DataObjectImpl*)dob, + namespaces, + attributes, + typeURI, + typeName, + bToBeNull); + } + if (pprop == 0) + { + // this is an open property , we will need to create it + LOGERROR_1(WARNING,"SDOSAX2Parser Unknown element:%s", + (const char *)localname); + + // We need to ignore all events until the end tag for this element + ignoreEvents = true; + ignoreTag.localname = localname; + ignoreTag.uri = URI; + ignoreTag.prefix = prefix; + ignoreTag.tagCount = 0; + if (setter != 0) + { + char *msg = new char[strlen((const char*)localname) + 32]; + if (msg) { + sprintf(msg,"Parser found unknown element %s", + (const char*)localname); + setter->setError( msg ); + delete[] msg; + } + } + } + LOGEXIT(INFO,"SDOSAX2Parser: startElementNs - exit5"); + return; + } + else + { + + const Property& prop = (Property&)*pprop; + const TypeImpl* propType = ((TypeImpl&)type).getRealPropertyTypeImpl(propertyName); + if (propType == 0) + { + // could be a previously created open type property + propType = (const TypeImpl*)pprop->getTypeImpl(); + } + if (propType != 0) + { + XSDPropertyInfo* pi = (XSDPropertyInfo*)((DASProperty*)&prop)->getDASValue("XMLDAS::PropertyInfo"); + if ((pi && pi->getPropertyDefinition().isIDREF) + || prop.isReference()) + { + // The name of this element is the name of a property on the current DO + currentPropertySetting = PropertySetting(currentDataObject, propertyName, bToBeNull, + true); + } + + // If it is a DataType then we need set the value + else if (propType->isDataType() ) + { + // The name of this element is the name of a property on the current DO + currentPropertySetting = PropertySetting(currentDataObject, propertyName, + bToBeNull); + } + else + { + + // If typeName is not set then create object of Type of Property + // otherwise use the typeURI and typeName specified by e.g. xsi:type + if (typeName.isNull()) + { + newDO = dataFactory->create(propType->getURI(), propType->getName()); + } + else + { + newDO = dataFactory->create((const char*)typeURI, (const char*)typeName); + } + + XSDTypeInfo* typeInfo = (XSDTypeInfo*) + ((DASType*)propType)->getDASValue("XMLDAS::TypeInfo"); + if (typeInfo && typeInfo->getTypeDefinition().isExtendedPrimitive) + { + // The name of this element is the name of a property on the current DO + currentPropertySetting = PropertySetting(newDO, "value", bToBeNull); + } + + } + } + } // End // currentDataObject != 0 + } // end prop != 0 + if (newDO) + { + if (!setDO(newDO, propertyName)) + { + LOGERROR_1(WARNING,"SDOSAX2Parser Unknown element:%s", + (const char *)localname); + + // We need to ignore all events until the end tag for this element + ignoreEvents = true; + ignoreTag.localname = localname; + ignoreTag.uri = URI; + ignoreTag.prefix = prefix; + ignoreTag.tagCount = 0; + if (setter != 0) + { + char *msg = new char[strlen((const char*)localname) + 32]; + if (msg) { + sprintf(msg,"Parser found unknown element %s", + (const char*)localname); + setter->setError( msg ); + delete msg; + } + } + LOGEXIT(INFO,"SDOSAX2Parser: startElementNs - exit6"); + return; + } + } + } // end try + + catch (const SDOTypeNotFoundException& ) + { + + LOGERROR_1(WARNING,"SDOSAX2Parser Unknown element:%s", + (const char *)localname); + + // We need to ignore all events until the end tag for this element + ignoreEvents = true; + ignoreTag.localname = localname; + ignoreTag.uri = URI; + ignoreTag.prefix = prefix; + ignoreTag.tagCount = 0; + if (setter != 0) + { + char *msg = new char[strlen((const char*)localname) + 32]; + if (msg) { + sprintf(msg,"Parser found unknown element %s", + (const char*)localname); + setter->setError( msg ); + delete[] msg; + } + } + LOGEXIT(INFO,"SDOSAX2Parser: startElementNs - exit7"); + return; + } + +#ifdef _DEBUG + catch (const SDOPropertyNotFoundException& e ) +#else + catch (const SDOPropertyNotFoundException& ) +#endif + { + LOGERROR_1(WARNING,"SDOSAX2Parser Unknown element exception:%s", + (const char *)localname); + LOGSDOEXCEPTION(WARNING,"Exception:",e); + + // We need to ignore all events until the end tag for this element + ignoreEvents = true; + ignoreTag.localname = localname; + ignoreTag.uri = URI; + ignoreTag.prefix = prefix; + ignoreTag.tagCount = 0; + if (setter != 0) + { + char *msg = new char[strlen((const char*)localname) + 32]; + if (msg) + { + sprintf(msg,"Parser found unknown element %s", + (const char*)localname); + setter->setError( msg ); + delete msg; + } + } + LOGEXIT(INFO,"SDOSAX2Parser: startElementNs - exit8"); + return; + } + + setAttributes(tns,namespaces, attributes); + + } + LOGEXIT(INFO,"SDOSAX2Parser: startElementNs - exit9"); + } + + + void SDOSAX2Parser::endElementNs( + const SDOXMLString& localname, + const SDOXMLString& prefix, + const SDOXMLString& URI) + { + + LOGENTRY(INFO,"SDOSAX2Parser: endElementNs"); + + newSequence = true; + + if (localname.equals("changeSummary")) + { + // end of change summary + dealingWithChangeSummary = false; + LOGINFO(INFO,"SDOSAX2Parser: Finished change summary"); + LOGEXIT(INFO,"SDOSAX2Parser: endElementNs - exit1"); + return; + } + + if (dealingWithChangeSummary) + + { + if (csbuilder == 0) + { + LOGERROR(WARNING,"SDOSAX2Parser: End change summary with no builder"); + LOGEXIT(INFO,"SDOSAX2Parser: endElementNs - exit2"); + return; + } + csbuilder->processEnd(localname, + prefix, + URI); + LOGEXIT(INFO,"SDOSAX2Parser: endElementNs - exit3"); + return; + } + + + if (ignoreEvents) + { + // Check for the tag we are waiting for + if ( (ignoreTag.localname.equals(localname)) + && (ignoreTag.uri.equals(URI)) + && (ignoreTag.prefix.equals(prefix)) ) + { + if (ignoreTag.tagCount == 0) + { + ignoreEvents = false; + } + ignoreTag.tagCount--; + } + LOGEXIT(INFO,"SDOSAX2Parser: endElementNs - exit4"); + return; + } + + // If currentPropertySetting is set (name is not null) + // then we need to set the property now + if (!currentPropertySetting.name.isNull()) + { + if (currentPropertySetting.isNULL) + { + + currentPropertySetting.dataObject-> + setNull((const char*)currentPropertySetting.name); + + } + else + { + if (currentPropertySetting.value.isNull()) + { + currentPropertySetting.value = SDOXMLString(""); + } + try + { + const Type& tp = currentPropertySetting.dataObject->getType(); + XSDTypeInfo* typeInfo = (XSDTypeInfo*) + ((DASType*)&tp)->getDASValue("XMLDAS::TypeInfo"); + if (typeInfo && typeInfo->getTypeDefinition().isExtendedPrimitive) + { + const Property& p = currentPropertySetting.dataObject->getProperty( + "value"); + if (p.isMany()) + { + // use the sequence interface if it exists. + if (currentPropertySetting.dataObject->getType().isSequencedType()) + { + SequencePtr seq = currentPropertySetting.dataObject->getSequence(); + seq->addCString("value", currentPropertySetting.getStringWithCDataMarkers().c_str()); + } + else + { + DataObjectList& dl = currentPropertySetting.dataObject-> + getList((const char*)"value"); + dl.append((const char*)currentPropertySetting.getStringWithCDataMarkers().c_str()); + } + + } + else + { + // use the sequence interface if it exists + if (currentPropertySetting.dataObject->getType().isSequencedType()) + { + SequencePtr seq = currentPropertySetting.dataObject->getSequence(); + seq->addCString("value", currentPropertySetting.getStringWithCDataMarkers().c_str()); + } + else + { + currentPropertySetting.dataObject-> +// setCString((const char*)"value", currentPropertySetting.value ); + setCString((const char*)"value", currentPropertySetting.getStringWithCDataMarkers().c_str() ); + } + } + if (dataObjectStack.size() == 0 || rootDataObject == dataObjectStack.top()) + { + currentDataObject = 0; + currentDataObjectType = 0; + } + else + { + dataObjectStack.pop(); + currentDataObject = dataObjectStack.top(); + currentDataObjectType = &(currentDataObject->getType()); + } + + } + else + { + if (currentPropertySetting.isIDREF) + { + // remember this value to resolve later + IDRef ref(currentPropertySetting.dataObject, + currentPropertySetting.name, + currentPropertySetting.value ); + IDRefs.push_back(ref); + } + else + { + if (currentPropertySetting.dataObject->getType().isSequencedType()) + { + SequencePtr seq = currentPropertySetting.dataObject->getSequence(); + seq->addCString(currentPropertySetting.name, currentPropertySetting.getStringWithCDataMarkers().c_str()); + } + // Always set the property as a String. SDO will do the conversion + + // It might be a single setting for a many-valued property. + // may throw SDOPropertyNotFoundException + else { + const Property& p = currentPropertySetting.dataObject->getProperty( + (const char*)currentPropertySetting.name); + if (p.isMany()) + { + DataObjectList& dl = currentPropertySetting.dataObject-> + getList((const char*)currentPropertySetting.name); + dl.append((const char*)currentPropertySetting.getStringWithCDataMarkers().c_str()); + } + else + { + currentPropertySetting.dataObject-> +// setCString((const char*)currentPropertySetting.name, currentPropertySetting.value ); + setCString((const char*)currentPropertySetting.name, currentPropertySetting.getStringWithCDataMarkers().c_str() ); + } + } + } + } + } +#ifdef _DEBUG + catch (const SDOPropertyNotFoundException& e) +#else + catch (const SDOPropertyNotFoundException&) +#endif + { + LOGSDOEXCEPTION(WARNING,"SDOSAX2Parser error attribute (ignored)",e); + } + } + currentPropertySetting = PropertySetting(); + + } + else + { + if (changeSummary + && changeSummaryLogging + && changeSummaryDO == currentDataObject) + { + // Set logging on for this DO before it is popped from stack + ChangeSummary* cs = currentDataObject->getChangeSummary(); + if (cs) + { + cs->beginLogging(); + } + changeSummary = false; + } + + if (dataObjectStack.size() == 0 || rootDataObject == dataObjectStack.top()) + { + currentDataObject = 0; + currentDataObjectType = 0; + } + else + { + dataObjectStack.pop(); + currentDataObject = dataObjectStack.top(); + currentDataObjectType = &(currentDataObject->getType()); + } + } + LOGEXIT(INFO,"SDOSAX2Parser: endElementNs - exit4"); + } + + + + void SDOSAX2Parser::characters(const SDOXMLString& chars) + { + if (chars.isNull()) return; + + if (!strcmp((const char*)chars,"\r") || + !strcmp((const char*)chars,"\n")) + { + newSequence = true; + return; + } + + if (dealingWithChangeSummary) + { + if (csbuilder == 0) + { + LOGERROR(WARNING,"SDOSAX2Parser: no builder"); + return; + } + csbuilder->processChars(chars); + return; + } + + if (ignoreEvents) + return; + + if (!currentPropertySetting.name.isNull()) + { + currentPropertySetting.value = currentPropertySetting.value + chars; + return; + } + DataObject* dob = currentDataObject; + if ((dob != 0) && ((DataObjectImpl*)dob)->getTypeImpl().isFromList()) + { + // this is a list,so we need to split it up + DataObjectList& dl = currentDataObject->getList( + (const char *)"values"); + + const char* str = (const char*)chars; + + // Convert any synthetic CDATA markers back to the real thing + SDOString valueString(str); + SDOString tmpString = SDOUtils::replace(valueString, SDOUtils::CDataStartMarker, SDOUtils::XMLCDataStartMarker); + tmpString = SDOUtils::replace(tmpString, SDOUtils::CDataEndMarker, SDOUtils::XMLCDataEndMarker); + str = (const char*)tmpString.c_str(); + + char* buf = new char[strlen(str)+1]; + if (!buf) return; + + strcpy(buf,str); + + int start_point = 0; + int end_point; + int final = strlen(buf); + + do { + if (start_point >= final)break; + while (buf[start_point] == (char)0x20 || buf[start_point] == (char)0x09 + || buf[start_point] == (char)0x0A || buf[start_point] == (char)0x0D )start_point++; + end_point = start_point; + while (buf[end_point] != (char)0x20 && buf[end_point] != (char)0x09 && + buf[end_point] != (char)0x0A && buf[end_point] != (char)0x0D && + buf[end_point] != 0x0)end_point++; + if (end_point == start_point)break; + *(buf+end_point) = 0; + dl.append((const char*)(buf+start_point)); + start_point = end_point + 1; + } while(1); + + delete[] buf; + return; + } + + + // If the current DataObject is a sequenced Type + // then add this as text to the sequence + if (currentDataObject && currentDataObjectType->isSequencedType()) + { + // Convert any synthetic CDATA markers back to the real thing + const char* str = (const char*)chars; + + SDOString valueString(str); + SDOString tmpString = SDOUtils::replace(valueString, SDOUtils::CDataStartMarker, SDOUtils::XMLCDataStartMarker); + tmpString = SDOUtils::replace(tmpString, SDOUtils::CDataEndMarker, SDOUtils::XMLCDataEndMarker); + str = tmpString.c_str(); + + SequencePtr seq = currentDataObject->getSequence(); + if (seq) + { + if (newSequence == true) + { + seq->addText(str); + newSequence = false; + } + else + { + for (int k= (int)(seq->size())-1; k>=0 ; k --) + { + if (seq->isText(k)) + { + const char * s = seq->getCStringValue(k); + + if (s) + { + char *combi = + new char[strlen(s)+strlen(str) + 2]; + strcpy(combi,s); + strcat(combi,str); + seq->setText(k,(const char*)combi); + delete[] combi; + } + else + { + seq->setText(k,str); + } + return; + } + } + seq->addText(str); + } + return; + } + } + + } + + + void SDOSAX2Parser::setCurrentDataObject(DataObjectPtr currentDO) + { + currentDataObject = currentDO; + dataObjectStack.push(currentDataObject); + currentDataObjectType = &(currentDataObject->getType()); + if (rootDataObject == 0) + { + rootDataObject = currentDataObject; + } + } + + const SDOXMLString& SDOSAX2Parser::getSDOName(const Type& type, const SDOXMLString& localName) + { + +/* XSDTypeInfo* typeInfo = (XSDTypeInfo*)((DASType*)&type)->getDASValue("XMLDAS::TypeInfo"); + if (typeInfo) + { + const TypeDefinitionImpl& typeDefinition = typeInfo->getTypeDefinition(); + XmlDasPropertyDefs::const_iterator propsIter; + for (propsIter = typeDefinition.properties.begin(); propsIter != typeDefinition.properties.end(); propsIter++) + { + const PropertyDefinitionImpl& prop = *propsIter; + if (prop.localname.equals(localName)) + { + return prop.name; + } + for (int i=0;i< prop.substituteNames.size();i++) + { + if (prop.substituteLocalNames[i].equals(localName)) + { + return prop.substituteNames[i]; + // possibly should be return prop.name; + } + } + } + } + */ + + const std::list<PropertyImpl*> pl = type.getPropertyListReference(); + + for (std::list<PropertyImpl*>::const_iterator i = pl.begin(); + i != pl.end(); + i++) + { + XSDPropertyInfo* pi = (XSDPropertyInfo*) + ((DASProperty*) (*i))->getDASValue("XMLDAS::PropertyInfo"); + + if (pi) + { + const PropertyDefinitionImpl& propdef = pi->getPropertyDefinition(); + if (localName .equals(propdef.localname)) + return propdef.name; + + for (unsigned int j=0;j< propdef.substituteNames.size();j++) + { + if (propdef.substituteLocalNames[j].equals(localName)) + { + return propdef.substituteNames[j]; + // possibly should be return propdef.name; + } + } + } + } + + + + return localName; + } + + + std::istream& operator>>(std::istream& input, SDOSAX2Parser& parser) + { + parser.stream(input); + + return input; + } + + std::istringstream& operator>>(std::istringstream& input, SDOSAX2Parser& parser) + { + parser.stream(input); + + return input; + } + + } // End - namespace sdo +} // End - namespace commonj + |