/* * 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 using namespace std; namespace commonj { namespace sdo { using internal::XSDPropertyInfo; using internal::PropertyDefinitionImpl; using internal::XSDTypeInfo; using internal::TypeDefinitionImpl; using internal::SDOUtils; SDOSAX2Parser::SDOSAX2Parser( DataFactoryPtr df, const SDOXMLString& targetNamespace, DataObjectPtr& rootDO, ParserErrorSetter* insetter ) : dataFactory(staticCast(df)), targetNamespaceURI(targetNamespace), rootDataObject(rootDO), currentDataObject(0), isDataGraph(false), ignoreEvents(false), dealingWithChangeSummary(false), csbuilder(0), SAX2Parser(insetter), rootElementName(""), rootElementURI("") { 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(); rootElementURI = ""; rootElementName = ""; } void SDOSAX2Parser::setRootElementName(const SDOXMLString& name) { rootElementName = name; } void SDOSAX2Parser::setRootElementURI(const SDOXMLString& uri) { rootElementURI = uri; } 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(); PropertyPtr prop = refsIter->dataObject->getInstanceProperty((const char*)refsIter->property); if (!prop) { SDOString msg("Cannot find property: "); msg += (const char*)refsIter->property; throw SDOPropertyNotFoundException(TUSCANY_SDO_EINFO, msg.c_str()); } 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 = getRawPointer(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 { const PropertyImpl* prop = 0; const TypeImpl* ti = dataFactory->findTypeImpl(propuri,"RootType"); if (ti != 0) { prop = (const PropertyImpl*)ti->getPropertyImpl(propname); } else { ti = dataFactory->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 = getRawPointer(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::IntType: ((DataObjectImpl*)dob)->defineInt(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 = getRawPointer(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 { const TypeImpl* ti = 0; const PropertyImpl* prop = 0; SDOXMLString propertyName; ti = dataFactory->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::IntType: pprop = ((DataObjectImpl*)dob)->defineInt(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(SDOUtils::sdoURI, "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(SDOUtils::sdoURI)) { /////////////////////////////////////////////////////////////////////// // 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; rootElementURI = tns; } else { rootElementURI = URI; } // Check for localname as a property of the RootType // if we do not already know the type if (typeName.isNull()) { try { const Type& rootType = dataFactory->getType(tns, "RootType"); propertyName = getSDOName(rootType, localname); const Type& newType = ((TypeImpl&)(rootType)).getRealPropertyType(propertyName); typeURI = newType.getURI(); typeName = newType.getName(); } catch (const SDOTypeNotFoundException&) { typeURI = SDOUtils::sdoURI; typeName = "OpenDataObject"; } } // Create the root DataObject if (isDataGraph) { DataObjectPtr rootdo = dataFactory->create(tns, "RootType"); setCurrentDataObject(rootdo); changeSummaryDO = currentDataObject; } else { rootElementName = 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 = getRawPointer(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) { PropertyPtr p = currentPropertySetting.dataObject->getInstanceProperty( "value"); if (!p) { throw SDOPropertyNotFoundException(TUSCANY_SDO_EINFO, "Cannot find property: 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 { PropertyPtr p = currentPropertySetting.dataObject->getInstanceProperty( (const char*)currentPropertySetting.name); if (!p) { SDOString msg("Cannot find property: "); msg += (const char*)currentPropertySetting.name; throw SDOPropertyNotFoundException(TUSCANY_SDO_EINFO, msg.c_str()); } if (p->isMany()) { DataObjectList& dl = currentPropertySetting.dataObject-> getList(*p); dl.append((const char*)currentPropertySetting.getStringWithCDataMarkers().c_str()); } else { currentPropertySetting.dataObject-> setCString(*p, 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 ChangeSummaryPtr 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 = getRawPointer(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 TypeImpl& typeImpl = dynamic_cast(type); const std::vector pl = typeImpl.getPropertyListReference(); for (std::vector::const_iterator i = pl.begin(); i != pl.end(); i++) { XSDPropertyInfo* pi = (XSDPropertyInfo*) ((DASProperty*) getRawPointer(*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