1 martin 1.45 //%LICENSE////////////////////////////////////////////////////////////////
|
2 martin 1.46 //
|
3 martin 1.45 // Licensed to The Open Group (TOG) under one or more contributor license
4 // agreements. Refer to the OpenPegasusNOTICE.txt file distributed with
5 // this work for additional information regarding copyright ownership.
6 // Each contributor licenses this file to you under the OpenPegasus Open
7 // Source License; you may not use this file except in compliance with the
8 // License.
|
9 martin 1.46 //
|
10 martin 1.45 // Permission is hereby granted, free of charge, to any person obtaining a
11 // copy of this software and associated documentation files (the "Software"),
12 // to deal in the Software without restriction, including without limitation
13 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 // and/or sell copies of the Software, and to permit persons to whom the
15 // Software is furnished to do so, subject to the following conditions:
|
16 martin 1.46 //
|
17 martin 1.45 // The above copyright notice and this permission notice shall be included
18 // in all copies or substantial portions of the Software.
|
19 martin 1.46 //
|
20 martin 1.45 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
21 martin 1.46 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22 martin 1.45 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
24 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27 martin 1.46 //
|
28 martin 1.45 //////////////////////////////////////////////////////////////////////////
|
29 mike 1.16 //
30 //%/////////////////////////////////////////////////////////////////////////////
31
32 #include <Pegasus/Common/String.h>
33 #include <Pegasus/Common/HashTable.h>
|
34 kumpf 1.44 #include <Pegasus/Common/CIMNameCast.h>
|
35 mike 1.16 #include "InheritanceTree.h"
36
|
37 schuur 1.25 #if 0
38 #undef PEG_METHOD_ENTER
39 #undef PEG_METHOD_EXIT
40 #define PEG_METHOD_ENTER(x,y) cout<<"--- Enter: "<<y<<endl;
41 #define PEG_METHOD_EXIT()
42 #endif
43
|
44 mike 1.16 PEGASUS_NAMESPACE_BEGIN
45
46 PEGASUS_USING_STD;
47
48 ////////////////////////////////////////////////////////////////////////////////
49 //
|
50 schuur 1.25 // InheritanceTreeRep
51 //
52 ////////////////////////////////////////////////////////////////////////////////
53
|
54 marek 1.26 struct InheritanceTreeNode;
|
55 schuur 1.25
56 struct InheritanceTreeRep
57 {
|
58 mike 1.32 typedef HashTable<
|
59 kumpf 1.42 String, InheritanceTreeNode*, EqualNoCaseFunc, HashLowerCaseFunc> Table;
|
60 schuur 1.25 Table table;
|
61 mike 1.32
62 // Tradeoff: chosing a larger value decreases hash lookup time but
63 // increases iteration (which seems to be the dominant operations).
64 // This power of two (256) seems to produce the best results.
65
66 InheritanceTreeRep() : table(256)
67 {
68 }
|
69 schuur 1.25 };
70
71 ////////////////////////////////////////////////////////////////////////////////
72 //
|
73 mike 1.16 // InheritanceTreeNode
74 //
75 ////////////////////////////////////////////////////////////////////////////////
76
|
77 schuur 1.25 class NameSpace;
78
79 struct InheritanceTreeExt
80 {
81 InheritanceTreeExt(NameSpace* t, InheritanceTreeNode* itn)
82 : tag(t), node(itn) {}
83 NameSpace* tag;
84 InheritanceTreeNode* node;
85 };
86
87
|
88 mike 1.16 struct InheritanceTreeNode
89 {
|
90 kumpf 1.41 InheritanceTreeNode(const CIMName& className_);
|
91 venkat.puvvada 1.39 ~InheritanceTreeNode();
|
92 mike 1.16
93 void addSubClass(InheritanceTreeNode* subClass);
94
95 Boolean removeSubClass(InheritanceTreeNode* subClass);
96
97 void getSubClassNames(
|
98 kumpf 1.37 Array<CIMName>& subClassNames,
99 Boolean deepInheritance,
100 NameSpace* tag = 0);
|
101 mike 1.16
|
102 kumpf 1.22 void getSuperClassNames(Array<CIMName>& superClassNames);
|
103 mike 1.16
104 void print(PEGASUS_STD(ostream)& os) const;
|
105 schuur 1.25 #if 0
|
106 kumpf 1.22 Boolean isSubClass(const CIMName& className) const;
|
107 schuur 1.25 #endif
|
108 kumpf 1.22 CIMName className;
|
109 mike 1.16 InheritanceTreeNode* superClass;
110 InheritanceTreeNode* sibling;
|
111 schuur 1.25 union {
|
112 mike 1.16 InheritanceTreeNode* subClasses;
|
113 schuur 1.25 Array<InheritanceTreeExt*>* extNodes;
114 };
|
115 mike 1.16 Boolean provisional;
|
116 schuur 1.25 Boolean extension;
|
117 mike 1.16 };
118
|
119 kumpf 1.41 InheritanceTreeNode::InheritanceTreeNode(const CIMName& className_)
120 : className(className_), superClass(0),
|
121 schuur 1.25 sibling(0), subClasses(0), provisional(true), extension(false)
|
122 mike 1.16 {
123 }
124
|
125 venkat.puvvada 1.39 InheritanceTreeNode::~InheritanceTreeNode()
126 {
127 if (extension)
128 {
129 for(Uint32 i = 0, size = extNodes->size(); i < size; i++)
130 {
131 delete (*extNodes)[i];
132 }
133 delete extNodes;
134 }
135 }
136
|
137 mike 1.16 void InheritanceTreeNode::addSubClass(InheritanceTreeNode* subClass)
138 {
139 subClass->superClass = this;
140 subClass->sibling = subClasses;
141 subClasses = subClass;
142 }
143
144 Boolean InheritanceTreeNode::removeSubClass(InheritanceTreeNode* subClass)
145 {
146 InheritanceTreeNode* prev = 0;
147
148 for (InheritanceTreeNode* p = subClasses; p; p = p->sibling)
149 {
|
150 kumpf 1.37 if (p == subClass)
151 {
152 if (prev)
153 prev->sibling = subClass->sibling;
154 else
155 subClasses = subClass->sibling;
156
157 return true;
158 }
159 prev = p;
|
160 mike 1.16 }
161
162 return false;
163 }
164
165 void InheritanceTreeNode::getSubClassNames(
|
166 schuur 1.25 Array<CIMName>& subClassNames,
167 Boolean deepInheritance,
|
168 kumpf 1.37 NameSpace* ns)
|
169 mike 1.16 {
170 // For each subClass:
171
|
172 kumpf 1.37 for (InheritanceTreeNode* p = subClasses; p; p = p->sibling)
173 {
174 if (p->extension)
175 {
176 for (int j = 0, m = p->extNodes->size(); j < m; j++)
177 {
178 InheritanceTreeExt* itx = (*(p->extNodes))[j];
179 subClassNames.append(p->className);
180 if (!ns)
181 {
182 InheritanceTreeNode* itn=itx->node;
183 itn->getSubClassNames(subClassNames, deepInheritance, ns);
184 }
185 else if (itx->tag == ns)
186 {
187 InheritanceTreeNode* itn=itx->node;
188 itn->getSubClassNames(subClassNames, deepInheritance, ns);
189 break;
190 }
191 }
192 }
193 kumpf 1.37 else
194 {
195 subClassNames.append(p->className);
196 if (deepInheritance)
197 {
198 p->getSubClassNames(subClassNames, true, ns);
199 }
200 }
|
201 mike 1.16 }
202 }
203
|
204 schuur 1.25 #if 0
|
205 kumpf 1.22 Boolean InheritanceTreeNode::isSubClass(const CIMName& className_) const
|
206 mike 1.16 {
|
207 kumpf 1.22 if (className.equal (className_))
|
208 kumpf 1.37 return true;
|
209 mike 1.16
210 for (InheritanceTreeNode* p = subClasses; p; p = p->sibling)
211 {
|
212 kumpf 1.37 if (p->className.equal (className_))
213 return true;
|
214 mike 1.16 }
215
216 return false;
217 }
|
218 schuur 1.25 #endif
|
219 mike 1.16
|
220 kumpf 1.22 void InheritanceTreeNode::getSuperClassNames(Array<CIMName>& superClassNames)
|
221 mike 1.16 {
222 // For each superClass:
223
224 for (InheritanceTreeNode* p = superClass; p; p = p->superClass)
225 {
|
226 kumpf 1.37 superClassNames.append(p->className);
227 // p->getSuperClassNames(superClassNames);
|
228 mike 1.16 }
229 }
230
231 void InheritanceTreeNode::print(PEGASUS_STD(ostream)& os) const
232 {
|
233 kumpf 1.40 os << className.getString() << " : " ;
234 os << (superClass ? superClass->className : CIMName()).getString();
|
235 mike 1.16
236 os << " { ";
237
238 for (InheritanceTreeNode* p = subClasses; p; p = p->sibling)
|
239 kumpf 1.40 os << p->className.getString() << ' ';
|
240 mike 1.16
241 os << "}" << endl;
242 }
243
244 ////////////////////////////////////////////////////////////////////////////////
245 //
246 // InheritanceTree
247 //
248 ////////////////////////////////////////////////////////////////////////////////
249
250 InheritanceTree::InheritanceTree()
251 {
252 _rep = new InheritanceTreeRep;
253 }
254
255 InheritanceTree::~InheritanceTree()
256 {
|
257 sage 1.18 for (InheritanceTreeRep::Table::Iterator i = _rep->table.start(); i; i++)
258 delete i.value();
259
|
260 mike 1.16 delete _rep;
261 }
|
262 schuur 1.25 void InheritanceTree::insert(
263 const String& className,
264 const String& superClassName,
265 InheritanceTree& parentTree,
|
266 kumpf 1.37 NameSpace* tag)
|
267 schuur 1.25 {
268 InheritanceTreeNode* superClassNode = 0;
269
|
270 kumpf 1.37 if (superClassName.size() &&
271 !parentTree._rep->table.lookup(superClassName, superClassNode))
272 {
273 superClassNode =
|
274 mike 1.43 new InheritanceTreeNode(CIMNameCast(superClassName));
|
275 kumpf 1.37 parentTree._rep->table.insert(superClassName, superClassNode);
|
276 schuur 1.25 }
277
278 InheritanceTreeNode* extNode = 0;
279
|
280 kumpf 1.37 if (!parentTree._rep->table.lookup(className, extNode))
281 {
|
282 mike 1.43 extNode = new InheritanceTreeNode(CIMNameCast(className));
|
283 kumpf 1.37 parentTree._rep->table.insert(className, extNode);
284 extNode->extension=true;
285 extNode->extNodes=new Array<InheritanceTreeExt*>;
|
286 schuur 1.25 }
287
288 extNode->provisional = false;
289
290 if (superClassNode)
|
291 kumpf 1.37 superClassNode->addSubClass(extNode);
|
292 schuur 1.25
293 InheritanceTreeNode* classNode = 0;
294
|
295 kumpf 1.37 if (!_rep->table.lookup(className, classNode))
296 {
297 classNode = new InheritanceTreeNode(className);
298 _rep->table.insert(className, classNode);
|
299 schuur 1.25 }
300
301 extNode->extNodes->append(new InheritanceTreeExt(tag,classNode));
302
303 classNode->superClass = superClassNode;
304 }
|
305 mike 1.16
306 void InheritanceTree::insert(
|
307 kumpf 1.37 const String& className,
|
308 mike 1.16 const String& superClassName)
309 {
310 // ATTN: need found flag!
311
312 // -- Insert superclass:
313
314 InheritanceTreeNode* superClassNode = 0;
315
|
316 kumpf 1.37 if (superClassName.size() &&
317 !_rep->table.lookup(superClassName, superClassNode))
|
318 mike 1.16 {
|
319 kumpf 1.37 superClassNode =
|
320 mike 1.43 new InheritanceTreeNode(CIMNameCast(superClassName));
|
321 kumpf 1.37 _rep->table.insert(superClassName, superClassNode);
|
322 mike 1.16 }
323
324 // -- Insert class:
|
325 kumpf 1.37
|
326 mike 1.16 InheritanceTreeNode* classNode = 0;
327
328 if (!_rep->table.lookup(className, classNode))
329 {
|
330 mike 1.43 classNode = new InheritanceTreeNode(CIMNameCast(className));
|
331 kumpf 1.37 _rep->table.insert(className, classNode);
|
332 mike 1.16 }
333
334 classNode->provisional = false;
335
336 // -- Link the class and superclass nodes:
337
338 if (superClassNode)
|
339 kumpf 1.37 superClassNode->addSubClass(classNode);
|
340 mike 1.16 }
341
342 void InheritanceTree::check() const
343 {
344 for (InheritanceTreeRep::Table::Iterator i = _rep->table.start(); i; i++)
345 {
|
346 kumpf 1.37 if (i.value()->provisional)
347 throw InvalidInheritanceTree(i.value()->className.getString());
|
348 mike 1.16 }
349 }
350
351 Boolean InheritanceTree::getSubClassNames(
|
352 kumpf 1.22 const CIMName& className,
|
353 mike 1.16 Boolean deepInheritance,
|
354 schuur 1.25 Array<CIMName>& subClassNames,
|
355 kumpf 1.37 NameSpace* ns) const
|
356 mike 1.16 {
|
357 kumpf 1.37 // -- Case 1: className is empty: get all class names (if deepInheritance)
358 // -- or just root class names (if not deepInheritance).
|
359 mike 1.16
|
360 kumpf 1.37 if (className.isNull())
361 {
362 for (InheritanceTreeRep::Table::Iterator i = _rep->table.start();i;i++)
363 {
364 InheritanceTreeNode* itn=i.value();
365 if (itn->extension)
366 {
367 if (!ns)
368 continue;
369 for (int j=0,m=itn->extNodes->size(); j<m; j++)
370 {
371 InheritanceTreeExt* itx=(*(itn->extNodes))[j];
372 if (itx->tag==ns)
373 {
|
374 kumpf 1.41 InheritanceTreeNode* itxn=itx->node;
|
375 kumpf 1.37 if (deepInheritance)
376 {
|
377 mike 1.43 subClassNames.append(CIMNameCast(i.key()));
|
378 kumpf 1.41 itxn->getSubClassNames(
|
379 kumpf 1.37 subClassNames, deepInheritance, ns);
380 }
381 else if (!i.value()->superClass)
|
382 mike 1.43 subClassNames.append(CIMNameCast(i.key()));
|
383 kumpf 1.37 break;
384 }
385 }
386 }
387 else if (deepInheritance)
388 {
389 // Append all classes:
|
390 mike 1.43 subClassNames.append(CIMNameCast(i.key()));
|
391 kumpf 1.37 }
392 else if (!i.value()->superClass)
393 {
394 // Just append root classes:
|
395 mike 1.43 subClassNames.append(CIMNameCast(i.key()));
|
396 kumpf 1.37 }
397 }
398 return true;
399 }
|
400 schuur 1.25
|
401 kumpf 1.37 // -- Case 2: className non-empty: get names of classes descendent from
402 // -- the given class.
|
403 schuur 1.25
|
404 kumpf 1.37 for (InheritanceTreeRep::Table::Iterator i = _rep->table.start(); i; i++)
405 {
|
406 mike 1.43 if (className.equal (CIMNameCast(i.key())))
|
407 kumpf 1.37 {
408 i.value()->getSubClassNames(subClassNames, deepInheritance, ns);
409 return true;
410 }
411 }
|
412 schuur 1.25
|
413 kumpf 1.37 // Not found!
414 return false;
|
415 mike 1.16 }
|
416 kumpf 1.37
|
417 schuur 1.25 #if 0
|
418 mike 1.17 Boolean InheritanceTree::isSubClass(
|
419 kumpf 1.37 const CIMName& class1,
|
420 kumpf 1.22 const CIMName& class2) const
|
421 mike 1.16 {
|
422 kumpf 1.37 InheritanceTreeNode* node = 0;
|
423 mike 1.16
|
424 kumpf 1.22 if (!_rep->table.lookup(class1.getString(), node))
|
425 kumpf 1.37 return false;
|
426 mike 1.16
|
427 kumpf 1.22 return node->isSubClass(class2.getString());
|
428 mike 1.16 }
|
429 schuur 1.25 #endif
|
430 mike 1.16
431 Boolean InheritanceTree::getSuperClassNames(
|
432 kumpf 1.22 const CIMName& className,
433 Array<CIMName>& superClassNames) const
|
434 mike 1.16 {
435 InheritanceTreeNode* classNode;
436
|
437 kumpf 1.22 if (_rep->table.lookup(className.getString(), classNode))
|
438 mike 1.16 {
|
439 kumpf 1.37 classNode->getSuperClassNames(superClassNames);
440 return true;
|
441 mike 1.16 }
442
443 return false;
444 }
445
446 Boolean InheritanceTree::getSuperClass(
|
447 kumpf 1.22 const CIMName& className,
448 CIMName& superClassName) const
|
449 mike 1.16 {
450 InheritanceTreeNode* classNode;
451
|
452 kumpf 1.22 if (_rep->table.lookup(className.getString(), classNode))
|
453 mike 1.16 {
|
454 kumpf 1.37 if (classNode->superClass)
455 {
456 superClassName = classNode->superClass->className;
457 }
458 else
459 {
460 superClassName.clear();
461 }
|
462 mike 1.16
|
463 kumpf 1.37 return true;
|
464 mike 1.16 }
465
466 return false;
467 }
468
469 Boolean InheritanceTree::hasSubClasses(
|
470 kumpf 1.22 const CIMName& className,
|
471 mike 1.16 Boolean& hasSubClasses) const
472 {
|
473 kumpf 1.37 InheritanceTreeNode* node = 0;
|
474 mike 1.16
|
475 kumpf 1.22 if (!_rep->table.lookup(className.getString(), node))
|
476 kumpf 1.37 return false;
|
477 mike 1.16
478 hasSubClasses = node->subClasses != 0;
479 return true;
480 }
481
|
482 kumpf 1.22 Boolean InheritanceTree::containsClass(const CIMName& className) const
|
483 mike 1.16 {
|
484 kumpf 1.22 return _rep->table.contains(className.getString());
|
485 mike 1.16 }
486
|
487 kumpf 1.37 void InheritanceTree::remove(
488 const CIMName& className,
489 InheritanceTree& parentTree,
490 NameSpace* tag)
|
491 mike 1.16 {
492 // -- Lookup the node:
493
|
494 kumpf 1.37 InheritanceTreeNode* node = 0;
|
495 mike 1.16
|
496 kumpf 1.22 if (!_rep->table.lookup(className.getString(), node))
|
497 kumpf 1.37 throw PEGASUS_CIM_EXCEPTION(
498 CIM_ERR_INVALID_CLASS, className.getString());
|
499 mike 1.16
500 // -- Disallow if is has any subclasses:
501
502 if (node->subClasses)
|
503 kumpf 1.37 throw PEGASUS_CIM_EXCEPTION(
504 CIM_ERR_CLASS_HAS_CHILDREN, className.getString());
|
505 mike 1.16
506 // -- Remove as child of superclass:
507
508 InheritanceTreeNode* superClass = node->superClass;
509
|
510 kumpf 1.37 if (tag)
511 {
512 InheritanceTreeNode* itn = 0;
513 if (parentTree._rep->table.lookup(className.getString(), itn))
514 {
515 if (itn->extension)
516 {
517 for (int j = 0, m = itn->extNodes->size(); j < m; j++)
518 {
519 if ((*(itn->extNodes))[j]->tag == tag)
520 {
521 itn->extNodes->remove(j);
522 break;
523 }
524 }
525 if (itn->extNodes->size() == 0)
526 {
527 delete itn->extNodes;
528 parentTree._rep->table.remove(className.getString());
|
529 schuur 1.25 }
|
530 kumpf 1.37 }
531 }
532 else
533 {
534 Boolean result = superClass->removeSubClass(node);
535 PEGASUS_ASSERT(result);
536 }
|
537 schuur 1.25 }
538 else if (superClass)
|
539 mike 1.16 {
|
540 kumpf 1.37 Boolean result = superClass->removeSubClass(node);
541 PEGASUS_ASSERT(result);
|
542 mike 1.16 }
543
|
544 schuur 1.25
|
545 mike 1.16 // -- Remove from the hash table and delete:
546
|
547 kumpf 1.22 Boolean result = _rep->table.remove(className.getString());
|
548 mike 1.16 PEGASUS_ASSERT(result);
549 delete node;
550 }
551
552 void InheritanceTree::print(PEGASUS_STD(ostream)& os) const
553 {
554 for (InheritanceTreeRep::Table::Iterator i = _rep->table.start(); i; i++)
|
555 kumpf 1.37 i.value()->print(os);
|
556 mike 1.16 }
557
558 PEGASUS_NAMESPACE_END
|