DEVELOPING APPLICATIONS WITH EDMinterface


 
This chapter introduces readers to the principles of application development using the EDMinterface.
The list of EDMinterface functions found in this chapter is not complete, nor is it intended to be so. For a complete list of all functions, readers should refer to the following documents:

  • "EDMinterface : SDAI C binding reference"
  • "EDMinterface : EDMI C binding reference".

 
Setting up for Application Development
All the necessarily files for application development are available in the form of the EDMsdk toolkit and they are:
On the WINDOWS platform:

  • <EDM home directory>\Include\sdai.h

The EDMI header file.

  • <EDM home directory>\bin\edmikit400.lib

  <EDM home directory>\bin\edmikit400.dll
  The EDMinterface library.

  • <EDM home directory>\Include\cpp_edmi.h

The EDMinterface/C++ header file.
 

  •  <EDM home directory>\bin\cpp_edmi.lib

<EDM home directory>\bin\cpp_edmi.dll
 The EDMinterface/C++ library.
 

On UNIX platforms:

  • <EDM home directory>/sdai.h

The EDMI header file.

  • <EDM home directory>/edmi.a

  The EDMinterface static library.

 

ANSI C conformance option should be used when compiling C. Also add <EDM_home_directory> to the preprocessor #include file search path. The LD_LIBRARY_PATH (LIBPATH) and CLASSPATH will then be defined each time you log in.
 
Manipulating EDM databases.
As indicated previously in this chapter, a newly created EDMdatabase contains two distinct repositories, namely a dictionary repository and a data repository. The two repositories can be manipulated by the same set of EDMinterface functions.
Database operations
The following functions handle EDM databases.

  • edmiCreateDatabase.
  • edmiOpenDatabase.
  • edmiCloseDatabase.
  • edmiDeleteDatabase.

 
Repository operations
The following functions initializes and closes a repository:

  • sdaiOpenRepository.
  • sdaiOpenRepositoryBN.
  • sdaiCloseRepository.

 
There are two classes of open repository functions. One class which performs a call by repository identifier, and another one with a BN suffix, which performs a call by name.
The EDMinterface also provides additional functions to manipulate repositories. These functions are prefixed with edmi.

  • edmiCreateRepository
  • edmiDeleteRepository
  • edmiDeleteRepositoryBN
  • edmiGetRepository
  • edmiGetRepositoryOpenMode
  • edmiGetRepositoryOpenModeBN
  • edmiOpenRepository
  • edmiOpenRepositoryBN

 
Model operations
The principal functions to initialize and close models are:

  • sdaiCreateModel.
  • sdaiCreateModelBN.
  • sdaiOpenModel.
  • sdaiOpenModelBN.
  • sdaiCloseModel.
  • sdaiDeleteModel.

There are two classes of functions. One class which performs calls by identifier, and another one, with a BN suffix, which performs calls by name.
The EDMinterface also provides additional functions to manipulate models. These functions are prefixed with edmi.

  • edmiConvertModelBN
  • edmiConvertModelsBN
  • edmiCopyModel
  • edmiCopyModelBN
  • edmiCreateModel
  • edmiCreateModelBN
  • edmiDeleteModel.
  • edmiDeleteModelBN.
  • edmiDeleteModelContents.
  • edmiGetModel
  • edmiGetModelBN
  • edmiGetModelOpenMode
  • edmiGetModelOpenModeBN
  • edmiGetModelRepository

 
Instance operations
The principal functions to create and delete instances are:

  • sdaiCreateInstance.
  • sdaiCreateInstanceBN.
  • sdaiDeleteInstance.

There are two classes of functions. One class which performs call by identifier, and another one, with a BN suffix, which performs call by name.
In addition to the principal functions, metadata for instances can be obtained by means of these EDMinterface functions:

  • sdaiGetInstanceType.
  • sdaiIsInstanceOf.
  • sdaiIsInstanceOfBN.
  • sdaiIsKindOf.
  • sdaiIsKindOfBN.

 
Aggregate operations
The principal functions to create aggregates are:

  • sdaiCreateAggr.
  • sdaiCreateAggrBN.

The functions accept an argument representing an attribute either by identifier or by name.
The functions to populate an aggregate are:

  • sdaiPutAggrByIndex.
  • sdaiPutAggrByIterator.
  • sdaiInsertAfter.
  • sdaiInsertBefore.
  • sdaiAdd
  • sdaiAppend.
  • sdaiPrepend.

 
