X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FModelHighAPI%2FModelHighAPI_Dumper.cpp;h=28961598fd5ecfc827f2fb82c77e7624d4616aca;hb=08772a0d243521482396981ddd3737067f30e349;hp=e1ed55d36942c39d43366d8edbed5f73861d87cc;hpb=287d69a9faf9368f8fc352d50ab408892222c69e;p=modules%2Fshaper.git diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp index e1ed55d36..28961598f 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.cpp @@ -18,7 +18,11 @@ #include #include #include +#include +#include +#include #include +#include #include #include #include @@ -31,10 +35,11 @@ #include -#include #include -//#define DUMP_USER_DEFINED_NAMES +#define DUMP_USER_DEFINED_NAMES + +static int gCompositeStackDepth = 0; ModelHighAPI_Dumper* ModelHighAPI_Dumper::mySelf = 0; @@ -54,13 +59,35 @@ ModelHighAPI_Dumper* ModelHighAPI_Dumper::getInstance() return mySelf; } -void ModelHighAPI_Dumper::clear() +#define CLEAR_STREAM(theStream) { \ + std::ostringstream anOther; \ + swap(theStream, anOther); \ + } + +void ModelHighAPI_Dumper::clear(bool bufferOnly) { - myDumpBuffer = std::ostringstream(); + CLEAR_STREAM(myDumpBuffer); myDumpBuffer << std::setprecision(16); + + clearNotDumped(); + + if (!bufferOnly) { + CLEAR_STREAM(myFullDump); + myFullDump << std::setprecision(16); + + myNames.clear(); + myModules.clear(); + myFeatureCount.clear(); + myLastEntityWithName = EntityPtr(); + } } -const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity) +void ModelHighAPI_Dumper::clearNotDumped() +{ + myNotDumpedEntities.clear(); +} + +const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity, bool theSaveNotDumped) { EntityNameMap::const_iterator aFound = myNames.find(theEntity); if (aFound != myNames.end()) @@ -68,23 +95,34 @@ const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity) // entity is not found, store it std::string aName; - bool isNameDefined = false; + bool isUserDefined = false; FeaturePtr aFeature = std::dynamic_pointer_cast(theEntity); if (aFeature) { + isUserDefined = true; aName = aFeature->name(); - isNameDefined = !aName.empty(); - - if (!isNameDefined) { - static long anIndex = 0; - // set default name: feature ID + index - std::ostringstream aConverter; - aConverter << aFeature->getKind() << "_" << ++anIndex; - aName = aConverter.str(); - std::transform(aName.begin(), aName.end(), aName.begin(), ::tolower); + const std::string& aKind = aFeature->getKind(); + DocumentPtr aDoc = aFeature->document(); + int& aNbFeatures = myFeatureCount[aDoc][aKind]; + + size_t anIndex = aName.find(aKind); + if (anIndex == 0 && aName[aKind.length()] == '_') { // name starts with "FeatureKind_" + std::string anIdStr = aName.substr(aKind.length() + 1, std::string::npos); + int anId = std::stoi(anIdStr); + + // Check number of already registered objects of such kind. Index of current object + // should be the same to identify feature's name as automatically generated. + if (aNbFeatures + 1 == anId) { + isUserDefined = false; + //aNbFeatures = anId - 1; + } } + + aNbFeatures += 1; } - myNames[theEntity] = std::pair(aName, isNameDefined); + myNames[theEntity] = std::pair(aName, isUserDefined); + if (theSaveNotDumped) + myNotDumpedEntities.insert(theEntity); return myNames[theEntity].first; } @@ -118,51 +156,87 @@ bool ModelHighAPI_Dumper::process(const std::shared_ptr& theD bool ModelHighAPI_Dumper::process(const std::shared_ptr& theDoc) { bool isOk = true; - CompositeFeaturePtr aLastComposite; - // dump all features std::list aFeatures = theDoc->allFeatures(); std::list::const_iterator aFeatIt = aFeatures.begin(); - for (; aFeatIt != aFeatures.end(); ++aFeatIt) { - // dump feature if and only if it is not a sub-feature of last composite feature - // (all subs of composite are dumped in special method) - if (!aLastComposite || !aLastComposite->isSub(*aFeatIt)) - dumpFeature(*aFeatIt); - - // iteratively process composite features + // firstly, dump all parameters + for (; aFeatIt != aFeatures.end(); ++ aFeatIt) + dumpParameter(*aFeatIt); + // dump all other features + for (aFeatIt = aFeatures.begin(); aFeatIt != aFeatures.end(); ++aFeatIt) { CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast(*aFeatIt); - if (!aCompFeat) - continue; - - // sub-part is processed independently, because it provides separate document - if ((*aFeatIt)->getKind() == PartSetPlugin_Part::ID()) { - ResultPartPtr aPartResult = - std::dynamic_pointer_cast((*aFeatIt)->lastResult()); - if (!aPartResult) - continue; - DocumentPtr aSubDoc = aPartResult->partDoc(); - // set name of document equal to part name - myNames[aSubDoc] = myNames[*aFeatIt]; - - isOk = process(aSubDoc) && isOk; - } else { + if (aCompFeat) // iteratively process composite features isOk = process(aCompFeat) && isOk; - aLastComposite = aCompFeat; - } + else if (!isDumped(*aFeatIt)) // dump common feature + dumpFeature(*aFeatIt); } return isOk; } -bool ModelHighAPI_Dumper::process(const std::shared_ptr& theComposite) +bool ModelHighAPI_Dumper::process(const std::shared_ptr& theComposite, bool isForce) { + // increase composite features stack + ++gCompositeStackDepth; + // dump composite itself + if (!isDumped(theComposite) || isForce) + dumpFeature(theComposite, isForce); + + // sub-part is processed independently, because it provides separate document + if (theComposite->getKind() == PartSetPlugin_Part::ID()) { + // decrease composite features stack because we run into separate document + --gCompositeStackDepth; + + ResultPartPtr aPartResult = + std::dynamic_pointer_cast(theComposite->lastResult()); + if (!aPartResult) + return false; + DocumentPtr aSubDoc = aPartResult->partDoc(); + // set name of document + const std::string& aPartName = myNames[theComposite].first; + std::string aDocName = aPartName + "_doc"; + myNames[aSubDoc] = std::pair(aDocName, false); + + // dump document in a separate line + *this << aDocName << " = " << aPartName << ".document()" << std::endl; + // dump features in the document + return process(aSubDoc); + } + + // dump sub-features + bool isOk = processSubs(theComposite); + // decrease composite features stack + --gCompositeStackDepth; + + return isOk; +} + +bool ModelHighAPI_Dumper::processSubs(const std::shared_ptr& theComposite, + bool theDumpModelDo) +{ + bool isOk = true; // dump all sub-features; int aNbSubs = theComposite->numberOfSubs(); +////////////////////////////////////// + std::list aList = theComposite->reflist("Features")->list(); +////////////////////////////////////// for (int anIndex = 0; anIndex < aNbSubs; ++anIndex) { FeaturePtr aFeature = theComposite->subFeature(anIndex); - dumpFeature(aFeature, true); + if (isDumped(aFeature)) + continue; + + CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast(aFeature); + if (aCompFeat) // iteratively process composite features + isOk = process(aCompFeat) && isOk; + else + dumpFeature(aFeature, true); } - // dump command to update model - myDumpBuffer << "model.do()" << std::endl; - return true; + + // It is necessary for the sketch to create its result when complete (command "model.do()"). + // This option is set by flat theDumpModelDo. + // However, nested sketches are rebuilt by parent feature, so, they do not need + // explicit call of "model.do()". This will be controlled by the depth of the stack. + if (theDumpModelDo && gCompositeStackDepth <= 1) + *this << "model.do()" << std::endl; + return isOk; } bool ModelHighAPI_Dumper::exportTo(const std::string& theFileName) @@ -195,7 +269,7 @@ bool ModelHighAPI_Dumper::exportTo(const std::string& theFileName) aFile << "model.begin()" << std::endl; // dump collected data - aFile << myDumpBuffer.str(); + aFile << myFullDump.str(); // standard footer aFile << "model.end()" << std::endl; @@ -225,9 +299,16 @@ void ModelHighAPI_Dumper::dumpEntitySetName() myDumpBuffer << ".feature()"; myDumpBuffer << ".data().setName(\"" << aName << "\")" << std::endl; #endif + myNames[myLastEntityWithName].second = false; // don't dump "setName" for the entity twice myLastEntityWithName = EntityPtr(); } +bool ModelHighAPI_Dumper::isDumped(const EntityPtr& theEntity) const +{ + EntityNameMap::const_iterator aFound = myNames.find(theEntity); + return aFound != myNames.end(); +} + ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char theChar) { myDumpBuffer << theChar; @@ -246,6 +327,12 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::string& theStrin return *this; } +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const bool theValue) +{ + myDumpBuffer << (theValue ? "True" : "False"); + return *this; +} + ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const int theValue) { myDumpBuffer << theValue; @@ -350,24 +437,125 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( return *this; } -ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const EntityPtr& theEntity) +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity) { myDumpBuffer << name(theEntity); if (myNames[theEntity].second) myLastEntityWithName = theEntity; + myNotDumpedEntities.erase(theEntity); + return *this; +} + +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ResultPtr& theResult) +{ + FeaturePtr aFeature = ModelAPI_Feature::feature(theResult); + int anIndex = 0; + std::list aResults = aFeature->results(); + for(std::list::const_iterator anIt = aResults.cbegin(); anIt != aResults.cend(); ++anIt, ++anIndex) { + if(theResult->isSame(*anIt)) { + break; + } + } + myDumpBuffer << name(aFeature) << ".result()[" << anIndex << "]"; + return *this; +} + +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ObjectPtr& theObject) +{ + FeaturePtr aFeature = std::dynamic_pointer_cast(theObject); + if(aFeature.get()) { + myDumpBuffer << name(aFeature); + return *this; + } + + ResultPtr aResult = std::dynamic_pointer_cast(theObject); + if(aResult.get()) { + *this << aResult; + return *this; + } + + return *this; +} + +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const AttributePtr& theAttr) +{ + FeaturePtr anOwner = ModelAPI_Feature::feature(theAttr->owner()); + myDumpBuffer << name(anOwner) << "." << attributeGetter(anOwner, theAttr->id()) << "()"; return *this; } ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( const std::shared_ptr& theRefAttr) { - if (theRefAttr->isObject()) { - FeaturePtr aFeature = ModelAPI_Feature::feature(theRefAttr->object()); - myDumpBuffer << name(aFeature); + if (theRefAttr->isObject()) + *this << theRefAttr->object(); + else + *this << theRefAttr->attr(); + return *this; +} + +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( + const std::shared_ptr& theRefAttrList) +{ + myDumpBuffer << "["; + std::list > aList = theRefAttrList->list(); + bool isAdded = false; + std::list >::const_iterator anIt = aList.begin(); + for (; anIt != aList.end(); ++anIt) { + if (isAdded) + myDumpBuffer << ", "; + else + isAdded = true; + if (anIt->first) + *this << anIt->first; + else if (anIt->second) + * this << anIt->second; + } + myDumpBuffer << "]"; + return *this; +} + +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( + const std::shared_ptr& theReference) +{ + *this << theReference->value(); + return *this; +} + +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( + const std::shared_ptr& theRefList) +{ + static const int aThreshold = 2; + // if number of elements in the list if greater than a threshold, + // dump it in a separate line with specific name + std::string aDumped = myDumpBuffer.str(); + if (aDumped.empty() || theRefList->size() <= aThreshold) { + myDumpBuffer << "["; + std::list aList = theRefList->list(); + bool isAdded = false; + std::list::const_iterator anIt = aList.begin(); + for (; anIt != aList.end(); ++anIt) { + if (isAdded) + myDumpBuffer << ", "; + else + isAdded = true; + + *this << *anIt; + } + myDumpBuffer << "]"; } else { - AttributePtr anAttr = theRefAttr->attr(); - FeaturePtr anOwner = ModelAPI_Feature::feature(anAttr->owner()); - myDumpBuffer << name(anOwner) << "." << attributeGetter(anOwner, anAttr->id()) << "()"; + // clear buffer and store list "as is" + CLEAR_STREAM(myDumpBuffer); + *this << theRefList; + // save buffer and clear it again + std::string aDumpedList = myDumpBuffer.str(); + CLEAR_STREAM(myDumpBuffer); + // obtain name of list + FeaturePtr anOwner = ModelAPI_Feature::feature(theRefList->owner()); + std::string aListName = name(anOwner) + "_objects"; + // store all previous data + myDumpBuffer << aListName << " = " << aDumpedList << std::endl + << aDumped << aListName; } return *this; } @@ -375,18 +563,57 @@ ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( const std::shared_ptr& theAttrSelect) { + myDumpBuffer << "model.selection("; + + if(!theAttrSelect->isInitialized()) { + myDumpBuffer << ")"; + return *this; + } + GeomShapePtr aShape = theAttrSelect->value(); if(!aShape.get()) { aShape = theAttrSelect->context()->shape(); } if(!aShape.get()) { + myDumpBuffer << ")"; return *this; } - std::string aShapeTypeStr = aShape->shapeTypeStr(); + myDumpBuffer << "\"" << aShape->shapeTypeStr() << "\", \"" << theAttrSelect->namingName() << "\")"; + return *this; +} + +ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<( + const std::shared_ptr& theAttrSelList) +{ + myDumpBuffer << "["; + + GeomShapePtr aShape; + std::string aShapeTypeStr; + + bool isAdded = false; + + for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) { + AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex); + aShape = anAttribute->value(); + if(!aShape.get()) { + aShape = anAttribute->context()->shape(); + } - myDumpBuffer << "model.selection(\"" << aShapeTypeStr << "\", \"" << theAttrSelect->namingName() << "\")"; + if(!aShape.get()) { + continue; + } + + if(isAdded) { + myDumpBuffer << ", "; + } else { + isAdded = true; + } + myDumpBuffer << "model.selection(\"" << aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")"; + } + + myDumpBuffer << "]"; return *this; } @@ -397,5 +624,30 @@ ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper, { theDumper.myDumpBuffer << theEndl; theDumper.dumpEntitySetName(); + + // store all not-dumped entities first + std::set aNotDumped = theDumper.myNotDumpedEntities; + std::string aBufCopy = theDumper.myDumpBuffer.str(); + theDumper.clear(true); + std::set::const_iterator anIt = aNotDumped.begin(); + for (; anIt != aNotDumped.end(); ++anIt) { + // if the feature is composite, dump it with all subs + CompositeFeaturePtr aCompFeat = + std::dynamic_pointer_cast(*anIt); + if (aCompFeat) + theDumper.process(aCompFeat, true); + else { + FeaturePtr aFeature = std::dynamic_pointer_cast(*anIt); + theDumper.dumpFeature(aFeature, true); + } + } + + // avoid multiple empty lines + size_t anInd = std::string::npos; + while ((anInd = aBufCopy.find("\n\n\n")) != std::string::npos) + aBufCopy.erase(anInd, 1); + // then store currently dumped string + theDumper.myFullDump << aBufCopy; + return theDumper; }