Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Examples  

examp2.cpp

This example is to show use of the Schema and Concept constructs

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:  $
*/




This is the CoreLinux++ Framework reference manual
Provided by The CoreLinux Consortium