The functions to retrieve an element from an aggregate are:

  • sdaiGetAggrByIndex.
  • edmiGetAggrElement

 
The following functions provide iterated operations:

  • sdaiCreateIterator.
  • sdaiGetAggrByIterator.
  • sdaiPrevious.
  • sdaiNext.

 
The following function gets the number of elements in an aggregate:

  • sdaiGetMemberCount.

 
The functions to unset elements of an ARRAY are:

  • sdaiUnsetAggrByIndex.
  • sdaiUnsetAggrByIterator.

 
The EDMinterface provides additional functions specific to EDM, to obtain aggregate type information. These functions are:

  • edmiGetAggrType.

 
The EDMinterface also implements the Express aggregate operators as specified in ISO 10303-11:1994 chapter 12.6.

  • edmiAggrDifference
  • edmiAggrIntersection
  • edmiAggrUnion
  • edmiIsAggrSubset
  • edmiIsAggrSuperset

 
Attribute operations
The functions to set attribute values are:

  • sdaiPutAttr.
  • sdaiPutAttrs
  • sdaiPutAttrBN.
  • sdaiPutAttrsBN.

 
There are two classes such of functions. On class which set a single attribute whereas the other one sets one or more attributes in a single call.
The functions to unset an attribute are:

  • sdaiUnsetAttr.
  • sdaiUnsetAttrBN.

 
The EDMinterface provides additional functions specific to EDM, to obtain attribute type information. These functions are:

  • edmiGetAttrPrimitiveType.
  • edmiGetAttrPrimitiveTypeBN.

 
The EDM macro functions.
The EDMinterface also provides a set of functions with high level functionality. These functions are referred to as the EDMI macro functions.
  EDMexpressCompiler |edmiDefine….Schema functions|

 

EDMp21Handler .

edmiReadStepFile, edmiWriteStepFile

EDMmodelConverter .edmiConvertModel… functions
EDMmodelChecker .edmiValidate… functions
 
 

The two applications found below are clearly quite simplified ones. Nevertheless, they demonstrate the basic principles, which are just as applicable to a complex application.
 
Example One: Hello world
 
/---------------------------------------------------------------/
/* */
/* C-LateBinding hello example: */
/* - Creates and opens a database. */
/* - Compiles an EXPRESS schema. */
/* - Creates a data model. */
/* - Populates an instance. */
/* - Retrieves an attribute value. */
/* */
/* --------------------------------------------------------------*/
 
#include <stdio.h>
#include "sdai.h"
 
#define DBLOC "db"
#define EXP_FILE "hello.exp"
#define DBNAME "db"
#define DBPASSW "db"
#define MYSCHEMA "hello_schema"
#define MYMODEL "HELLO"
#define DIA_FILE "comp.dia"
#define STEP_FILE "hello.stp"
 
void main()
{
long rstat,nwarnings,nerrors;
SdaiRepository data_repository;
SdaiSession sessionId;
SdaiModel mymodel;
SdaiInstance hello_instance;
SdaiString hello_world;
char c;
/------------------------------------------/
/* CREATE DATABASE AND OPEN SESSION */
/* -----------------------------------------*/
rstat = edmiDeleteDatabase(DBLOC,DBNAME,DBPASSW);
rstat = sdaiErrorQuery();
rstat = edmiCreateDatabase(DBLOC,DBNAME,DBPASSW);
rstat = edmiOpenDatabase(DBLOC,DBNAME,DBPASSW);
sessionId = sdaiOpenSession();
if(rstat = sdaiErrorQuery()) goto err;
/------------------------------------------/
/* COMPILE THE SCHEMA */
/* -----------------------------------------*/
if(rstat = edmiDefineSchema(EXP_FILE, DIA_FILE, NULL, 0,   &nwarnings, &nerrors)) goto err;
if(nerrors){
printf("\nErrors when compiling %s",EXP_FILE);
goto end;
}
/-----------------------------------------------------/
/* OPEN THE DATA REPOSITORY,CREATE A MODEL AND OPEN IT */
/* ----------------------------------------------------*/
data_repository = sdaiOpenRepositoryBN("DataRepository");
mymodel = sdaiCreateModelBN(data_repository,MYMODEL,MYSCHEMA);
mymodel = sdaiOpenModelBN(data_repository,MYMODEL,sdaiRW);
if(rstat = sdaiErrorQuery()) goto err;
/-----------------------------------------------------/
/* POPULATE INSTANCE */
/* ----------------------------------------------------*/
hello_instance = sdaiCreateInstanceBN(mymodel,"HELLO");
sdaiPutAttrBN(hello_instance,"HELLO",sdaiSTRING,"Hello world!");
if(rstat = sdaiErrorQuery()) goto err;
/-----------------------------------------------------/
/* RETRIEVE ATTRIBUTE VALUE */
/* ----------------------------------------------------*/
sdaiGetAttrBN(hello_instance,"HELLO",sdaiSTRING,&hello_world);
if(rstat = sdaiErrorQuery()) goto err;
printf("\n%s\n",hello_world);
goto end;
err:
/-------/
/* ERROR */
/* ------*/
printf("\nERROR: rstat= %d: %s",rstat,edmiGetErrorText(rstat));
end:
/-----------------/
/* CLOSE DATABASE */
/* ----------------*/
edmiCloseDatabase("");
if(rstat){
printf("\nError\n");
} else {
printf("\nNo error\n");
}
#ifdef _WINDOWS
c = getchar();
#endif
}
 
 
Example two: The Flinstone family:
 
