This may be the begining of the schema management stuff, who knows? Maybe that guy over there does...no?...over there?
Anyway, for this example we make a number of assertions: 1. Concept property collections are sets, therefore two keys with the same value will be rejected 2. Keys are constructed from FrameworkStrings
/* CoreLinux++ Copyright (C) 1999,2001 CoreLinux Consortium The CoreLinux++ Library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. The CoreLinux++ Library Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with the GNU C Library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // // ClfwCommon.hpp included before anything else. This is not // required but it makes things consistent. You can also // wrap it with: // // #if !defined(_CLFWCOMMON_HPP) // #include <clfw/ClfwCommon.hpp> // #endif // // if file i/o during compilation should be reduced. // Each CoreLinux header has itself wrapped as well so // multiple includes or cross-includes are performance harmless // #define PERSIST_FRAMEWORK #if !defined(__CLFWCOMMON_HPP) #include <clfw/ClfwCommon.hpp> #endif #if !defined(__COLLECTION_HPP) #include <clfw/Collection.hpp> #endif #if !defined(__ATTRIBUTE_HPP) #include <clfw/Attribute.hpp> #endif #if !defined(__SCHEMA_HPP) #include <clfw/Schema.hpp> #endif #if !defined(__METASPACE_HPP) #include <clfw/MetaSpace.hpp> #endif #if !defined(__ONTOLOGY_HPP) #include <clfw/Ontology.hpp> #endif #if !defined(__FRAMEWORKSTRING_HPP) #include <clfw/FrameworkString.hpp> #endif #if !defined(__STORESPONSOR_HPP) #include INCL_StoreSponsor #endif #if !defined(__STORECATALOG_HPP) #include INCL_StoreCatalog #endif #if !defined(__STORE_HPP) #include INCL_Store #endif using namespace corelinux; // // Data Declarations // // // Main entry prototype // int main( void ); // // Menu management // Int catalogMenuGetCommand( void ); void commandLoop( StoreCatalogPtr ) throw(); Int schemaMenuGetCommand( void ); // // Functions for catalog // void displayCatalog( StoreCatalogPtr ); void createSchema( StoreCatalogPtr ) throw (); void saveOpen( StoreCatalogPtr ) throw (); void closeOpen( StoreCatalogPtr ) throw (); void deleteSchema( StoreCatalogPtr ) throw (); // // Functions for schemas // void editSchema( StoreCatalogPtr ) throw (); void displayConcepts( SchemaPtr ) throw (); void createConcept( SchemaPtr ) throw (); void deleteConcept( SchemaPtr ) throw (); void initializeConcept( ConceptPtr, CharCptr, CharCptr ) throw (); void assignCollection( ConceptPtr, CharCptr ) throw (); // // Helper functions // FrameworkEntityPtr getInstanceOf( CharCptr, CharCptr domain=NULLPTR ); void resolveAndDestroy( FrameworkEntityPtr ); AttributePtr buildStringAttribute( CharCptr, CharCptr ); AttributePtr buildStringAttribute( CharCptr, UniversalIdentifierCref ); AttributePtr buildStringAttribute( CharCptr, FrameworkEntityPtr ); // // Assertion and Exception handlers // void handleAssertion( AssertionCref aAssert ); void handleException( ExceptionCref ); // // Global flags because I'm lazy and don't want to take the // opportunity away for someone to CONTRIBUTE and do a better // job :) // bool DIRTYSCHEMASABOUND( false ); int main( void ) { int results(0); try { // // Housekeeping // MetaSpace::initialize(); // Resolve sponser for Schema gdbm // and get the catalog interface StoreSponsorPtr aSponsor ( StoreSponsor::castDown(getInstanceOf("SchemaSponsor")) ); StoreCatalogPtr aCatalog = aSponsor->getCatalog(); // // Enter command loop // commandLoop( aCatalog ); } catch( AssertionRef aAssert ) { handleAssertion(aAssert); } catch( ExceptionRef aException ) { handleException(aException); } catch( std::exception & e ) { cerr << e.what() << endl; } catch( ... ) { cerr << "Unknown exception." << endl; } return results; } Int catalogMenuGetCommand( void ) { Int results(-1); cout << endl; cout << "Schema management command options" << endl; cout << endl << endl; cout << "\t1 - List Catalog " << endl; cout << "\t2 - Create Schema " << endl; cout << "\t3 - Edit Schema " << endl; cout << "\t4 - Save Schemas " << endl; cout << "\t5 - Close Schemas " << endl; cout << "\t6 - Delete Schema " << endl; cout << "\t9 - Quit " << endl; cout << endl; if( DIRTYSCHEMASABOUND == true ) { cout << "CAUTION: Work has been done that merits a save." << endl << endl; } else { ; // do nothing } cout << "Enter command option : "; cin >> results; cout << endl; return results; } SetCollection liveSchemas; void commandLoop( StoreCatalogPtr aSCPtr ) throw () { Int results(0); while( results != -1 ) { results = catalogMenuGetCommand(); if( results > 9 || results < 0 ) { cout << "Invalid command option, exiting" << endl; results = -1; } else { switch( results ) { case 1: displayCatalog( aSCPtr ); break; case 2: createSchema( aSCPtr ); break; case 3: editSchema( aSCPtr ); break; case 4: saveOpen( aSCPtr ); break; case 5: saveOpen( aSCPtr ); closeOpen( aSCPtr ); break; case 6: deleteSchema( aSCPtr ); break; case 9: results = -1; break; default: break; } } } } Int schemaMenuGetCommand( FrameworkStringPtr aSchema ) { Int results(-1); cout << endl; cout << "Schema edit command options..active schema ["<<aSchema->getValue()<<"]" << endl; cout << endl << endl; cout << "\t1 - List Concepts " << endl; cout << "\t2 - Create Concept " << endl; cout << "\t3 - Delete Concept " << endl; cout << "\t9 - Quit " << endl; cout << endl; cout << "Enter command option : "; cin >> results; cout << endl; return results; } void displayCatalog( StoreCatalogPtr aSCPtr ) { // list existing schemas Iterator<FrameworkEntityPtr> *aItr( aSCPtr->createCatalogIterator() ); cout << endl << "********************" << endl << "Catalog dump display" << endl << "********************" << endl << endl; Counter entCount(0); while( aItr->isValid() ) { FrameworkStringPtr aName( FrameworkString::castDown(aItr->getElement())); cout << "Entry [" << entCount << "] = " << aName->getValue() << endl; aItr->setNext(); ++entCount; } aSCPtr->destroyIterator( aItr ); cout << endl << "********************" << endl ; } // // Create the empty vessel then populate // with concepts // char inputBuffer[256]; void createSchema( StoreCatalog *aCatalog ) throw () { SetCollection args; cout << endl << endl << "Schema creation requires at least two attributes " << endl << "which are fundementally name value pairs. The attributes are: " << endl << "\tName - no spaces, have fun. " << endl << "\tCollection - no spaces..choices are Array and SetCollection. " << endl << "Other Stores may require user id and password as well." << endl << endl; cout << "Input the Name for the schema : "; cin >> inputBuffer; FrameworkStringPtr aName( FrameworkString::create() ); *aName = inputBuffer; cout << "Enter the collection type (Array or SetCollection) : "; cin >> inputBuffer; FrameworkStringPtr aCollection( FrameworkString::create() ); *aCollection = inputBuffer; cout << endl << "Creating " << aName->getValue() << " with collection " << aCollection->getValue() << endl; args.put( buildStringAttribute("Name",aName) ); args.put( buildStringAttribute("Collection",aCollection) ); aCatalog->createEntry(&args); SchemaPtr aSchema(Schema::castDown(aCatalog->getEntry(&args))); // // We need to clean up the arguments // AttributePtr aPtr = Attribute::castDown( args.getElementAt(0) ); resolveAndDestroy( aPtr->getKey() ); resolveAndDestroy( aPtr ); aPtr = Attribute::castDown( args.getElementAt(1) ); resolveAndDestroy( aPtr->getKey() ); resolveAndDestroy( aPtr->getValue() ); aPtr->setKey( aName ); aPtr->setValue( aSchema ); liveSchemas.put( aPtr ); DIRTYSCHEMASABOUND = true; } void saveOpen( StoreCatalogPtr aSCPtr ) throw () { Array args; // // Loop for gather // for( Counter x = 0; x < liveSchemas.getSize(); ++x ) { AttributePtr aAtt( Attribute::castDown( liveSchemas.getElementAt(x) ) ); args.put( aAtt->getValue() ); } // // Save // if( args.getSize() > 0 ) { if( DIRTYSCHEMASABOUND == true ) { aSCPtr->saveEntries( &args ); DIRTYSCHEMASABOUND = false; } else { ; // do nothing } } else { ; // do nothing } } void closeOpen( StoreCatalogPtr aSCPtr ) throw () { Array args; Array indexes; // // Loop for gather // for( Counter x = 0; x < liveSchemas.getSize(); ++x ) { AttributePtr aAtt( Attribute::castDown( liveSchemas.getElementAt(x) ) ); args.put( aAtt->getValue() ); indexes.put( aAtt ); } // // Close and remove from live list // if( args.getSize() > 0 ) { aSCPtr->closeEntries( &args ); for( Counter r = 0; r < args.getSize(); ++r ) { FrameworkEntityPtr aPtr( indexes.getElementAt(r) ); liveSchemas.remove( aPtr ); AttributePtr aAtt( Attribute::castDown(aPtr) ); resolveAndDestroy( aAtt->getKey() ); resolveAndDestroy( aAtt ); } } else { ; // do nothing } } void deleteSchema( StoreCatalogPtr aSCPtr ) throw () { displayCatalog( aSCPtr ); cout << endl << endl << "Schema delete requires at least one attribute " << endl << "which is fundementally a name value pair. The attribute is: " << endl << "\tName - no spaces, select from above list. " << endl << endl; cout << "Input the schema name to be deleted : "; cin >> inputBuffer; FrameworkString aName; aName = inputBuffer; Attribute anAtt; anAtt.setKey( FrameworkStringPtr(&Store::getNameKey()) ); anAtt.setValue( &aName ); Array args; args.put( &anAtt ); aSCPtr->deleteEntry( &args ); anAtt.setKey( anAtt.getValue() ); ElementIndex hit( liveSchemas.indexOf( &anAtt ) ); if( hit >= 0 ) { AttributePtr aAPtr(Attribute::castDown( liveSchemas.getElementAt(hit) ) ); resolveAndDestroy( aAPtr->getKey() ); resolveAndDestroy( aAPtr ); } else { ; // do nothing } } void editSchema( StoreCatalogPtr aSCPtr ) throw () { // // First get the schema to use in editing // displayCatalog( aSCPtr ); cout << endl << endl << "Select a Schema from this list to work with" << endl << endl; cout << "Enter name of schema : "; cin >> inputBuffer; FrameworkString aName; aName = inputBuffer; // Check the liveSchemas first before going to the catalog SchemaPtr aSchema; Attribute anAtt; anAtt.setKey( &aName ); ElementIndex index(-1); if( ( index = liveSchemas.indexOf( &anAtt ) ) != -1 ) { AttributePtr anAP( Attribute::castDown( liveSchemas.getElementAt(index) ) ); aSchema = Schema::castDown( anAP->getValue() ); } else { Array anArray; anAtt.setKey( FrameworkStringPtr(&Store::getNameKey()) ); anAtt.setValue( &aName ); anArray.put( &anAtt ); aSchema = Schema::castDown( aSCPtr->getEntry( &anArray ) ); liveSchemas.put( buildStringAttribute(aName.getValue(),aSchema) ); } // // Then present the options in regards to concepts // if( aSchema != NULLPTR ) { Int results(0); while( results != -1 ) { results = schemaMenuGetCommand(&aName); if( results > 9 || results < 0 ) { cout << "Invalid command option, exiting" << endl; results = -1; } else { switch( results ) { case 1: displayConcepts( aSchema ); break; case 2: createConcept( aSchema ); break; case 3: deleteConcept( aSchema ); break; case 9: results = -1; break; default: break; } } } } } void displayConcepts( SchemaPtr aSchmPtr ) throw () { REQUIRE( aSchmPtr != NULLPTR ); CollectionPtr aCollection( aSchmPtr->getProperties() ); Counter maxCnt( aCollection->getSize() ); AttributePtr anAtt( NULLPTR ); ConceptPtr aConcept( NULLPTR ); FrameworkStringPtr aKey( NULLPTR ); FrameworkStringPtr aClassName( NULLPTR ); cout << endl << "********************" << endl << "Schema dump display" << endl << "********************" << endl << endl; for( Counter x = 0; x < maxCnt; ++x ) { anAtt =( Attribute::castDown( aCollection->getElementAt(x) ) ); aKey = FrameworkString::castDown( anAtt->getKey() ); aConcept = Concept::castDown( anAtt->getValue() ); CHECK( aConcept ); aClassName = Store::resolveValueAssignment ( aConcept->getProperties(), FrameworkStringPtr(&Store::getClassIdKey()) ); CHECK( aClassName ); UniversalIdentifier aCID( aClassName->getValue() ); MetaClassPtr aClass( Ontology::getClassFor( aCID ) ); CHECK( aClass ); cout << "Entry [" << aKey->getValue() << "] is a schema concept for " << aClass->getInstanceTypeName() << "[" << aClassName->getValue() << "]" << endl; } cout << endl << "********************" << endl ; } void createConcept( SchemaPtr aSchmPtr ) throw () { SetCollection args; cout << endl << endl << "Concept creation requires at least three attributes " << endl << "which are fundementally name value pairs. The attributes are: " << endl << "\tName - no spaces" << endl << "\tCollection - no spaces..choices are Array and SetCollection. " << endl << "\tClass - no spaces..the Class that this concept defines for persist. " << endl << "Other Stores may require user id and password as well." << endl << endl; cout << "Enter the Name for the concept : "; cin >> inputBuffer; FrameworkString aName; aName = inputBuffer; cout << "Enter the collection type (Array or SetCollection) : "; cin >> inputBuffer; FrameworkString aCollection; aCollection = inputBuffer; cout << "Enter the Class name for the concept to manager : "; cin >> inputBuffer; FrameworkString aClassName; aClassName = inputBuffer; cout << endl << "Creating " << aName.getValue() << " with collection " << aCollection.getValue() << " to manage " << aClassName.getValue() << endl; ConceptPtr aConcept = Concept::castDown(getInstanceOf("Concept")); initializeConcept( aConcept, aName.getValue(), aCollection.getValue() ); MetaClassPtr aClass( Ontology::getClassFor( aClassName.getValue() ) ); ENSURE( aClass != NULLPTR ); // // Now add what class this concept represents // AttributePtr aClassAtt ( buildStringAttribute ( "Class", aClass->getIdentifier() ) ); aConcept->addAttribute( aClassAtt ); aSchmPtr->addAttribute( buildStringAttribute(aName.getValue(),aConcept) ); DIRTYSCHEMASABOUND = true; } void deleteConcept( SchemaPtr aSchmPtr ) throw () { displayConcepts( aSchmPtr ); cout << endl << endl << "Concept deletion requires the name of the concept " << endl << "to be deleted. " << endl << endl; cout << "Enter the Name for the concept : "; cin >> inputBuffer; FrameworkString aName; aName = inputBuffer; Attribute srchAtt; srchAtt.setKey( &aName ); ElementIndex cIndex(-1); // // Find, and iterate through the concepts properties deleting // as you go // if( ( cIndex = aSchmPtr->getProperties()->indexOf(&srchAtt) ) != -1 ) { AttributePtr aCncAtt ( Attribute::castDown ( aSchmPtr->getProperties()->getElementAt(cIndex) ) ); CHECK( aCncAtt ); ConceptPtr aConcept( Concept::castDown(aCncAtt->getValue()) ); CHECK( aConcept ); aSchmPtr->getProperties()->remove( aCncAtt ); resolveAndDestroy( aCncAtt->getKey() ); CollectionPtr aCol( aConcept->getProperties() ); for( Counter x = 0; x < aCol->getSize() ; ++x ) { AttributePtr aAtt( Attribute::castDown(aCol->getElementAt(x)) ); FrameworkEntityPtr aKey( aAtt->getKey() ); FrameworkEntityPtr aValue( aAtt->getValue() ); if( aValue != NULLPTR ) { resolveAndDestroy( aValue ); } else { cout << FrameworkString::castDown(aKey)->getValue() << " has no value" << endl; } if( aKey != NULLPTR ) { resolveAndDestroy( aKey ); } else { cout << "Key has no value" << endl; } resolveAndDestroy( aAtt ); } resolveAndDestroy( aCol ); resolveAndDestroy( aCncAtt ); DIRTYSCHEMASABOUND = true; } else { cout << inputBuffer << " concept not found " << endl; } } // // Constructs a new concept, gives it a name, and // manages to resolve the collection type // void initializeConcept ( ConceptPtr aConcept, CharCptr aConceptName, CharCptr aCollectionName ) throw () { // // First we assign a collection type to // the concept // assignCollection(aConcept,aCollectionName); // // Give ourselfs a name // aConcept->addAttribute ( buildStringAttribute("Name",aConceptName) ); } void assignCollection ( ConceptPtr aConcept, CharCptr aCollectionName ) throw () { // // Resolve collection type or throw exception // aConcept->setProperties ( Collection::castDown(getInstanceOf(aCollectionName)) ); } // // Routine resolves a class and instantiates a instance // of it using the metaclass dispatch on the well know // construct method // FrameworkEntityPtr getInstanceOf( CharCptr aClassTarget, CharCptr domain ) { FrameworkEntityPtr aPtr( NULLPTR ); MetaClassPtr aClass( Ontology::getClassFor( aClassTarget, domain ) ); aClass->dispatch( "Construct" , (void **)NULLPTR,(void *)&aPtr ); if( aPtr == NULLPTR ) { throw NullPointerException( LOCATION ); } else { ; // do nothing } return aPtr; } void resolveAndDestroy( FrameworkEntityPtr aPtr ) { REQUIRE( aPtr != NULLPTR ); MetaClassPtr aClass ( Ontology::getClassFor( aPtr->getType()->getIdentifier() ) ); CHECK( aClass ); aClass->dispatch(aPtr,"Destruct",NULLPTR,NULLPTR); } AttributePtr buildStringAttribute ( CharCptr aKey, CharCptr aValue ) { AttributePtr aAtr( Attribute::create() ); aAtr->setKey( new FrameworkString(aKey) ); aAtr->setValue( new FrameworkString(aValue) ); return aAtr; } // Stringifies a OID for attribute AttributePtr buildStringAttribute ( CharCptr aKey, UniversalIdentifierCref aValue ) { Char buffer[40]; aValue.getAsString(buffer); return buildStringAttribute(aKey,buffer); } AttributePtr buildStringAttribute( CharCptr aKey, FrameworkEntityPtr aValue ) { AttributePtr aAtr( Attribute::create() ); aAtr->setKey( new FrameworkString(aKey) ); aAtr->setValue( aValue ); return aAtr; } // // Peform default (just show it) // void handleAssertion( AssertionCref aAssert ) { cerr << aAssert.getFile() << ":" << aAssert.getLine() << ":" << "Assertion: "; if( aAssert.getType() == Assertion::NEVERGETHERE ) { cerr << "NEVER_GET_HERE"; } else { if( aAssert.getType() == Assertion::REQUIRE ) { cerr << "REQUIRE"; } else if( aAssert.getType() == Assertion::ENSURE ) { cerr << "ENSURE"; } else if( aAssert.getType() == Assertion::CHECK ) { cerr << "CHECK"; } else { cerr << "ASSERT"; } cerr << "( " << aAssert.getWhy() << " )"; } cerr << endl; } // // Default exception handler // void handleException( ExceptionCref aExcp ) { cerr << aExcp.getFile() << ":" << aExcp.getLine() << ":" << "Exception: " << aExcp.getWhy() << endl; } /* Common rcs information do not modify $Author: frankc $ $Revision: 1.10 $ $Date: 2001/04/26 10:22:35 $ $Locker: $ */