1 /*
2 * NIST STEP Core Class Library
3 * clstepcore/Registry.inline.cc
4 * April 1997
5 * K. C. Morris
6 * David Sauder
7 
8 * Development of this software was funded by the United States Government,
9 * and is not subject to copyright.
10 */
11 
12 #include <ExpDict.h>
13 #include <Registry.h>
14 #include "sc_memmgr.h"
15 
16 const TypeDescriptor  * t_sdaiINTEGER = NULL;
17 const TypeDescriptor  * t_sdaiREAL = NULL;
18 const TypeDescriptor  * t_sdaiNUMBER = NULL;
19 const TypeDescriptor  * t_sdaiSTRING = NULL;
20 const TypeDescriptor  * t_sdaiBINARY = NULL;
21 const TypeDescriptor  * t_sdaiBOOLEAN = NULL;
22 const TypeDescriptor  * t_sdaiLOGICAL = NULL;
23 
24 static int uniqueNames( const char *, const SchRename * );
25 
Registry(CF_init initFunct)26 Registry::Registry( CF_init initFunct )
27     : col( 0 ), entity_cnt( 0 ), all_ents_cnt( 0 ) {
28 
29     primordialSwamp = SC_HASHcreate( 1000 );
30     active_schemas = SC_HASHcreate( 10 );
31     active_types = SC_HASHcreate( 100 );
32 
33     if( !t_sdaiINTEGER ) {
34         t_sdaiINTEGER = new TypeDescriptor( "INTEGER",    // Name
35                                             sdaiINTEGER, // FundamentalType
36                                             0, // Originating Schema
37                                             "INTEGER" );  // Description;
38     }
39     if( !t_sdaiREAL ) {
40         t_sdaiREAL = new TypeDescriptor( "REAL", sdaiREAL,
41                                          0, // Originating Schema
42                                          "Real" );
43     }
44     if( !t_sdaiSTRING ) {
45         t_sdaiSTRING = new TypeDescriptor( "STRING", sdaiSTRING,
46                                            0, // Originating Schema
47                                            "String" );
48     }
49     if( !t_sdaiBINARY ) {
50         t_sdaiBINARY = new TypeDescriptor( "BINARY", sdaiBINARY,
51                                            0, // Originating Schema
52                                            "Binary" );
53     }
54     if( !t_sdaiBOOLEAN ) {
55         t_sdaiBOOLEAN = new TypeDescriptor( "BOOLEAN", sdaiBOOLEAN,
56                                             0, // Originating Schema
57                                             "Boolean" );
58     }
59     if( !t_sdaiLOGICAL ) {
60         t_sdaiLOGICAL = new TypeDescriptor( "LOGICAL", sdaiLOGICAL,
61                                             0, // Originating Schema
62                                             "Logical" );
63     }
64     if( !t_sdaiNUMBER ) {
65         t_sdaiNUMBER = new TypeDescriptor( "NUMBER", sdaiNUMBER,
66                                            0, // Originating Schema
67                                            "Number" );
68     }
69 
70     initFunct( *this );
71     SC_HASHlistinit( active_types, &cur_type );
72     SC_HASHlistinit( primordialSwamp, &cur_entity ); // initialize cur's
73     SC_HASHlistinit( active_schemas, &cur_schema );
74 }
75 
~Registry()76 Registry::~Registry() {
77     DeleteContents();
78 
79     SC_HASHdestroy( primordialSwamp );
80     SC_HASHdestroy( active_schemas );
81     SC_HASHdestroy( active_types );
82     delete col;
83 
84     if( t_sdaiINTEGER ) {
85         delete t_sdaiINTEGER;
86         t_sdaiINTEGER = NULL;
87     }
88     if( t_sdaiREAL ) {
89         delete t_sdaiREAL;
90         t_sdaiREAL = NULL;
91     }
92     if( t_sdaiSTRING ) {
93         delete t_sdaiSTRING;
94         t_sdaiSTRING = NULL;
95     }
96     if( t_sdaiBINARY ) {
97         delete t_sdaiBINARY;
98         t_sdaiBINARY = NULL;
99     }
100     if( t_sdaiBOOLEAN ) {
101         delete t_sdaiBOOLEAN;
102         t_sdaiBOOLEAN = NULL;
103     }
104     if( t_sdaiLOGICAL ) {
105         delete t_sdaiLOGICAL;
106         t_sdaiLOGICAL = NULL;
107     }
108     if( t_sdaiNUMBER ) {
109         delete t_sdaiNUMBER;
110         t_sdaiNUMBER = NULL;
111     }
112 }
113 
DeleteContents()114 void Registry::DeleteContents() {
115     // entities first
116     SC_HASHlistinit( primordialSwamp, &cur_entity );
117     while( SC_HASHlist( &cur_entity ) ) {
118         delete( EntityDescriptor * ) cur_entity.e->data;
119     }
120 
121     // schemas
122     SC_HASHlistinit( active_schemas, &cur_schema );
123     while( SC_HASHlist( &cur_schema ) ) {
124         delete( Schema * ) cur_schema.e->data;
125     }
126 
127     // types
128     SC_HASHlistinit( active_types, &cur_type );
129     while( SC_HASHlist( &cur_type ) ) {
130         delete( TypeDescriptor * ) cur_type.e->data;
131     }
132 }
133 
134 /**
135  * schNm refers to the current schema.  This will have a value if we are
136  * reading from a Part 21 file (using a STEPfile object), and the file
137  * declares a schema name in the File_Schema section of the Header.  (If
138  * >1 schema names are declared, the first is taken.)  The schema name is
139  * significant because of the USE and REFERENCE clause.  Say schema X USEs
140  * entity A from schema Y and renames it to B, X should only refer to A as
141  * B.  Thus, if schNm here = "X", only e="B" would be valid but not e="A".
142  */
FindEntity(const char * e,const char * schNm,int check_case) const143 const EntityDescriptor * Registry::FindEntity( const char * e, const char * schNm, int check_case ) const {
144     const EntityDescriptor * entd;
145     const SchRename * altlist;
146     char schformat[BUFSIZ], altName[BUFSIZ];
147 
148     if( check_case ) {
149         entd = ( EntityDescriptor * )SC_HASHfind( primordialSwamp, ( char * )e );
150     } else {
151         entd = ( EntityDescriptor * )SC_HASHfind( primordialSwamp,
152                 ( char * )PrettyTmpName( e ) );
153     }
154     if( entd && schNm ) {
155         // We've now found an entity.  If schNm has a value, we must ensure we
156         // have a valid name.
157         strcpy( schformat, PrettyTmpName( schNm ) );
158         if( ( ( altlist = entd->AltNameList() ) != 0 )
159                 && ( altlist->rename( schformat, altName ) ) ) {
160             // If entd has other name choices, and entd is referred to with a
161             // new name by schema schNm, then e had better = the new name.
162             if( !StrCmpIns( e, altName ) ) {
163                 return entd;
164             }
165             return NULL;
166         } else if( FindSchema( schformat, 1 ) ) {
167             // If schema schNm exists but we had no conditions above to use an
168             // altName, we must use the original name:
169             if( !StrCmpIns( e, entd->Name() ) ) {
170                 return entd;
171             }
172             return NULL;
173         } else {
174             // Last choice: schNm does not exist at all.  The user must have
175             // typed something wrong.  Don't penalize him for it (so even if
176             // we have an altName of entd, accept it):
177             return entd;
178         }
179     }
180     return entd;
181 }
182 
FindSchema(const char * n,int check_case) const183 const Schema * Registry::FindSchema( const char * n, int check_case ) const {
184     if( check_case ) {
185         return ( const Schema * ) SC_HASHfind( active_schemas, ( char * ) n );
186     }
187 
188     return ( const Schema * ) SC_HASHfind( active_schemas,
189                                            ( char * )PrettyTmpName( n ) );
190 }
191 
FindType(const char * n,int check_case) const192 const TypeDescriptor * Registry::FindType( const char * n, int check_case ) const {
193     if( check_case ) {
194         return ( const TypeDescriptor * ) SC_HASHfind( active_types, ( char * ) n );
195     }
196     return ( const TypeDescriptor * ) SC_HASHfind( active_types,
197             ( char * )PrettyTmpName( n ) );
198 }
199 
ResetTypes()200 void Registry::ResetTypes() {
201     SC_HASHlistinit( active_types, &cur_type );
202 }
203 
NextType()204 const TypeDescriptor * Registry::NextType() {
205     if( 0 == SC_HASHlist( &cur_type ) ) {
206         return 0;
207     }
208     return ( const TypeDescriptor * ) cur_type.e->data;
209 }
210 
AddEntity(const EntityDescriptor & e)211 void Registry::AddEntity( const EntityDescriptor & e ) {
212     SC_HASHinsert( primordialSwamp, ( char * ) e.Name(), ( EntityDescriptor * ) &e );
213     ++entity_cnt;
214     ++all_ents_cnt;
215     AddClones( e );
216 }
217 
218 
AddSchema(const Schema & d)219 void Registry::AddSchema( const Schema & d ) {
220     SC_HASHinsert( active_schemas, ( char * ) d.Name(), ( Schema * ) &d );
221 }
222 
AddType(const TypeDescriptor & d)223 void Registry::AddType( const TypeDescriptor & d ) {
224     SC_HASHinsert( active_types, ( char * ) d.Name(), ( TypeDescriptor * ) &d );
225 }
226 
227 /**
228  * Purpose is to insert e into the registry hashed according to all its
229  * alternate names (the names it was renamed with when other schemas USEd
230  * or REFERENCEd it).  This will make these names available to the Registry
231  * so that if we comes across one of them in a Part 21 file, we'll recog-
232  * nize it.
233  */
AddClones(const EntityDescriptor & e)234 void Registry::AddClones( const EntityDescriptor & e ) {
235     const SchRename * alts = e.AltNameList();
236 
237     while( alts ) {
238         SC_HASHinsert( primordialSwamp, ( char * )alts->objName(),
239                        ( EntityDescriptor * )&e );
240         alts = alts->next;
241     }
242     all_ents_cnt += uniqueNames( e.Name(), e.AltNameList() );
243 }
244 
245 /**
246  * Returns the number of unique names in an entity's _altname list.  If
247  * schema B uses ent xx from schema A and renames it to yy, and schema C
248  * does the same (or if C simply uses yy from B), altlist will contain 2
249  * entries with the same alt name.
250  */
uniqueNames(const char * entnm,const SchRename * altlist)251 static int uniqueNames( const char * entnm, const SchRename * altlist ) {
252     int cnt = 0;
253     const SchRename * alt = altlist;
254 
255     while( alt ) {
256         if( !( ( alt->next && alt->next->choice( alt->objName() ) )
257                 || !StrCmpIns( alt->objName(), entnm ) ) ) {
258             // alt has a unique alternate name if it's not reused by a later
259             // alt.  alt->next->choice() returns 1 if one of the later alts
260             // also has alt's name as its value.  The final condition checks
261             // that our alt name is not the same as the original ent's (would
262             // be the case if the Express file said "USE from A (xx as xx)",
263             // which may not be legal and certainly isn't meaningful, but we
264             // check for it just in case.  If none of the above conditions are
265             // true, we have a unique.
266             cnt++;
267         }
268         alt = alt->next;
269     }
270     return cnt;
271 }
272 
RemoveEntity(const char * n)273 void Registry::RemoveEntity( const char * n ) {
274     const EntityDescriptor * e = FindEntity( n );
275     struct Element tmp;
276 
277     if( e ) {
278         RemoveClones( *e );
279     }
280     tmp.key = ( char * ) n;
281     SC_HASHsearch( primordialSwamp, &tmp, HASH_DELETE ) ? --entity_cnt : 0;
282 
283 }
284 
RemoveSchema(const char * n)285 void Registry::RemoveSchema( const char * n ) {
286     struct Element tmp;
287     tmp.key = ( char * ) n;
288     SC_HASHsearch( active_schemas, &tmp, HASH_DELETE );
289 }
290 
RemoveType(const char * n)291 void Registry::RemoveType( const char * n ) {
292     struct Element tmp;
293     tmp.key = ( char * ) n;
294     SC_HASHsearch( active_types, &tmp, HASH_DELETE );
295 }
296 
297 /**
298  * Remove all the "clones", or rename values of e.
299  */
RemoveClones(const EntityDescriptor & e)300 void Registry::RemoveClones( const EntityDescriptor & e ) {
301     const SchRename * alts = e.AltNameList();
302     struct Element * tmp;
303 
304     while( alts ) {
305         tmp = new Element;
306         tmp->key = ( char * ) alts->objName();
307         SC_HASHsearch( primordialSwamp, tmp, HASH_DELETE );
308         alts = alts->next;
309     }
310 }
311 
312 
ObjCreate(const char * nm,const char * schnm,int check_case) const313 SDAI_Application_instance * Registry::ObjCreate( const char * nm, const char * schnm, int check_case ) const {
314     const EntityDescriptor  * entd = FindEntity( nm, schnm, check_case );
315     if( entd ) {
316         SDAI_Application_instance * se =
317             ( ( EntityDescriptor * )entd ) -> NewSTEPentity();
318 
319         // See comment in previous function.
320         if( entd->AbstractEntity().asInt() == 1 ) {
321             se->Error().severity( SEVERITY_WARNING );
322             se->Error().UserMsg( "ENTITY is abstract supertype" );
323         } else if( entd->ExtMapping().asInt() == 1 ) {
324             se->Error().severity( SEVERITY_WARNING );
325             se->Error().UserMsg( "ENTITY requires external mapping" );
326         }
327         se->setEDesc( entd );
328         return se;
329     } else {
330         return ENTITY_NULL;
331     }
332 }
333 
334 
GetEntityCnt()335 int Registry::GetEntityCnt() {
336     return entity_cnt;
337 }
338 
ResetEntities()339 void Registry::ResetEntities() {
340     SC_HASHlistinit( primordialSwamp, &cur_entity );
341 
342 }
343 
NextEntity()344 const EntityDescriptor * Registry::NextEntity() {
345     if( 0 == SC_HASHlist( &cur_entity ) ) {
346         return 0;
347     }
348     return ( const EntityDescriptor * ) cur_entity.e->data;
349 }
350 
ResetSchemas()351 void Registry::ResetSchemas() {
352     SC_HASHlistinit( active_schemas, &cur_schema );
353 }
354 
NextSchema()355 const Schema * Registry::NextSchema() {
356     if( 0 == SC_HASHlist( &cur_schema ) ) {
357         return 0;
358     }
359     return ( const Schema * ) cur_schema.e->data;
360 }
361