Salome HOME
SketchSolver library refactoring
[modules/shaper.git] / src / SketchSolver / SketchSolver_Constraint.cpp
1 #include <SketchSolver_Constraint.h>
2 #include <SketchSolver_Group.h>
3 #include <SketchSolver_Error.h>
4
5 #include <SketchPlugin_Arc.h>
6 #include <SketchPlugin_Circle.h>
7 #include <SketchPlugin_Line.h>
8 #include <SketchPlugin_Point.h>
9
10 #include <GeomDataAPI_Point.h>
11 #include <GeomDataAPI_Point2D.h>
12 #include <ModelAPI_AttributeDouble.h>
13 #include <ModelAPI_ResultConstruction.h>
14
15
16 SketchSolver_Constraint::SketchSolver_Constraint(
17     ConstraintPtr  theConstraint)
18   : myBaseConstraint(theConstraint),
19     myGroup(0)
20 {
21 }
22
23 SketchSolver_Constraint::~SketchSolver_Constraint()
24 {
25   std::map<AttributePtr, Slvs_hParam>::const_iterator anIt1 = myValueMap.begin();
26   for (; anIt1 != myValueMap.end(); anIt1++)
27     myStorage->removeParameter(anIt1->second);
28   myValueMap.clear();
29
30   std::map<AttributePtr, Slvs_hEntity>::const_iterator anIt2 = myAttributeMap.begin();
31   for (; anIt2 != myAttributeMap.end(); anIt2++)
32     myStorage->removeEntity(anIt2->second);
33   myAttributeMap.clear();
34
35   std::map<FeaturePtr, Slvs_hEntity>::const_iterator anIt3 =  myFeatureMap.begin();
36   for (; anIt3 != myFeatureMap.end(); anIt3++)
37     myStorage->removeEntity(anIt3->second);
38   myFeatureMap.clear();
39
40   std::vector<Slvs_hConstraint>::const_iterator anIt4 = mySlvsConstraints.begin();
41   for (; anIt4 != mySlvsConstraints.end(); anIt4++)
42     myStorage->removeConstraint(*anIt4);
43   mySlvsConstraints.clear();
44 }
45
46 void SketchSolver_Constraint::setStorage(StoragePtr theStorage)
47 {
48   myStorage = theStorage;
49   process();
50 }
51
52 void SketchSolver_Constraint::setGroup(SketchSolver_Group* theGroup)
53 {
54   myGroup = theGroup;
55   process();
56 }
57
58
59 void SketchSolver_Constraint::process()
60 {
61   cleanErrorMsg();
62   if (!myBaseConstraint || !myStorage || myGroup == 0) {
63     /// TODO: Put error message here
64     return;
65   }
66   if (!mySlvsConstraints.empty()) // some data is changed, update constraint
67     update(myBaseConstraint);
68
69   int aConstrType = getType();
70   double aValue = 0.0;
71   std::vector<Slvs_hEntity> anAttributes;
72   getAttributes(aValue, anAttributes);
73   if (!myErrorMsg.empty())
74     return;
75
76   Slvs_hGroup aGroupID = myGroup->getId();
77   Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
78   Slvs_Constraint aConstraint;
79   if (mySlvsConstraints.empty())
80     aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, aGroupID, aConstrType, aWorkplaneID,
81         aValue, anAttributes[0], anAttributes[1], anAttributes[2], anAttributes[3]);
82   else {
83     aConstraint = myStorage->getConstraint(mySlvsConstraints[0]);
84     aConstraint.valA = aValue;
85     static const int aNbAttrs = 6;
86     Slvs_hEntity* aConstrAttrs[aNbAttrs] = {
87         &aConstraint.ptA, &aConstraint.ptB,
88         &aConstraint.entityA, &aConstraint.entityB,
89         &aConstraint.entityC, &aConstraint.entityD};
90     std::vector<Slvs_hEntity>::const_iterator anIter = anAttributes.begin();
91     for (int i = 0; i < aNbAttrs && anIter != anAttributes.end(); i++, anIter++)
92       *(aConstrAttrs[i]) = *anIter;
93   }
94
95   Slvs_hConstraint anID = myStorage->addConstraint(aConstraint);
96   if (mySlvsConstraints.empty())
97     mySlvsConstraints.push_back(anID);
98   else
99     mySlvsConstraints[0] = anID;
100 }
101
102 void SketchSolver_Constraint::update(ConstraintPtr theConstraint)
103 {
104   cleanErrorMsg();
105   if (theConstraint && theConstraint != myBaseConstraint) {
106     if (theConstraint->getKind() != myBaseConstraint->getKind())
107       return;
108     remove(myBaseConstraint);
109     myBaseConstraint = theConstraint;
110     process();
111   }
112
113   int aType;
114   std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIter = myFeatureMap.begin();
115   for (; aFeatIter != myFeatureMap.end(); aFeatIter++)
116     aFeatIter->second = changeEntity(aFeatIter->first, aType);
117   std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
118   for (; anAttrIter != myAttributeMap.end(); anAttrIter++)
119     anAttrIter->second = changeEntity(anAttrIter->first, aType);
120 }
121
122 bool SketchSolver_Constraint::remove(ConstraintPtr theConstraint)
123 {
124   cleanErrorMsg();
125   if (theConstraint && theConstraint != myBaseConstraint)
126     return false;
127   bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints.front());
128   if (isFullyRemoved) {
129     myFeatureMap.clear();
130     myAttributeMap.clear();
131     myValueMap.clear();
132   } else
133     cleanRemovedEntities();
134   return true;
135 }
136
137 void SketchSolver_Constraint::cleanRemovedEntities()
138 {
139   std::set<Slvs_hParam> aRemovedParams;
140   std::set<Slvs_hEntity> aRemovedEntities;
141   std::set<Slvs_hConstraint> aRemovedConstraints;
142   myStorage->getRemoved(aRemovedParams, aRemovedEntities, aRemovedConstraints);
143   std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = myFeatureMap.begin();
144   while (aFeatIt != myFeatureMap.end()) {
145     if (aRemovedEntities.find(aFeatIt->second) == aRemovedEntities.end()) {
146       aFeatIt++;
147       continue;
148     }
149     std::map<FeaturePtr, Slvs_hEntity>::iterator aTmpIter = aFeatIt++;
150     myFeatureMap.erase(aTmpIter);
151   }
152   std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = myAttributeMap.begin();
153   while (anAttrIt != myAttributeMap.end()) {
154     if (aRemovedEntities.find(anAttrIt->second) == aRemovedEntities.end()) {
155       anAttrIt++;
156       continue;
157     }
158     std::map<AttributePtr, Slvs_hEntity>::iterator aTmpIter = anAttrIt++;
159     myAttributeMap.erase(aTmpIter);
160   }
161   std::map<AttributePtr, Slvs_hParam>::iterator aValIt = myValueMap.begin();
162   while (aValIt != myValueMap.end()) {
163     if (aRemovedParams.find(aValIt->second) == aRemovedParams.end()) {
164       aValIt++;
165       continue;
166     }
167     std::map<AttributePtr, Slvs_hParam>::iterator aTmpIter = aValIt++;
168     myValueMap.erase(aTmpIter);
169   }
170 }
171
172 void SketchSolver_Constraint::getAttributes(
173     double& theValue,
174     std::vector<Slvs_hEntity>& theAttributes)
175 {
176   static const int anInitNbOfAttr = 4;
177   theAttributes.assign(anInitNbOfAttr, SLVS_E_UNKNOWN);
178
179   DataPtr aData = myBaseConstraint->data();
180
181   AttributeDoublePtr aValueAttr = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
182     aData->attribute(SketchPlugin_Constraint::VALUE()));
183   theValue = aValueAttr ? aValueAttr->value() : 0.0;
184
185   int aPtInd = 0; // index of first point in the list of attributes
186   int aEntInd = 2; // index of first antity in the list of attributes
187   std::list<AttributePtr> aConstrAttrs = aData->attributes(ModelAPI_AttributeRefAttr::typeId());
188   std::list<AttributePtr>::iterator anIter = aConstrAttrs.begin();
189   for (; anIter != aConstrAttrs.end(); anIter++) {
190     AttributeRefAttrPtr aRefAttr =
191         std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
192     if (!aRefAttr || !aRefAttr->isInitialized()) {
193       myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
194       return;
195     }
196
197     int aType = SLVS_E_UNKNOWN; // type of created entity
198     Slvs_hEntity anEntity = myGroup->getAttributeId(aRefAttr);
199     if (anEntity == SLVS_E_UNKNOWN)
200       anEntity = changeEntity(aRefAttr, aType);
201     else {
202       Slvs_Entity anEnt = myStorage->getEntity(anEntity);
203       aType = anEnt.type;
204     }
205
206     if (aType == SLVS_E_UNKNOWN)
207       continue;
208     else if (aType == SLVS_E_POINT_IN_2D || aType == SLVS_E_POINT_IN_3D)
209       theAttributes[aPtInd++] = anEntity; // the point is created
210     else { // another entity (not a point) is created
211       if (aEntInd < anInitNbOfAttr)
212         theAttributes[aEntInd] = anEntity;
213       else
214         theAttributes.push_back(anEntity);
215       aEntInd++;
216     }
217   }
218 }
219
220 Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributeRefAttrPtr theAttribute, int& theType)
221 {
222   // Convert the object of the attribute to the feature
223   FeaturePtr aFeature;
224   if (theAttribute->isObject() && theAttribute->object()) {
225     ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
226         theAttribute->object());
227     if (!aRC) {
228       myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
229       return SLVS_E_UNKNOWN;
230     }
231     std::shared_ptr<ModelAPI_Document> aDoc = aRC->document();
232     aFeature = aDoc->feature(aRC);
233
234     return changeEntity(aFeature, theType);
235   }
236
237   return changeEntity(theAttribute->attr(), theType);
238 }
239
240 Slvs_hEntity SketchSolver_Constraint::changeEntity(AttributePtr theEntity, int& theType)
241 {
242   Slvs_hEntity aResult = SLVS_E_UNKNOWN;
243   if (!theEntity->isInitialized())
244     return SLVS_E_UNKNOWN;
245
246   // If the entity is already in the group, try to find it
247   std::map<std::shared_ptr<ModelAPI_Attribute>, Slvs_hEntity>::const_iterator anEntIter =
248       myAttributeMap.find(theEntity);
249   Slvs_Entity aCurrentEntity;
250   aCurrentEntity.h = SLVS_E_UNKNOWN;
251   if (anEntIter != myAttributeMap.end())
252     aCurrentEntity = myStorage->getEntity(anEntIter->second);
253   else {
254     aResult = myGroup->getAttributeId(theEntity);
255     if (aResult != SLVS_E_UNKNOWN) {
256       Slvs_Entity anEnt = myStorage->getEntity(aResult);
257       theType = anEnt.type;
258       return aResult;
259     }
260   }
261
262   Slvs_hGroup aGroupID = myGroup->getId();
263   // Point in 3D
264   std::shared_ptr<GeomDataAPI_Point> aPoint =
265       std::dynamic_pointer_cast<GeomDataAPI_Point>(theEntity);
266   if (aPoint) {
267     double aXYZ[3] = {aPoint->x(), aPoint->y(), aPoint->z()};
268     Slvs_hParam aParams[3];
269     for (int i = 0; i < 3; i++) {
270       Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
271           myStorage->getParameter(aCurrentEntity.param[i]) :
272           Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
273       aPar.val = aXYZ[i];
274       aParams[i] = myStorage->addParameter(aPar);
275     }
276
277     if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
278       aCurrentEntity = Slvs_MakePoint3d(SLVS_E_UNKNOWN, aGroupID, aParams[0], aParams[1], aParams[2]);
279     else { // update entity data
280       for (int i = 0; i < 3; i++)
281         aCurrentEntity.param[i] = aParams[i];
282     }
283     aResult = myStorage->addEntity(aCurrentEntity);
284   } else {
285     // All entities except 3D points are created on workplane. So, if there is no workplane yet, then error
286     Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
287     if (aWorkplaneID == SLVS_E_UNKNOWN)
288       return SLVS_E_UNKNOWN;
289
290     // Point in 2D
291     std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
292         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(theEntity);
293     if (aPoint2D) {
294       double aXY[2] = {aPoint2D->x(), aPoint2D->y()};
295       Slvs_hParam aParams[2];
296       for (int i = 0; i < 2; i++) {
297         Slvs_Param aPar = aCurrentEntity.h != SLVS_E_UNKNOWN ?
298             myStorage->getParameter(aCurrentEntity.param[i]) :
299             Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
300         aPar.val = aXY[i];
301         aParams[i] = myStorage->addParameter(aPar);
302       }
303
304       if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
305         aCurrentEntity = Slvs_MakePoint2d(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aParams[0], aParams[1]);
306       else { // update entity data
307         for (int i = 0; i < 2; i++)
308           aCurrentEntity.param[i] = aParams[i];
309       }
310       aResult = myStorage->addEntity(aCurrentEntity);
311     } else {
312       // Scalar value (used for the distance entities)
313       AttributeDoublePtr aScalar = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(theEntity);
314       if (aScalar) {
315         Slvs_Param aParam = aCurrentEntity.h != SLVS_E_UNKNOWN ?
316             myStorage->getParameter(aCurrentEntity.param[0]) :
317             Slvs_MakeParam(SLVS_E_UNKNOWN, aGroupID, 0.0);
318         aParam.val = aScalar->value();
319         Slvs_hParam aValue = myStorage->addParameter(aParam);
320
321         if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
322           aCurrentEntity = Slvs_MakeDistance(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aValue);
323         else
324           aCurrentEntity.param[0] = aValue;
325         aResult = myStorage->addEntity(aCurrentEntity);
326       }
327     }
328   }
329
330   myAttributeMap[theEntity] = aResult;
331   theType = aCurrentEntity.type;
332   return aResult;
333 }
334
335 Slvs_hEntity SketchSolver_Constraint::changeEntity(FeaturePtr theEntity, int& theType)
336 {
337   Slvs_hEntity aResult = SLVS_E_UNKNOWN;
338   if (!theEntity->data()->isValid())
339     return SLVS_E_UNKNOWN;
340   // If the entity is already in the group, try to find it
341   std::map<FeaturePtr, Slvs_hEntity>::const_iterator anEntIter = myFeatureMap.find(theEntity);
342   Slvs_Entity aCurrentEntity;
343   aCurrentEntity.h = SLVS_E_UNKNOWN;
344   if (anEntIter != myFeatureMap.end())
345     aCurrentEntity = myStorage->getEntity(anEntIter->second);
346   else {
347     aResult = myGroup->getFeatureId(theEntity);
348     if (aResult != SLVS_E_UNKNOWN) {
349       Slvs_Entity anEnt = myStorage->getEntity(aResult);
350       theType = anEnt.type;
351       return aResult;
352     }
353   }
354
355   Slvs_hGroup aGroupID = myGroup->getId();
356   Slvs_hEntity aWorkplaneID = myGroup->getWorkplaneId();
357   // SketchPlugin features
358   std::shared_ptr<SketchPlugin_Feature> aFeature = std::dynamic_pointer_cast<
359       SketchPlugin_Feature>(theEntity);
360   if (aFeature) {  // Verify the feature by its kind
361     const std::string& aFeatureKind = aFeature->getKind();
362     AttributePtr anAttribute;
363     int anAttrType;
364
365     // Line
366     if (aFeatureKind.compare(SketchPlugin_Line::ID()) == 0) {
367       anAttribute = aFeature->data()->attribute(SketchPlugin_Line::START_ID());
368       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
369       Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
370
371       anAttribute = aFeature->data()->attribute(SketchPlugin_Line::END_ID());
372       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
373       Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
374
375       if (aCurrentEntity.h == SLVS_E_UNKNOWN) // New entity
376         aCurrentEntity = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID, aStart, aEnd);
377       else {
378         aCurrentEntity.point[0] = aStart;
379         aCurrentEntity.point[1] = aEnd;
380       }
381       aResult = myStorage->addEntity(aCurrentEntity);
382     }
383     // Circle
384     else if (aFeatureKind.compare(SketchPlugin_Circle::ID()) == 0) {
385       anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::CENTER_ID());
386       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
387       Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
388
389       anAttribute = aFeature->data()->attribute(SketchPlugin_Circle::RADIUS_ID());
390       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
391       Slvs_hEntity aRadius = changeEntity(anAttribute, anAttrType);
392
393       if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
394         Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
395         aCurrentEntity = Slvs_MakeCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
396                                          aCenter, aWorkplane.normal, aRadius);
397       } else {
398         aCurrentEntity.point[0] = aCenter;
399         aCurrentEntity.distance = aRadius;
400       }
401       aResult = myStorage->addEntity(aCurrentEntity);
402     }
403     // Arc
404     else if (aFeatureKind.compare(SketchPlugin_Arc::ID()) == 0) {
405       anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::CENTER_ID());
406       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
407       Slvs_hEntity aCenter = changeEntity(anAttribute, anAttrType);
408
409       anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::START_ID());
410       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
411       Slvs_hEntity aStart = changeEntity(anAttribute, anAttrType);
412
413       anAttribute = aFeature->data()->attribute(SketchPlugin_Arc::END_ID());
414       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
415       Slvs_hEntity aEnd = changeEntity(anAttribute, anAttrType);
416
417       if (aCurrentEntity.h == SLVS_E_UNKNOWN) { // New entity
418         Slvs_Entity aWorkplane = myStorage->getEntity(aWorkplaneID);
419         aCurrentEntity = Slvs_MakeArcOfCircle(SLVS_E_UNKNOWN, aGroupID, aWorkplaneID,
420                                               aWorkplane.normal, aCenter, aStart, aEnd);
421       } else {
422         aCurrentEntity.point[0] = aCenter;
423         aCurrentEntity.point[1] = aStart;
424         aCurrentEntity.point[2] = aEnd;
425       }
426       aResult = myStorage->addEntity(aCurrentEntity);
427     }
428     // Point (it has low probability to be an attribute of constraint, so it is checked at the end)
429     else if (aFeatureKind.compare(SketchPlugin_Point::ID()) == 0) {
430       anAttribute = aFeature->data()->attribute(SketchPlugin_Point::COORD_ID());
431       if (!anAttribute->isInitialized()) return SLVS_E_UNKNOWN;
432       // Both the sketch point and its attribute (coordinates) link to the same SolveSpace point identifier
433       aResult = changeEntity(anAttribute, anAttrType);
434       aCurrentEntity.type = SLVS_E_POINT_IN_3D;
435     }
436   }
437
438   myFeatureMap[theEntity] = aResult;
439   theType = aCurrentEntity.type;
440   return aResult;
441 }
442
443 std::list<ConstraintPtr> SketchSolver_Constraint::constraints() const
444 {
445   std::list<ConstraintPtr> aConstraints;
446   aConstraints.push_back(myBaseConstraint);
447   return aConstraints;
448 }
449
450 void SketchSolver_Constraint::refresh()
451 {
452   cleanErrorMsg();
453   std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
454   for (; anAttrIter != myAttributeMap.end(); anAttrIter++) {
455     std::shared_ptr<GeomDataAPI_Point> aPoint =
456         std::dynamic_pointer_cast<GeomDataAPI_Point>(anAttrIter->first);
457     if (aPoint) {
458       Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second);
459       double aXYZ[3];
460       for (int i = 0; i < 3; i++) {
461         Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
462         aXYZ[i] = aPar.val;
463       }
464       aPoint->setValue(aXYZ[0], aXYZ[1], aXYZ[2]);
465     } else {
466       // Point in 2D
467       std::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
468           std::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttrIter->first);
469       if (aPoint2D) {
470         Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second);
471         double aXYZ[2];
472         for (int i = 0; i < 2; i++) {
473           Slvs_Param aPar = myStorage->getParameter(anEntity.param[i]);
474           aXYZ[i] = aPar.val;
475         }
476         aPoint2D->setValue(aXYZ[0], aXYZ[1]);
477       } else {
478         // Scalar value (used for the distance entities)
479         AttributeDoublePtr aScalar =
480             std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
481         if (aScalar) {
482           Slvs_Entity anEntity = myStorage->getEntity(anAttrIter->second);
483           Slvs_Param aPar = myStorage->getParameter(anEntity.param[0]);
484           aScalar->setValue(aPar.val);
485         }
486       }
487     }
488   }
489
490   std::map<AttributePtr, Slvs_hParam>::iterator aValIter = myValueMap.begin();
491   for (; aValIter != myValueMap.end(); aValIter++) {
492     AttributeDoublePtr aScalar =
493         std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(anAttrIter->first);
494     if (aScalar) {
495       Slvs_Param aPar = myStorage->getParameter(anAttrIter->second);
496       aScalar->setValue(aPar.val);
497     }
498   }
499 }
500
501 Slvs_hEntity SketchSolver_Constraint::getId(FeaturePtr theFeature) const
502 {
503   std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFIter = myFeatureMap.find(theFeature);
504   if (aFIter == myFeatureMap.end())
505     return SLVS_E_UNKNOWN;
506   return aFIter->second;
507 }
508
509 Slvs_hEntity SketchSolver_Constraint::getId(AttributePtr theAttribute) const
510 {
511   std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrIter = myAttributeMap.find(theAttribute);
512   if (anAttrIter == myAttributeMap.end())
513     return SLVS_E_UNKNOWN;
514   return anAttrIter->second;
515 }
516