1 // Copyright (C) 2016-20xx CEA/DEN, EDF R&D -->
3 // File: ModelHighAPI_Dumper.cpp
4 // Created: 1 August 2016
5 // Author: Artem ZHIDKOV
7 //--------------------------------------------------------------------------------------
8 #include "ModelHighAPI_Dumper.h"
10 #include <GeomAPI_Pnt.h>
11 #include <GeomAPI_Dir.h>
13 #include <GeomDataAPI_Dir.h>
14 #include <GeomDataAPI_Point.h>
15 #include <GeomDataAPI_Point2D.h>
17 #include <ModelAPI_AttributeBoolean.h>
18 #include <ModelAPI_AttributeDouble.h>
19 #include <ModelAPI_AttributeIntArray.h>
20 #include <ModelAPI_AttributeInteger.h>
21 #include <ModelAPI_AttributeRefAttr.h>
22 #include <ModelAPI_AttributeRefAttrList.h>
23 #include <ModelAPI_AttributeReference.h>
24 #include <ModelAPI_AttributeRefList.h>
25 #include <ModelAPI_AttributeSelection.h>
26 #include <ModelAPI_AttributeSelectionList.h>
27 #include <ModelAPI_AttributeString.h>
28 #include <ModelAPI_CompositeFeature.h>
29 #include <ModelAPI_Document.h>
30 #include <ModelAPI_Entity.h>
31 #include <ModelAPI_Feature.h>
32 #include <ModelAPI_Result.h>
33 #include <ModelAPI_ResultPart.h>
35 #include <PartSetPlugin_Part.h>
37 #include <OSD_OpenFile.hxx>
41 static int gCompositeStackDepth = 0;
43 ModelHighAPI_Dumper* ModelHighAPI_Dumper::mySelf = 0;
45 ModelHighAPI_Dumper::ModelHighAPI_Dumper()
50 void ModelHighAPI_Dumper::setInstance(ModelHighAPI_Dumper* theDumper)
56 ModelHighAPI_Dumper* ModelHighAPI_Dumper::getInstance()
61 void ModelHighAPI_Dumper::clear(bool bufferOnly)
64 myDumpBuffer << std::setprecision(16);
70 myFullDump << std::setprecision(16);
74 myFeatureCount.clear();
75 while (!myEntitiesStack.empty())
76 myEntitiesStack.pop();
80 void ModelHighAPI_Dumper::clearNotDumped()
82 myNotDumpedEntities.clear();
85 const std::string& ModelHighAPI_Dumper::name(const EntityPtr& theEntity,
86 bool theSaveNotDumped,
87 bool theUseEntityName)
89 EntityNameMap::const_iterator aFound = myNames.find(theEntity);
90 if (aFound != myNames.end())
91 return aFound->second.myCurrentName;
93 // entity is not found, store it
95 bool isDefaultName = false;
96 std::ostringstream aDefaultName;
97 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theEntity);
99 aName = aFeature->name();
100 const std::string& aKind = aFeature->getKind();
101 DocumentPtr aDoc = aFeature->document();
102 int& aNbFeatures = myFeatureCount[aDoc][aKind];
105 size_t anIndex = aName.find(aKind);
106 if (anIndex == 0 && aName[aKind.length()] == '_') { // name starts with "FeatureKind_"
107 std::string anIdStr = aName.substr(aKind.length() + 1);
108 int anId = std::stoi(anIdStr);
110 // Check number of already registered objects of such kind. Index of current object
111 // should be the same to identify feature's name as automatically generated.
112 if (aNbFeatures == anId) {
113 // name is not user-defined
114 isDefaultName = true;
118 // obtain default name for the feature
119 if (theUseEntityName)
120 aDefaultName << aName;
123 NbFeaturesMap::const_iterator aFIt = myFeatureCount.begin();
124 for (; aFIt != myFeatureCount.end(); ++aFIt) {
125 std::map<std::string, int>::const_iterator aFound = aFIt->second.find(aKind);
126 if (aFound != aFIt->second.end())
127 aFullIndex += aFound->second;
129 aDefaultName << aKind << "_" << aFullIndex;
133 myNames[theEntity] = EntityName(aDefaultName.str(), aName, isDefaultName);
134 if (theSaveNotDumped)
135 myNotDumpedEntities.insert(theEntity);
137 // store names of results
139 saveResultNames(aFeature);
141 return myNames[theEntity].myCurrentName;
144 const std::string& ModelHighAPI_Dumper::parentName(const FeaturePtr& theEntity)
146 const std::set<AttributePtr>& aRefs = theEntity->data()->refsToMe();
147 std::set<AttributePtr>::const_iterator aRefIt = aRefs.begin();
148 for (; aRefIt != aRefs.end(); ++aRefIt) {
149 CompositeFeaturePtr anOwner = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(
150 ModelAPI_Feature::feature((*aRefIt)->owner()));
152 return name(anOwner);
155 static const std::string DUMMY;
159 void ModelHighAPI_Dumper::saveResultNames(const FeaturePtr& theFeature)
161 // Default name of the feature
162 const std::string& aKind = theFeature->getKind();
163 DocumentPtr aDoc = theFeature->document();
164 int aNbFeatures = myFeatureCount[aDoc][aKind];
165 std::ostringstream aNameStream;
166 aNameStream << aKind << "_" << aNbFeatures;
167 std::string aFeatureName = aNameStream.str();
169 // Save only names of results which is not correspond to default feature name
170 const std::list<ResultPtr>& aResults = theFeature->results();
171 std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
172 for (int i = 1; aResIt != aResults.end(); ++aResIt, ++i) {
173 bool isUserDefined = true;
174 std::string aResName = (*aResIt)->data()->name();
175 size_t anIndex = aResName.find(aFeatureName);
177 std::string aSuffix = aResName.substr(aFeatureName.length());
178 if (aSuffix.empty() && i == 1) // first result may not constain index in the name
179 isUserDefined = false;
181 if (aSuffix[0] == '_' && std::stoi(aSuffix.substr(1)) == i)
182 isUserDefined = false;
186 myNames[*aResIt] = EntityName(aResName,
187 (isUserDefined ? aResName : std::string()), !isUserDefined);
191 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theDoc,
192 const std::string& theFileName)
194 // dump top level document feature
195 static const std::string aDocName("partSet");
196 myNames[theDoc] = EntityName(aDocName, std::string(), true);
197 *this << aDocName << " = model.moduleDocument()" << std::endl;
199 // dump subfeatures and store result to file
200 return process(theDoc) && exportTo(theFileName);
203 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_Document>& theDoc)
206 std::list<FeaturePtr> aFeatures = theDoc->allFeatures();
207 std::list<FeaturePtr>::const_iterator aFeatIt = aFeatures.begin();
208 // firstly, dump all parameters
209 for (; aFeatIt != aFeatures.end(); ++ aFeatIt)
210 dumpParameter(*aFeatIt);
211 // dump all other features
212 for (aFeatIt = aFeatures.begin(); aFeatIt != aFeatures.end(); ++aFeatIt) {
213 CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*aFeatIt);
214 if (aCompFeat) // iteratively process composite features
215 isOk = process(aCompFeat) && isOk;
216 else if (!isDumped(*aFeatIt)) // dump common feature
217 dumpFeature(*aFeatIt);
222 bool ModelHighAPI_Dumper::process(const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite, bool isForce)
224 // increase composite features stack
225 ++gCompositeStackDepth;
226 // dump composite itself
227 if (!isDumped(theComposite) || isForce)
228 dumpFeature(FeaturePtr(theComposite), isForce);
230 // sub-part is processed independently, because it provides separate document
231 if (theComposite->getKind() == PartSetPlugin_Part::ID()) {
232 // decrease composite features stack because we run into separate document
233 --gCompositeStackDepth;
235 ResultPartPtr aPartResult =
236 std::dynamic_pointer_cast<ModelAPI_ResultPart>(theComposite->lastResult());
239 DocumentPtr aSubDoc = aPartResult->partDoc();
242 // set name of document
243 const std::string& aPartName = myNames[theComposite].myCurrentName;
244 std::string aDocName = aPartName + "_doc";
245 myNames[aSubDoc] = EntityName(aDocName, std::string(), true);
247 // dump document in a separate line
248 *this << aDocName << " = " << aPartName << ".document()" << std::endl;
249 // dump features in the document
250 return process(aSubDoc);
254 bool isOk = processSubs(theComposite);
255 // decrease composite features stack
256 --gCompositeStackDepth;
261 bool ModelHighAPI_Dumper::processSubs(const std::shared_ptr<ModelAPI_CompositeFeature>& theComposite,
265 // dump all sub-features;
266 bool isSubDumped = false;
267 int aNbSubs = theComposite->numberOfSubs();
268 for (int anIndex = 0; anIndex < aNbSubs; ++anIndex) {
269 FeaturePtr aFeature = theComposite->subFeature(anIndex);
270 if (isDumped(aFeature))
274 CompositeFeaturePtr aCompFeat = std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aFeature);
275 if (aCompFeat) // iteratively process composite features
276 isOk = process(aCompFeat) && isOk;
278 dumpFeature(aFeature, true);
281 bool isDumpSetName = !myEntitiesStack.empty() &&
282 myEntitiesStack.top().myEntity == EntityPtr(theComposite);
283 bool isForceModelDo = isSubDumped && isDumpSetName &&
284 (myEntitiesStack.top().myUserName || !myEntitiesStack.top().myResults.empty());
285 // It is necessary for the sketch to create its result when complete (command "model.do()").
286 // This option is set by flat theDumpModelDo.
287 // However, nested sketches are rebuilt by parent feature, so, they do not need
288 // explicit call of "model.do()". This will be controlled by the depth of the stack.
289 if (isForceModelDo || (theDumpModelDo && gCompositeStackDepth <= 1))
290 *this << "model.do()" << std::endl;
292 // dump "setName" for composite feature
298 void ModelHighAPI_Dumper::dumpSubFeatureNameAndColor(const std::string theSubFeatureGet,
299 const FeaturePtr& theSubFeature)
301 name(theSubFeature, false);
302 myNames[theSubFeature] = EntityName(theSubFeatureGet, theSubFeature->name(), false);
304 // store results if they have user-defined names or colors
305 std::list<ResultPtr> aResultsWithNameOrColor;
306 const std::list<ResultPtr>& aResults = theSubFeature->results();
307 std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
308 for (; aResIt != aResults.end(); ++aResIt) {
309 std::string aResName = (*aResIt)->data()->name();
310 myNames[*aResIt] = EntityName(aResName, aResName, false);
311 aResultsWithNameOrColor.push_back(*aResIt);
314 // store just dumped entity to stack
315 myEntitiesStack.push(LastDumpedEntity(theSubFeature, true, aResultsWithNameOrColor));
320 bool ModelHighAPI_Dumper::exportTo(const std::string& theFileName)
323 OSD_OpenStream(aFile, theFileName.c_str(), std::ofstream::out);
324 if (!aFile.is_open())
328 for (ModulesMap::const_iterator aModIt = myModules.begin();
329 aModIt != myModules.end(); ++aModIt) {
330 aFile << "from " << aModIt->first << " import ";
331 if (aModIt->second.empty() ||
332 aModIt->second.find(std::string()) != aModIt->second.end())
333 aFile << "*"; // import whole module
335 // import specific features
336 std::set<std::string>::const_iterator anObjIt = aModIt->second.begin();
338 for (++anObjIt; anObjIt != aModIt->second.end(); ++anObjIt)
339 aFile << ", " << *anObjIt;
343 if (!myModules.empty())
346 aFile << "import model" << std::endl << std::endl;
347 aFile << "model.begin()" << std::endl;
349 // dump collected data
350 aFile << myFullDump.str();
351 aFile << myDumpBuffer.str();
354 aFile << "model.end()" << std::endl;
362 void ModelHighAPI_Dumper::importModule(const std::string& theModuleName,
363 const std::string& theObject)
365 myModules[theModuleName].insert(theObject);
368 void ModelHighAPI_Dumper::dumpEntitySetName()
370 const LastDumpedEntity& aLastDumped = myEntitiesStack.top();
372 // dump "setName" for the entity
373 if (aLastDumped.myUserName) {
374 EntityName& anEntityNames = myNames[aLastDumped.myEntity];
375 if (!anEntityNames.myIsDefault)
376 myDumpBuffer << anEntityNames.myCurrentName << ".setName(\""
377 << anEntityNames.myUserName << "\")" << std::endl;
378 // don't dump "setName" for the entity twice
379 anEntityNames.myUserName.clear();
380 anEntityNames.myIsDefault = true;
382 // dump "setName" for results
383 std::list<ResultPtr>::const_iterator aResIt = aLastDumped.myResults.begin();
384 std::list<ResultPtr>::const_iterator aResEnd = aLastDumped.myResults.end();
385 for (; aResIt != aResEnd; ++aResIt) {
387 EntityName& anEntityNames = myNames[*aResIt];
388 if (!anEntityNames.myIsDefault) {
390 myDumpBuffer << ".setName(\"" << anEntityNames.myUserName << "\")" << std::endl;
391 // don't dump "setName" for the entity twice
392 anEntityNames.myUserName.clear();
393 anEntityNames.myIsDefault = true;
396 if (!isDefaultColor(*aResIt)) {
397 AttributeIntArrayPtr aColor = (*aResIt)->data()->intArray(ModelAPI_Result::COLOR_ID());
398 if (aColor && aColor->isInitialized()) {
400 myDumpBuffer << ".setColor(" << aColor->value(0) << ", " << aColor->value(1)
401 << ", " << aColor->value(2) << ")" << std::endl;
406 myEntitiesStack.pop();
409 bool ModelHighAPI_Dumper::isDumped(const EntityPtr& theEntity) const
411 EntityNameMap::const_iterator aFound = myNames.find(theEntity);
412 return aFound != myNames.end();
415 bool ModelHighAPI_Dumper::isDefaultColor(const ResultPtr& theResult) const
417 AttributeIntArrayPtr aColor = theResult->data()->intArray(ModelAPI_Result::COLOR_ID());
418 if (!aColor || !aColor->isInitialized())
421 std::string aSection, aName, aDefault;
422 theResult->colorConfigInfo(aSection, aName, aDefault);
424 // dump current color
425 std::ostringstream aColorInfo;
426 aColorInfo << aColor->value(0) << "," << aColor->value(1) << "," << aColor->value(2);
428 return aDefault == aColorInfo.str();
431 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char theChar)
433 myDumpBuffer << theChar;
437 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const char* theString)
439 myDumpBuffer << theString;
443 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::string& theString)
445 myDumpBuffer << theString;
449 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const bool theValue)
451 myDumpBuffer << (theValue ? "True" : "False");
455 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const int theValue)
457 myDumpBuffer << theValue;
461 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const double theValue)
463 myDumpBuffer << theValue;
467 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::shared_ptr<GeomAPI_Pnt>& thePoint)
469 importModule("GeomAPI", "GeomAPI_Pnt");
470 myDumpBuffer << "GeomAPI_Pnt(" << thePoint->x() << ", "
471 << thePoint->y() << ", " << thePoint->z() << ")";
475 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const std::shared_ptr<GeomAPI_Dir>& theDir)
477 importModule("GeomAPI", "GeomAPI_Dir");
478 myDumpBuffer << "GeomAPI_Dir(" << theDir->x() << ", "
479 << theDir->y() << ", " << theDir->z() << ")";
483 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
484 const std::shared_ptr<GeomDataAPI_Dir>& theDir)
486 myDumpBuffer << theDir->x() << ", " << theDir->y() << ", " << theDir->z();
490 static void dumpArray(std::ostringstream& theOutput, int theSize,
491 double* theValues, std::string* theTexts)
493 for (int i = 0; i < theSize; ++i) {
496 if (theTexts[i].empty())
497 theOutput << theValues[i];
499 theOutput << "\"" << theTexts[i] << "\"";
503 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
504 const std::shared_ptr<GeomDataAPI_Point>& thePoint)
506 static const int aSize = 3;
507 double aValues[aSize] = {thePoint->x(), thePoint->y(), thePoint->z()};
508 std::string aTexts[aSize] = {thePoint->textX(), thePoint->textY(), thePoint->textZ()};
509 dumpArray(myDumpBuffer, aSize, aValues, aTexts);
513 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
514 const std::shared_ptr<GeomDataAPI_Point2D>& thePoint)
516 static const int aSize = 2;
517 double aValues[aSize] = {thePoint->x(), thePoint->y()};
518 std::string aTexts[aSize] = {thePoint->textX(), thePoint->textY()};
519 dumpArray(myDumpBuffer, aSize, aValues, aTexts);
523 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
524 const std::shared_ptr<ModelAPI_AttributeBoolean>& theAttrBool)
526 myDumpBuffer << (theAttrBool->value() ? "True" : "False");
530 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
531 const std::shared_ptr<ModelAPI_AttributeInteger>& theAttrInt)
533 std::string aText = theAttrInt->text();
535 myDumpBuffer << theAttrInt->value();
537 myDumpBuffer << "\"" << aText << "\"";
541 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
542 const std::shared_ptr<ModelAPI_AttributeDouble>& theAttrReal)
544 std::string aText = theAttrReal->text();
546 myDumpBuffer << theAttrReal->value();
548 myDumpBuffer << "\"" << aText << "\"";
552 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
553 const std::shared_ptr<ModelAPI_AttributeString>& theAttrStr)
555 myDumpBuffer << "\"" << theAttrStr->value() << "\"";
559 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const FeaturePtr& theEntity)
561 myDumpBuffer << name(theEntity);
563 bool isUserDefinedName = !myNames[theEntity].myIsDefault;
564 // store results if they have user-defined names or colors
565 std::list<ResultPtr> aResultsWithNameOrColor;
566 const std::list<ResultPtr>& aResults = theEntity->results();
567 std::list<ResultPtr>::const_iterator aResIt = aResults.begin();
568 for (; aResIt != aResults.end(); ++aResIt)
569 if (!myNames[*aResIt].myIsDefault || !isDefaultColor(*aResIt))
570 aResultsWithNameOrColor.push_back(*aResIt);
571 // store just dumped entity to stack
572 myEntitiesStack.push(LastDumpedEntity(theEntity, isUserDefinedName, aResultsWithNameOrColor));
574 // remove entity from the list of not dumped items
575 myNotDumpedEntities.erase(theEntity);
579 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ResultPtr& theResult)
581 FeaturePtr aFeature = ModelAPI_Feature::feature(theResult);
583 std::list<ResultPtr> aResults = aFeature->results();
584 for(std::list<ResultPtr>::const_iterator anIt = aResults.cbegin(); anIt != aResults.cend(); ++anIt, ++anIndex) {
585 if(theResult->isSame(*anIt)) {
589 myDumpBuffer << name(aFeature) << ".result()[" << anIndex << "]";
593 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const ObjectPtr& theObject)
595 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
597 myDumpBuffer << name(aFeature);
601 ResultPtr aResult = std::dynamic_pointer_cast<ModelAPI_Result>(theObject);
610 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(const AttributePtr& theAttr)
612 FeaturePtr anOwner = ModelAPI_Feature::feature(theAttr->owner());
614 std::string aWrapperPrefix, aWrapperSuffix;
615 // Check the attribute belongs to copied (in multi-translation or multi-rotation) feature.
616 // In this case we need to cast explicitly feature to appropriate type.
617 AttributeBooleanPtr isCopy = anOwner->boolean("Copy");
618 if (isCopy.get() && isCopy->value()) {
619 aWrapperPrefix = featureWrapper(anOwner) + "(";
620 aWrapperSuffix = ")";
621 importModule("SketchAPI");
624 myDumpBuffer << aWrapperPrefix << name(anOwner) << aWrapperSuffix
625 << "." << attributeGetter(anOwner, theAttr->id()) << "()";
629 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
630 const std::shared_ptr<ModelAPI_AttributeRefAttr>& theRefAttr)
632 if (theRefAttr->isObject())
633 *this << theRefAttr->object();
635 *this << theRefAttr->attr();
639 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
640 const std::shared_ptr<ModelAPI_AttributeRefAttrList>& theRefAttrList)
643 std::list<std::pair<ObjectPtr, AttributePtr> > aList = theRefAttrList->list();
644 bool isAdded = false;
645 std::list<std::pair<ObjectPtr, AttributePtr> >::const_iterator anIt = aList.begin();
646 for (; anIt != aList.end(); ++anIt) {
648 myDumpBuffer << ", ";
652 *this << anIt->first;
653 else if (anIt->second)
654 * this << anIt->second;
660 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
661 const std::shared_ptr<ModelAPI_AttributeReference>& theReference)
663 *this << theReference->value();
667 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
668 const std::shared_ptr<ModelAPI_AttributeRefList>& theRefList)
670 static const int aThreshold = 2;
671 // if number of elements in the list if greater than a threshold,
672 // dump it in a separate line with specific name
673 std::string aDumped = myDumpBuffer.str();
674 if (aDumped.empty() || theRefList->size() <= aThreshold) {
676 std::list<ObjectPtr> aList = theRefList->list();
677 bool isAdded = false;
678 std::list<ObjectPtr>::const_iterator anIt = aList.begin();
679 for (; anIt != aList.end(); ++anIt) {
681 myDumpBuffer << ", ";
689 // clear buffer and store list "as is"
690 myDumpBuffer.str("");
692 // save buffer and clear it again
693 std::string aDumpedList = myDumpBuffer.str();
694 myDumpBuffer.str("");
695 // obtain name of list
696 FeaturePtr anOwner = ModelAPI_Feature::feature(theRefList->owner());
697 std::string aListName = name(anOwner) + "_objects";
698 // store all previous data
699 myDumpBuffer << aListName << " = " << aDumpedList << std::endl
700 << aDumped << aListName;
705 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
706 const std::shared_ptr<ModelAPI_AttributeSelection>& theAttrSelect)
708 myDumpBuffer << "model.selection(";
710 if(!theAttrSelect->isInitialized()) {
715 GeomShapePtr aShape = theAttrSelect->value();
717 aShape = theAttrSelect->context()->shape();
725 myDumpBuffer << "\"" << aShape->shapeTypeStr() << "\", \"" << theAttrSelect->namingName() << "\")";
729 ModelHighAPI_Dumper& ModelHighAPI_Dumper::operator<<(
730 const std::shared_ptr<ModelAPI_AttributeSelectionList>& theAttrSelList)
735 std::string aShapeTypeStr;
737 bool isAdded = false;
739 for(int anIndex = 0; anIndex < theAttrSelList->size(); ++anIndex) {
740 AttributeSelectionPtr anAttribute = theAttrSelList->value(anIndex);
741 aShape = anAttribute->value();
743 aShape = anAttribute->context()->shape();
751 myDumpBuffer << ", ";
755 myDumpBuffer << "model.selection(\"" << aShape->shapeTypeStr() << "\", \"" << anAttribute->namingName() << "\")";
764 ModelHighAPI_Dumper& operator<<(ModelHighAPI_Dumper& theDumper,
765 std::basic_ostream<char>& (*theEndl)(std::basic_ostream<char>&))
767 theDumper.myDumpBuffer << theEndl;
769 if (!theDumper.myEntitiesStack.empty()) {
770 // Name for composite feature is dumped when all sub-entities are dumped
771 // (see method ModelHighAPI_Dumper::processSubs).
772 const ModelHighAPI_Dumper::LastDumpedEntity& aLastDumped = theDumper.myEntitiesStack.top();
773 CompositeFeaturePtr aComposite =
774 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(aLastDumped.myEntity);
776 theDumper.dumpEntitySetName();
779 // store all not-dumped entities first
780 std::set<EntityPtr> aNotDumped = theDumper.myNotDumpedEntities;
781 std::string aBufCopy = theDumper.myDumpBuffer.str();
782 theDumper.clear(true);
783 std::set<EntityPtr>::const_iterator anIt = aNotDumped.begin();
784 for (; anIt != aNotDumped.end(); ++anIt) {
785 // if the feature is composite, dump it with all subs
786 CompositeFeaturePtr aCompFeat =
787 std::dynamic_pointer_cast<ModelAPI_CompositeFeature>(*anIt);
789 theDumper.process(aCompFeat, true);
791 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(*anIt);
792 theDumper.dumpFeature(aFeature, true);
796 // avoid multiple empty lines
797 size_t anInd = std::string::npos;
798 while ((anInd = aBufCopy.find("\n\n\n")) != std::string::npos)
799 aBufCopy.erase(anInd, 1);
800 // then store currently dumped string
801 theDumper.myFullDump << aBufCopy;