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