/* * 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. */ #include "apache/das/rdb/ApplyChanges.h" namespace apache { namespace das { namespace rdb { ApplyChanges::ApplyChanges(DASImpl& das, commonj::sdo::DataObjectPtr root) : summary(root->getChangeSummary()) { this->config = (const ConfigImpl*) &das.getConfig(); this->root = root; processRootDataObject(root); StatementPtr stmt = *das.getConnection()->createStatement(); try { for (std::list::iterator it = updateOrderList.begin() ; it != updateOrderList.end() ; it++) { (*it)->execute(stmt); } stmt->executeQuery("commit"); } catch (...) { stmt->executeQuery("rollback"); throw; } } ApplyChanges::~ApplyChanges(void) { for (std::map::iterator relationshipsIterator = relationships.begin() ; relationshipsIterator != relationships.end() ; relationshipsIterator++) { delete relationshipsIterator->second; } for (std::map::iterator tablesIterator = tables.begin() ; tablesIterator != tables.end() ; tablesIterator++) { delete tablesIterator->second; } for (std::map*>::iterator dasDataObjectsIterator = dasDataObjects.begin() ; dasDataObjectsIterator != dasDataObjects.end() ; dasDataObjectsIterator++) { std::list* list = dasDataObjectsIterator->second; for (std::list::iterator listIterator = list->begin() ; listIterator != list->end() ; listIterator++) { delete *listIterator; } delete list; } } void ApplyChanges::processRootDataObject(commonj::sdo::DataObjectPtr dataObject) { commonj::sdo::ChangedDataObjectList& changedObjects = summary->getChangedDataObjects(); std::list createdObjects; std::list deletedObjects; std::list modifiedObjects; for (unsigned int i = 0 ; i < changedObjects.size() ; i++) { if (changedObjects[i] == root) { continue; } processMetadata(changedObjects[i]); if (summary->isCreated(changedObjects[i])) { createdObjects.push_back(changedObjects[i]); } else if (summary->isDeleted(changedObjects[i])) { deletedObjects.push_back(changedObjects[i]); } else { modifiedObjects.push_back(changedObjects[i]); } //const commonj::sdo::SettingList& setting = summary->getOldValues(changedObjects[i]); } std::list::iterator deletedIterator; for (deletedIterator = deletedObjects.begin() ; deletedIterator != deletedObjects.end() ; deletedIterator++) { processDeletedDataObject(*deletedIterator); } std::list::iterator createdIterator; for (createdIterator = createdObjects.begin() ; createdIterator != createdObjects.end() ; createdIterator++) { processCreatedDataObject(*createdIterator); } std::list::iterator modifiedIterator; for (modifiedIterator = modifiedObjects.begin() ; modifiedIterator != modifiedObjects.end() ; modifiedIterator++) { processModifiedDataObject(*modifiedIterator); } } DASDataObject& ApplyChanges::processDataObject(commonj::sdo::DataObjectPtr dataObject) { if (summary->isCreated(dataObject)) { return processCreatedDataObject(dataObject); } else if (summary->isDeleted(dataObject)) { return processDeletedDataObject(dataObject); } else { return processModifiedDataObject(dataObject); } } void ApplyChanges::processMetadata(commonj::sdo::DataObjectPtr dataObject) { const commonj::sdo::Type& type = dataObject->getType(); std::map::iterator it = tables.find((std::string) type.getName()); if (it != tables.end()) { return; } const Table* configTable = config->getTableByTypeName((std::string) type.getName()); commonj::sdo::PropertyList properties = type.getProperties(); const std::map* configTableColumns; std::map* configTableColumnsByPropertyName = 0; Table* table; unsigned int pkColumnCount = 0; unsigned int pkFoundCount = 0; if (configTable != 0) { table = new Table(configTable->getTableName(), configTable->getTypeName()); configTableColumns = &configTable->getColumns(); configTableColumnsByPropertyName = new std::map(); pkColumnCount = configTable->getPKColumnCount(); for (std::map::const_iterator configTableColumnsIterator = configTableColumns->begin() ; configTableColumnsIterator != configTableColumns->end() ; configTableColumnsIterator++) { configTableColumnsByPropertyName->insert( std::make_pair(configTableColumnsIterator->second->getPropertyName(), configTableColumnsIterator->second)); } } else { table = new Table((std::string) type.getName()); } for (unsigned int j = 0 ; j < properties.size() ; j++) { if (properties[j].getType().isDataType()) { if (configTable != 0) { std::map::const_iterator configTableColumnsIterator = configTableColumnsByPropertyName->find(properties[j].getName()); if (configTableColumnsIterator != configTableColumnsByPropertyName->end()) { const Column& column = *configTableColumnsIterator->second; if (column.isPK()) { pkFoundCount++; } table->addColumn(column); } else { table->addColumn(properties[j].getName(), ODBCTypeHelper::getSQLType(properties[j].getType())); } } else { table->addColumn(properties[j].getName(), ODBCTypeHelper::getSQLType(properties[j].getType())); } } else { const Table* fkTable = config->getTableByTypeName(properties[j].getType().getName()); std::string fkTableName; if (fkTable == 0) { fkTableName = properties[j].getType().getName(); } else { fkTableName = fkTable->getTableName(); } const Relationship* relationship = config->getRelationship(table->getTableName(), fkTableName); if (relationship == 0) { Relationship* aux = new Relationship(table->getTableName(), fkTableName); aux->addKeyPair("ID", table->getTableName() + "_ID"); relationships.insert(std::make_pair(table->getTableName() + "." + fkTableName, aux)); } else { relationships.insert(std::make_pair(table->getTableName() + "." + fkTableName, new Relationship(*relationship))); } } } if (pkColumnCount == 0 || pkColumnCount > pkFoundCount) { Column* column = table->getColumn("ID"); if (column == 0) { throw DASPrimaryKeyNotFoundException((std::string) "No PK found on Type " + type.getURI() + "." + type.getName()); } column->setPK(true); } if (configTableColumnsByPropertyName != 0) { delete configTableColumnsByPropertyName; } tables.insert(std::make_pair(type.getName(), table)); } bool ApplyChanges::isInStack(const DASDataObject& dasDataObject) { for (std::list::const_iterator it = stack.begin() ; stack.end() != it ; it++) { if ((*it)->getDataObject() == dasDataObject.getDataObject()) { return true; } } return false; } const Table& ApplyChanges::getTable(commonj::sdo::DataObjectPtr dataObject) { std::string typeName = dataObject->getType().getName(); std::map::const_iterator it = tables.find(typeName); if (it == tables.end()) { processMetadata(dataObject); } it = tables.find(typeName); return *it->second; } CreatedDataObject& ApplyChanges::processCreatedDataObject(commonj::sdo::DataObjectPtr dataObject) { DASDataObject* dasDB = getDASDataObject(dataObject); //dataObject->printSelf(std::cout); if (dasDB != 0) { return (CreatedDataObject&) *dasDB; } CreatedDataObject* createdDataObject = new CreatedDataObject( getTable(dataObject), dataObject, summary); updateOrderList.push_back(createdDataObject); addDataObject(*createdDataObject); commonj::sdo::PropertyList properties = dataObject->getInstanceProperties(); for (unsigned int i = 0 ; i < properties.size() ; i++) { if (properties[i].getType().isDataObjectType()) { if (properties[i].isMany()) { commonj::sdo::DataObjectList& dataObjectList = dataObject->getList(properties[i]); for (unsigned int j = 0 ; j < dataObjectList.size() ; j++) { DASDataObject& dob = processDataObject(dataObjectList[j]); RelationshipStatement& rs = dob.addFK(getRelationship(*createdDataObject, dob), &createdDataObject->getPrimaryKeys()); dob.addDependency(rs); } } else { commonj::sdo::DataObjectPtr dao = dataObject->getDataObject(properties[i]); DASDataObject& dob = processDataObject(dao); dob.addFK(getRelationship(*createdDataObject, dob), &createdDataObject->getPrimaryKeys()); RelationshipStatement& rs = dob.addFK(getRelationship(*createdDataObject, dob), &createdDataObject->getPrimaryKeys()); dob.addDependency(rs); } } } return *createdDataObject; } const Relationship& ApplyChanges::getRelationship(DASDataObject& parentDataObject, DASDataObject& dataObject) const { std::map::const_iterator relatIt = relationships. find(parentDataObject.getTable().getTableName() + "." + dataObject.getTable().getTableName()); return *relatIt->second; } DeletedDataObject& ApplyChanges::processDeletedDataObject(commonj::sdo::DataObjectPtr dataObject) { DASDataObject* dasDB = getDASDataObject(dataObject); //dataObject->printSelf(std::cout); if (dasDB != 0) { return (DeletedDataObject&) *dasDB; } DeletedDataObject* deletedDataObject = new DeletedDataObject( getTable(dataObject), dataObject, summary); const commonj::sdo::SettingList& setting = summary->getOldValues(dataObject); for (int i = 0 ; i < setting.size() ; i++) { if (setting[i].isSet() && setting[i].getProperty().getType().isDataObjectType()) { commonj::sdo::DataObjectPtr containedDataObject = setting[i].getDataObjectValue(); if (!summary->isDeleted(containedDataObject)) { DASDataObject& modDO = processDataObject(containedDataObject); RelationshipStatement& rs = modDO.addFK(getRelationship(*deletedDataObject, modDO), 0); deletedDataObject->addDependency(rs); } } } addDataObject(*deletedDataObject); updateOrderList.push_back(deletedDataObject); return *deletedDataObject; } DASDataObject* ApplyChanges::getDASDataObject(commonj::sdo::DataObjectPtr dataObject) const { std::map*>::const_iterator it = dasDataObjects.find((std::string) dataObject->getType().getName()); if (it != dasDataObjects.end()) { std::list& list = *it->second; std::list::iterator it2; for (it2 = list.begin() ; it2 != list.end() ; it2++) { if ((*it2)->getDataObject() == dataObject) { return *it2; } } } return 0; } ModifiedDataObject& ApplyChanges::processModifiedDataObject(commonj::sdo::DataObjectPtr dataObject) { DASDataObject* dasDB = getDASDataObject(dataObject); //dataObject->printSelf(std::cout); if (dasDB != 0) { return (ModifiedDataObject&) *dasDB; } ModifiedDataObject* modifiedDataObject = new ModifiedDataObject( getTable(dataObject), dataObject, summary); updateOrderList.push_back(modifiedDataObject); addDataObject(*modifiedDataObject); if (summary->isModified(dataObject)) { std::map*> manyOldValuedProperties; std::map singleOldValuedProperties; commonj::sdo::PropertyList props = dataObject->getInstanceProperties(); const commonj::sdo::SettingList& setting = summary->getOldValues(dataObject); for (int i = 0 ; i < setting.size() ; i++) { const commonj::sdo::Property& prop = setting[i].getProperty(); if (prop.getType().isDataObjectType()) { if (!setting[i].isNull() && setting[i].isSet()) { commonj::sdo::DataObjectPtr oldDO = setting[i].getDataObjectValue(); //oldDO->printSelf(std::cout); //std::cout << std::endl; if (prop.isMany()) { std::map*>::iterator manyIt = manyOldValuedProperties.find(&prop); std::list* list; if (manyIt == manyOldValuedProperties.end()) { list = new std::list(); manyOldValuedProperties.insert(std::make_pair(&prop, list)); } else { list = manyIt->second; } list->push_back(oldDO); } else { singleOldValuedProperties.insert(std::make_pair(&prop, oldDO)); } } } } for (unsigned int i = 0 ; i < props.size() ; i++) { if (props[i].getType().isDataObjectType()) { if (props[i].isMany()) { if (!dataObject->isSet(props[i]) || !dataObject->isNull(props[i])) { commonj::sdo::DataObjectList& doList = dataObject->getList(props[i]); for (unsigned int j = 0 ; j < doList.size() ; j++) { commonj::sdo::DataObjectPtr dob = doList[j]; if (summary->isCreated(dob)) { CreatedDataObject& createdDO = processCreatedDataObject(dob); RelationshipStatement& rs = createdDO.addFK(getRelationship(*modifiedDataObject, createdDO), &modifiedDataObject->getPrimaryKeys()); modifiedDataObject->addDependency(rs); } else { std::map*>::iterator manyIt = manyOldValuedProperties.find(&props[i]); bool existsOldDO = false; if (manyIt != manyOldValuedProperties.end()) { std::list& list = *manyIt->second; for (std::list::iterator listIt = list.begin() ; listIt != list.end() ; listIt++) { if (*listIt == dob) { existsOldDO = true; list.erase(listIt); break; } } } if (!existsOldDO) { ModifiedDataObject& modDO = processModifiedDataObject(dob); RelationshipStatement& rs = modDO.addFK(getRelationship(*modifiedDataObject, modDO), &modifiedDataObject->getPrimaryKeys()); modifiedDataObject->addDependency(rs); } } } } } else { if (!dataObject->isSet(props[i]) || !dataObject->isNull(props[i])) { commonj::sdo::DataObjectPtr dob = dataObject->getDataObject(props[i]); if (summary->isCreated(dob)) { CreatedDataObject& createdDO = processCreatedDataObject(dob); RelationshipStatement& rs = createdDO.addFK(getRelationship(*modifiedDataObject, createdDO), &modifiedDataObject->getPrimaryKeys()); modifiedDataObject->addDependency(rs); } else { std::map::iterator singleIt = singleOldValuedProperties.find(&props[i]); if (singleIt == singleOldValuedProperties.end() || singleIt->second != dob) { ModifiedDataObject& modDO = processModifiedDataObject(dob); RelationshipStatement& rs = modDO.addFK(getRelationship(*modifiedDataObject, modDO), &modifiedDataObject->getPrimaryKeys()); modifiedDataObject->addDependency(rs); } } } } } } for (std::map*>::iterator manyIt = manyOldValuedProperties.begin() ; manyIt != manyOldValuedProperties.end() ; manyIt++) { std::list* list = manyIt->second; for (std::list::const_iterator listIt = list->begin() ; listIt != list->end() ; listIt++) { ModifiedDataObject& modDO = processModifiedDataObject(*listIt); RelationshipStatement& rs = modDO.addFK(getRelationship(*modifiedDataObject, modDO), 0); modDO.addDependency(rs); } delete list; } } return *modifiedDataObject; } void ApplyChanges::addDataObject(DASDataObject& dataObject) { std::list* list; std::string typeName = dataObject.getDataObject()->getType().getName(); std::map*>::iterator it = dasDataObjects.find(typeName); if (it == dasDataObjects.end()) { list = new std::list(); dasDataObjects.insert(std::make_pair(typeName, list)); } else { list = it->second; } list->push_back(&dataObject); } }; }; };