/------------------------------------------------------------/
/* */
/* C-LateBinding example. */
/* This small application demonstrates the most basic edmi */
/* functionality as it: */
/* - Creates and opens a database. */
/* - Compiles an EXPRESS schema. */
/* - Creates a data model. */
/* - Populates instances. */
/* - Relates instances. */
/* - Populates aggregates */
/* - Looks up instances. */
/* - Retrieves attribute values. */
/* - Performes aggregate iteration. */
/* - Exports a STEP file. */
/* */
/* The CHECK_ERR macro checks the edmi error code. */
/* For the purpose of readabilty the usage of macro has */
/* been restricted. */
/* In a real application one should perhaps condsider more */
/* frequent usage in order to achieve robust code. */
/* */
/* -----------------------------------------------------------*/
 
#include <stdio.h>
#include "sdai.h"
 
#define DBLOC "db"
#define EXP_FILE "family.exp"
#define DBNAME "db"
#define DBPASSW "db"
#define MYSCHEMA "family_schema"
#define MYMODEL "FAMILY"
#define DIA_FILE "comp.dia"
#define STEP_FILE "family.stp"
 
#define CHECK_ERR(file,line) \
casefile = file; \
caseline = line; \
if (rstat = sdaiErrorQuery()) goto err;
 
void main()
{
long rstat,nwarnings,nerrors;
SdaiRepository data_repository;
SdaiSession sessionId;
SdaiErrorCode sdaiError;
SdaiModel mymodel;
SdaiInstance the_flintstones;
SdaiInstance fred_flintstone;
SdaiInstance wilma_flintstone;
SdaiInstance pebbles_flintstone;
SdaiInstance rocky_flintstone;
SdaiInstance ff,wife,child,mother,family;
SdaiAggr pets,children,the_pets;
SdaiString given_name,surname,pet_name,family_name,adress;
SdaiInteger index,hits,number_of_children,number_of_pets;
SdaiIterator iter;
char c;
char* casefile;
int caseline;
/------------------------------------------/
/* CREATE DATABASE AND OPEN SESSION */
/* -----------------------------------------*/
rstat = edmiDeleteDatabase(DBLOC,DBNAME,DBPASSW);
rstat = sdaiErrorQuery();
rstat = edmiCreateDatabase(DBLOC,DBNAME,DBPASSW);
rstat = edmiOpenDatabase(DBLOC,DBNAME,DBPASSW);
sessionId = sdaiOpenSession();
CHECK_ERR(_FILE,LINE_);
/------------------------------------------/
/* COMPILE THE SCHEMA */
/* -----------------------------------------*/
rstat = edmiDefineSchema(EXP_FILE,DIA_FILE,NULL,0 ,&nwarnings,&nerrors);
CHECK_ERR(_FILE,LINE_);
if(nerrors){
printf("\nErrors when compiling %s",EXP_FILE);
goto end;
}
/-----------------------------------------------------/
/* OPEN THE DATA REPOSITORY,CREATE A MODEL AND OPEN IT */
/* ----------------------------------------------------*/
data_repository = sdaiOpenRepositoryBN("DataRepository");
mymodel = sdaiCreateModelBN(data_repository,MYMODEL,MYSCHEMA);
mymodel = sdaiOpenModelBN(data_repository,MYMODEL,sdaiRW);
CHECK_ERR(_FILE,LINE_);
/-----------------------------------------------------/
/* POPULATE A FAMILY INSTANCE */
/* ----------------------------------------------------*/
the_flintstones = sdaiCreateInstanceBN(mymodel,"FAMILY");
sdaiPutAttrBN(the_flintstones,"NAME",sdaiSTRING,"Flintstones");
sdaiPutAttrBN(the_flintstones,"ADRESS",sdaiSTRING,"Bedrock");
CHECK_ERR(_FILE,LINE_);
/-----------------------------------------------------/
/* POPULATE Fred Flintstone */
/* ----------------------------------------------------*/
fred_flintstone = sdaiCreateInstanceBN(mymodel,"MAN");
sdaiPutAttrBN(fred_flintstone,"GIVEN_NAME",sdaiSTRING,"Fred");
sdaiPutAttrBN(fred_flintstone,"SURNAME",sdaiSTRING,"Flintstone");
sdaiPutAttrBN(fred_flintstone,"FAMILY",sdaiINSTANCE,the_flintstones);
CHECK_ERR(_FILE,LINE_);
/-----------------------------------------------------/
/* POPULATE Wilma Flintstone */
/* ----------------------------------------------------*/
wilma_flintstone = sdaiCreateInstanceBN(mymodel,"WOMAN");
sdaiPutAttrBN(wilma_flintstone,"GIVEN_NAME",sdaiSTRING,"Wilma");
sdaiPutAttrBN(wilma_flintstone,"SURNAME",sdaiSTRING,"Flintstone");
sdaiPutAttrBN(wilma_flintstone,"FAMILY",sdaiINSTANCE,the_flintstones);
CHECK_ERR(_FILE,LINE_);
/-----------------------------------------------------/
/* MARRIAGE */
/* ----------------------------------------------------*/
sdaiPutAttrBN(fred_flintstone,"WIFE",sdaiINSTANCE,wilma_flintstone);
CHECK_ERR(_FILE,LINE_);
/-----------------------------------------------------/
/* POPULATE Pebbles Flintstone (daughter) */
/* ----------------------------------------------------*/
pebbles_flintstone = sdaiCreateInstanceBN(mymodel,"WOMAN");
sdaiPutAttrBN(pebbles_flintstone,"GIVEN_NAME",sdaiSTRING,"Pebbles");
sdaiPutAttrBN(pebbles_flintstone,"SURNAME",sdaiSTRING,"Flintstone");
sdaiPutAttrBN(pebbles_flintstone,"FATHER",sdaiINSTANCE,fred_flintstone);
sdaiPutAttrBN(pebbles_flintstone,"MOTHER",sdaiINSTANCE,wilma_flintstone);
sdaiPutAttrBN(pebbles_flintstone,"FAMILY",sdaiINSTANCE,the_flintstones);
CHECK_ERR(_FILE,LINE_);
/-----------------------------------------------------/
/* POPULATE Rocky Flintstone (son) */
/* ----------------------------------------------------*/
rocky_flintstone = sdaiCreateInstanceBN(mymodel,"MAN");
sdaiPutAttrBN(rocky_flintstone,"GIVEN_NAME",sdaiSTRING,"Rocky");
sdaiPutAttrBN(rocky_flintstone,"SURNAME",sdaiSTRING,"Flintstone");
sdaiPutAttrBN(rocky_flintstone,"FATHER",sdaiINSTANCE,fred_flintstone);
sdaiPutAttrBN(rocky_flintstone,"MOTHER",sdaiINSTANCE,wilma_flintstone);
sdaiPutAttrBN(rocky_flintstone,"FAMILY",sdaiINSTANCE,the_flintstones);
CHECK_ERR(_FILE,LINE_);
/-----------------------------------------------------/
/* POPULATE THE FLINTSTONE PETS */
/* ----------------------------------------------------*/
pets = sdaiCreateAggrBN(the_flintstones,"PETS");
sdaiAdd(pets,sdaiSTRING,"Dino");
sdaiAdd(pets,sdaiSTRING,"Hoppy");
sdaiAdd(pets,sdaiSTRING,"Gazoo");
CHECK_ERR(_FILE,LINE_);
/-----------------------------------------------------/
/* EXPORT MODEL TO STEP FILE */
/* ----------------------------------------------------*/
rstat = edmiWriteStepFile("DataRepository",NULL,MYMODEL,STEP_FILE,
NULL,NULL,EDM_IDENTIFIERS,8,
&nwarnings,&nerrors,&sdaiError);
if(rstat){
if(rstat != edmiESTEPWRITE){
CHECK_ERR(_FILE,LINE_);
} else {
printf("\n%d errors, %d warnings during export to:
%s",nerrors,nwarnings,STEP_FILE);
rstat = 0;
}
}
/-----------------------------------------------------/
/* LOOKUP Fred Flinstone */
/* ----------------------------------------------------*/
index = 0;
hits = 1;
rstat = edmiSelectInstancesBN(mymodel,"MAN","(GIVEN_NAME = 'Fred') AND
(SURNAME = 'Flintstone')",
0,sizeof(SdaiInstance),&index,&hits,&ff);
CHECK_ERR(_FILE,LINE_);
if(hits != 1){
printf("\nLookup failed. Should never happen!");
rstat = 1;
goto end;
}
sdaiGetAttrBN(ff,"FAMILY",sdaiINSTANCE,&family);
sdaiGetAttrBN(family,"NAME",sdaiSTRING,&family_name);
sdaiGetAttrBN(family,"ADRESS",sdaiSTRING,&adress);
CHECK_ERR(_FILE,LINE_);
printf("\nThe %s family lives in %s.",family_name,adress);
if(family_name) edmiFree(family_name);
if(adress) edmiFree(adress);
/-----------------------------------------------------/
/* GET FREDs WIFE AND THEIR COMMON CHILDREN */
/* ----------------------------------------------------*/
sdaiGetAttrBN(ff,"WIFE",sdaiINSTANCE,&wife);
sdaiGetAttrBN(wife,"GIVEN_NAME",sdaiSTRING,&given_name);
sdaiGetAttrBN(wife,"SURNAME",sdaiSTRING,&surname);
CHECK_ERR(_FILE,LINE_);
printf("\nFred Flinstone is married to %s %s.",given_name,surname);
if(given_name) edmiFree(given_name);
if(surname) edmiFree(surname);
printf("\nThey have the children: ");
sdaiGetAttrBN(ff,"CHILDREN",sdaiAGGR,&children);
number_of_children = sdaiGetMemberCount(children);
for(index = 0; index < number_of_children; ++index){
/* Using index to get element */
edmiGetAggrElement(children,index,sdaiINSTANCE,&child);
sdaiGetAttrBN(child,"MOTHER",sdaiINSTANCE,&mother);
if(mother == wife){
sdaiGetAttrBN(child,"GIVEN_NAME",sdaiSTRING,&given_name);
sdaiGetAttrBN(child,"SURNAME",sdaiSTRING,&surname);
printf("%s %s",given_name,surname);
if(index < (number_of_children-1)) printf(" and "); else printf(".");
if(given_name) edmiFree(given_name);
if(surname) edmiFree(surname);
}
}
CHECK_ERR(_FILE,LINE_);
/-----------------------------------------------------/
/* GET THE FLINTSTONE PETS */
/* ----------------------------------------------------*/
printf("\nThe Flintstones have the pets: ");
sdaiGetAttrBN(family,"PETS",sdaiAGGR,&the_pets);
number_of_pets = sdaiGetMemberCount(the_pets);
index = 0;
iter = sdaiCreateIterator(the_pets);
while(sdaiNext(iter)){
++index;
/* Using iterator to get element */
sdaiGetAggrByIterator(iter,sdaiSTRING,&pet_name);
printf("%s",pet_name);
if(index < (number_of_pets)) printf(" and "); else printf(".");
if(pet_name) edmiFree(pet_name);
}
sdaiDeleteIterator(iter);
CHECK_ERR(_FILE,LINE_);
goto end;
err:
/-------/
/* ERROR */
/* ------*/
printf("\nError at: %s,%d\nrstat= %d:
%s",casefile,caseline,rstat,edmiGetErrorText(rstat));
end:
/-----------------/
/* CLOSE DATABASE */
/* ----------------*/
edmiCloseDatabase("");
if(rstat){
printf("\nOOPS!\n");
} else {
printf("\nYabba-Dabba-Doo!\n");
}
#ifdef _WINDOWS
c = getchar();
#endif
}