1 // Copyright (C) 2005 CEA/DEN, EDF R&D, OPEN CASCADE, PRINCIPIA R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
8 // This library is distributed in the hope that it will be useful
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include "DDS_Dictionary.h"
21 #include "DDS_KeyWords.h"
23 #include <LDOMString.hxx>
24 #include <LDOMParser.hxx>
26 #include <UnitsAPI.hxx>
28 #include <TColStd_SequenceOfInteger.hxx>
29 #include <TColStd_SequenceOfAsciiString.hxx>
30 #include <TColStd_SequenceOfExtendedString.hxx>
32 #include <NCollection_Map.hxx>
34 #include <Standard_Failure.hxx>
35 #include <Standard_ErrorHandler.hxx>
37 IMPLEMENT_STANDARD_HANDLE(DDS_Dictionary, MMgt_TShared)
38 IMPLEMENT_STANDARD_RTTIEXT(DDS_Dictionary, MMgt_TShared)
43 This class to provide information about used datums, reading them from 'xml' file
45 Datum is the set of parameters described a phisical characteristic. These parameters loaded from
46 special XML which has following format:
51 <COMPONENT COMPONENT_NAME="component_name">
53 <UNIT_SYSTEM UNIT_SYSTEM_NAME="[system_internal_name]" UNIT_SYSTEM_LABEL="[system_label]">
54 <UNIT_SYSTEM UNIT_SYSTEM_NAME="[system_internal_name]" UNIT_SYSTEM_LABEL="[system_label]">
56 <UNIT_SYSTEM UNIT_SYSTEM_NAME="[system_internal_name]" UNIT_SYSTEM_LABEL="[system_label]">
59 <DATUM DATUM_UNITS="[base_system_internal_name]" DATUM_FORMAT="[sprintf_format_specification]"
60 DATUM_ID="[datum_id]" DATUM_LABEL="[datum_label]" DATUM_REQUIRED="[requred_value]"
61 DATUM_FILTER="[string_regular_expression]">
63 <VALUE_DESCR VD_DEFV="[default_value]" VD_MAXV="[max_value]" VD_MINV="[min_value]" VD_TYPE="[value_type]"/>
64 <VALUE_LIST_REF VLR_LIST="[referenced_list_id]"/>
67 <SHORT_D>[brief_desription_text]</SHORT_D>
68 <LONG_D>[full_description_text]</LONG_D>
71 <OPTION OPTION_NAME="[option_name_1]">[option_value_1]</OPTION>
72 <OPTION OPTION_NAME="[option_name_2]">[option_value_2]</OPTION>
74 <OPTION OPTION_NAME="[option_name_n]">[option_value_n]</OPTION>
80 <VALUE_LIST VALUE_LIST_ID="[list_id]" VALUE_LIST_NAME="[list_name]">
81 <VALUE_LIST_VALUE VALUE_LIST_VALUEID="[list_element_id]" VALUE_LIST_VALUEICON="[list_element_icon_file]">[list_element_name]</VALUE_LIST_VALUE>
82 <VALUE_LIST_VALUE VALUE_LIST_VALUEID="[list_element_id]" VALUE_LIST_VALUEICON="[list_element_icon_file]">[list_element_name]</VALUE_LIST_VALUE>
84 <VALUE_LIST_VALUE VALUE_LIST_VALUEID="[list_element_id]" VALUE_LIST_VALUEICON="[list_element_icon_file]">[list_element_name]</VALUE_LIST_VALUE>
94 In description of datum file format used internal keys as XML tag and attributes names.
95 Concrete XML keywords defined by DDS_KeyWords class.
97 Describe datum file format more detailed. XML file should have one main tag named as "dictionary" (key "D_URI").
98 This tag should contains one or several components. Component is a independent set of datums and unit systems.
99 Components defined as XML tag named "component" (key "COMPONENT") with attribute "name" (key COMPONENT_NAME).
100 Component name used as component identifier and should be unique. Component tag can contains:
102 \li Tag "unit_systems" (key UNIT_SYSTEMS) defines set of used unit systems. Should exist at least one unit
103 system named SI ("System International"). If this system not exist then it will be defined automatically.
104 Each unit system defined by XML tag "unit system" (key UNIT_SYSTEM) under tag "unit_systems" with attributes
105 "name" (key UNIT_SYSTEM_NAME) and "label" (key UNIT_SYSTEM_LABEL). Name is identifier of unit system. Label is
106 human readable description.
108 \li One or several tag "datum" (key DATUM). For this tag can be defined following attributes:
110 \lo Identifier (key DATUM_ID) specify the unique id string for the datum.
111 \lo Label (key DATUM_LABEL) specify human readable name of the datum.
112 \lo Units of measure (key DATUM_UNITS) for given unit system. Attribute name consist of a name
113 of unit system and a keyword got from DDS_KeyWords by key DATUM_UNITS. For example for unit system
114 named SI and default keyword attribute name will be "SIunits". This attribute should be specified
115 for each deaclared unit system. Value of this attribute should be string describs units of measure.
116 Possible designations for units of measure and their multiple prefixes see in package UnitsAPI of
117 library OpenCascade (files Units.dat and Lexi_Expr.dat). Units of measure will be used for numeric
118 value conversion from one unit system to another one.
119 \lo Format (key DATUM_FORMAT) specify the format string which will be used during initial formatting
120 of value. This string should be specified in sprintf() format.
121 \lo Filter (key DATUM_FILTER) specify the regualr expression. Each user entered string will be checked up
122 on matching to this expression (if it defined). Non matched strings will be rejected.
123 \lo Required value (key DATUM_REQUIRED). If this attributed defined and value is true then user can't
124 leave a input filed blank (parameter must be always entered).
126 Tag "description" (key DESCR) can be defined under the tag "datum". This tag contains two sub tags:
127 \lo "short description" (key SHORT_D) specify a brief datum description text
128 \lo "long description" (key LONG_D) specify a detailed description text
130 Tag "options" (key OPTIONS) can be defined under the tag "datum". This tag contains one or more sub
131 tags "option" (key OPTION). Each of these XML elements should contain text option value and attribute
132 "name" (key OPTION_NAME) which specified option name.
134 Each tag "datum" define most common parameters of phisical characteristic.
135 This parameters placed in two groups:
136 \lo Domain parameters under tag "domain" (key DY_DOMAIN). This tag can contains value description tag
137 (key VALUE_DESCR) for discrete data or list reference tag (key VALUE_LIST_REF) for enumerable data.
138 Discrete data described following parameters:
139 default value (key VD_DEFV)
140 maximum value (key VD_MAXV)
141 minimum value (key VD_MINV)
142 type of value (key VD_TYPE) - possible values: String, Integer, Float, List
143 Enumerable data described by "list reference" attribute (key VLR_LIST) which reference on
144 list (see "list definition" tag) by list id.
146 \li One or several tag "list definition" (key VALUE_LIST). This tag define the list of items for enumerable
147 data. Attribute "list id" (key VALUE_LIST_ID) specify the identifier string for the list and attribute
148 "list name" (key VALUE_LIST_NAME) define a list name string. Each list item described by tag "list value"
149 (key VALUE_LIST_VALUE) under tag "list definition". Each this tag contains item string text and have
150 following attributes:
151 \lo "list item id" (key VALUE_LIST_VALUEID) - integer numerical identifier for item
152 \lo "list item icon" (key VALUE_LIST_VALUEICON) - icon file name for item
154 Below the example of a XML file with use default keywords.
156 <datadictionary version="1.0">
157 <component name="My Component">
159 <!-- specify two unit systems -->
162 <system name="SI" label="System international">
163 <system name="AS" label="Anglo - sacson system">
166 <!-- specify datum -->
167 <!-- units of measure for SI - meters (m), for AS - inches (in) -->
168 <datum SIunits="m" ASunits="in" format="%.25f" id="X" label="X coordinate" required="">
170 <!-- default value not specified -->
171 <valueDescr default="" max="999999999.999" min="0.000" type="Float"/>
174 <shortDescr>X coordinate for object</shortDescr>
175 <longDescr>X multiplier of object coordinates. Describe position of object in direction of X axis</longDescr>
179 <datum SIunits="m" ASunits="in" format="%.25f" id="Y" label="Y coordinate" required="">
181 <valueDescr default="" max="999999999.999" min="0.000" type="Float"/>
184 <shortDescr>Y coordinate for object</shortDescr>
185 <longDescr>Y multiplier of object coordinates. Describe position of object in direction of Y axis</longDescr>
189 <!-- datum for object name with filter which not allow to input more that 8 letters,
190 numbers or unerscores with first letter only -->
191 <datum format="%.8us" id="ObjectName" label="Name" required="yes"
192 filter="^([A-Z]+)([A-Z,0-9,_]*)$">
194 <!-- limits and default not specified, type is string -->
195 <valueDescr default="" max="" min="" type="String" />
198 <!-- long description not specified -->
199 <shortDescr>Name of object</shortDescr>
204 <!-- datum for enumeration of side -->
205 <datum format="" id="Side" label="Side" required="">
207 <!-- default list item is item with id 0 -->
208 <valueDescr default="0" type="List"/>
209 <!-- list reference on list named "side_list" -->
210 <listRef list="side_list"/>
213 <shortDescr>Side of object</shortDescr>
217 <!-- list definition for enumeration of side -->
218 <valueList listid="side_list" name="Side">
219 <value id="1">left</value>
220 <value id="2">right</value>
221 <value id="3">top</value>
222 <value id="4">bottom</value>
223 <value id="0">undefined</value>
233 Constructor. Creates the instance of dictionary. Private method. Use DDS_Dictionary::Get() instead.
235 DDS_Dictionary::DDS_Dictionary()
241 Copy constructor. Internal.
243 DDS_Dictionary::DDS_Dictionary( const DDS_Dictionary& )
248 Assigment operator. Internal.
250 void DDS_Dictionary::operator=( const DDS_Dictionary& )
255 Returns the names list of defined unit systems from all components.
256 Parameter \atheSystems will contains the sequence of string names.
258 void DDS_Dictionary::GetUnitSystems( TColStd_SequenceOfAsciiString& theSystems ) const
262 NCollection_Map<TCollection_AsciiString> aMap;
263 for ( Standard_Integer i = 1; i <= myGroupMap.Extent(); i++ )
265 TColStd_SequenceOfAsciiString theSeq;
266 myGroupMap.FindFromIndex( i )->GetUnitSystems( theSeq );
267 for ( Standard_Integer s = 1; s <= theSeq.Length(); s++ )
269 if ( aMap.Contains( theSeq.Value( s ) ) )
272 theSystems.Append( theSeq.Value( s ) );
273 aMap.Add( theSeq.Value( s ) );
280 Returns the names list of defined unit systems from the specified component \atheComponent.
281 Parameter \atheSystems will contains the sequence of string names. If component not found then
284 void DDS_Dictionary::GetUnitSystems( TColStd_SequenceOfAsciiString& theSystems,
285 const TCollection_AsciiString& theComponent ) const
288 if ( myGroupMap.Contains( theComponent ) )
289 myGroupMap.FindFromKey( theComponent )->GetUnitSystems( theSystems );
293 Returns the label of unit system \atheSystem. Function find the given unit system in
294 all components. If unit system not found in any component then empty string returned.
296 TCollection_ExtendedString DDS_Dictionary::GetUnitSystemLabel( const TCollection_AsciiString& theSystem ) const
298 TCollection_ExtendedString aLabel;
299 for ( Standard_Integer i = 1; i <= myGroupMap.Extent() && !aLabel.Length(); i++ )
300 aLabel = myGroupMap.FindFromIndex( i )->GetUnitSystemLabel( theSystem );
305 Returns the label of unit system \atheSystem from component \atheComponent. Function find
306 the given unit system in the specified component only. If unit system not found in the
307 component then empty string returned.
309 TCollection_ExtendedString DDS_Dictionary::GetUnitSystemLabel( const TCollection_AsciiString& theSystem,
310 const TCollection_AsciiString& theComponent ) const
312 TCollection_ExtendedString aLabel;
313 if ( myGroupMap.Contains( theComponent ) )
314 aLabel = myGroupMap.FindFromKey( theComponent )->GetUnitSystemLabel( theSystem );
319 Gets the name of active unit system from first got component. If any component exist then
320 active unit system name returned or empty string otherwise.
322 TCollection_AsciiString DDS_Dictionary::GetActiveUnitSystem() const
324 TCollection_AsciiString aSystem;
325 if ( myGroupMap.Extent() )
326 aSystem = myGroupMap.FindFromIndex( 1 )->GetActiveUnitSystem();
331 Gets the name of active unit system from component \atheComponent. If this component exist
332 active unit system name returned or empty string otherwise.
334 TCollection_AsciiString DDS_Dictionary::GetActiveUnitSystem( const TCollection_AsciiString& theComponent ) const
336 TCollection_AsciiString aSystem;
337 if ( myGroupMap.Contains( theComponent ) )
338 aSystem = myGroupMap.FindFromKey( theComponent )->GetActiveUnitSystem();
343 Sets the active unit system named \atheSystem. This unit system will be activated in all
344 existing components if component have it.
346 void DDS_Dictionary::SetActiveUnitSystem( const TCollection_AsciiString& theSystem )
348 for ( Standard_Integer i = 1; i <= myGroupMap.Extent(); i++ )
349 myGroupMap.FindFromIndex( i )->SetActiveUnitSystem( theSystem );
353 Sets the active unit system named \atheSystem for component \atheComponent. If specified unit
354 system doesn't exist in the component then function do nothing.
356 void DDS_Dictionary::SetActiveUnitSystem( const TCollection_AsciiString& theSystem,
357 const TCollection_AsciiString& theComponent )
359 if ( myGroupMap.Contains( theComponent ) )
360 myGroupMap.FindFromKey( theComponent )->SetActiveUnitSystem( theSystem );
364 Returns the instance of dictionary. Create instance if it is NULL.
366 Handle(DDS_Dictionary) DDS_Dictionary::Get()
368 static Handle(DDS_Dictionary) sDictionary;
370 if ( sDictionary.IsNull() )
371 sDictionary = new DDS_Dictionary();
377 Load datum definitions in the dictionary from XML file \atheFileName. Returns true if load
378 successed or false otherwise.
380 Standard_Boolean DDS_Dictionary::Load( const TCollection_AsciiString theFileName )
382 static NCollection_Map<TCollection_AsciiString> _LoadMap;
384 if ( _LoadMap.Contains( theFileName ) )
385 return Standard_True;
387 Handle(DDS_Dictionary) aDic = Get();
389 return Standard_False;
392 if ( aParser.parse( theFileName.ToCString() ) )
393 return Standard_False;
395 LDOM_Document aDoc = aParser.getDocument();
396 LDOM_Element aDocElement = aDoc.getDocumentElement();
397 for ( LDOM_Element aComponentElem = aDocElement.GetChildByTagName( KeyWord( "COMPONENT" ) );
398 !aComponentElem.isNull(); aComponentElem = aComponentElem.GetSiblingByTagName() )
399 aDic->FillDataMap( aComponentElem, aDocElement );
401 _LoadMap.Add( theFileName );
403 return Standard_True;
407 Gets XML keyword as LDOMString by specified \akey. If key doesn't exist then empty string
408 returned. This function provided for convenience.
410 LDOMString DDS_Dictionary::KeyWord( const TCollection_AsciiString& key )
413 Handle(DDS_KeyWords) aKeyWords = DDS_KeyWords::Get();
414 if ( !aKeyWords.IsNull() )
416 TCollection_AsciiString aStr = aKeyWords->GetKeyWord( key );
418 keyWord = LDOMString( aStr.ToCString() );
424 Gets dictionary item with specified identifier \atheID from specified component \atheComponent.
425 If component or item not found then null handle returned.
427 Handle(DDS_DicItem) DDS_Dictionary::GetDicItem( const TCollection_AsciiString& theID,
428 const TCollection_AsciiString& theComponent ) const
430 Handle(DDS_DicItem) aDicItem;
431 Handle(DDS_DicGroup) aDicGroup;
432 if ( myGroupMap.Contains( theComponent ) )
433 aDicGroup = myGroupMap.FindFromKey( theComponent );
434 if ( !aDicGroup.IsNull() )
435 aDicItem = aDicGroup->GetDicItem( theID );
440 Gets dictionary item with specified identifier \atheID. Function find the item in all components.
441 If item not found in any component then null handle returned.
443 Handle(DDS_DicItem) DDS_Dictionary::GetDicItem( const TCollection_AsciiString& theID ) const
445 Handle(DDS_DicItem) aDicItem;
446 for ( Standard_Integer i = 1; i <= myGroupMap.Extent() && aDicItem.IsNull(); i++ )
447 aDicItem = myGroupMap.FindFromIndex( i )->GetDicItem( theID );
452 Fill the internal data structures from XML parsed structures. Internal.
454 void DDS_Dictionary::FillDataMap( const LDOM_Element& theComponentData, const LDOM_Element& theDocElement )
456 TCollection_AsciiString aCompName = theComponentData.getAttribute( KeyWord( "COMPONENT_NAME" ) );
457 if ( !myGroupMap.Contains( aCompName ) )
458 myGroupMap.Add( aCompName, new DDS_DicGroup( aCompName ) );
459 Handle(DDS_DicGroup) aDicGroup = myGroupMap.FindFromKey( aCompName );
460 aDicGroup->FillDataMap( theComponentData, theDocElement );
461 myGroupMap.Add( aCompName, aDicGroup );
465 Convert numeric value \atheValue from specified unit of measure \atheUnits to SI unit of measure
466 (mm for Length, radians for Angles, etc). Converted value returned.
468 Standard_Real DDS_Dictionary::ToSI( const Standard_Real theValue, const Standard_CString theUnits )
470 Standard_Real aRetValue = theValue;
471 if ( theUnits && *theUnits && strcmp( theUnits, "%" ) )
474 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
477 aRetValue = UnitsAPI::AnyToSI( theValue, theUnits );
479 catch( Standard_Failure ) {
482 else if ( theUnits && *theUnits )
483 aRetValue = theValue / 100.0;
489 Convert numeric value \atheValue to specified unit of measure \atheUnits from SI unit of measure
490 (mm for Length, radians for Angles, etc). Converted value returned.
492 Standard_Real DDS_Dictionary::FromSI( const Standard_Real theValue, const Standard_CString theUnits )
494 Standard_Real aRetValue = theValue;
495 if ( theUnits && *theUnits && strcmp( theUnits, "%" ) )
498 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
501 aRetValue = UnitsAPI::AnyFromSI( theValue, theUnits );
503 catch( Standard_Failure ) {
506 else if ( theUnits && *theUnits )
507 aRetValue = theValue * 100.0;