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