]> SALOME platform Git repositories - modules/gui.git/blob - src/DDS/DDS_DicItem.cxx
Salome HOME
6a8954546c2fe97cab83b5d3d50996816d0b6968
[modules/gui.git] / src / DDS / DDS_DicItem.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "DDS_DicItem.h"
23 #include "DDS_Dictionary.h"
24
25 #include <TColStd_SequenceOfInteger.hxx>
26 #include <TColStd_SequenceOfExtendedString.hxx>
27
28 #include <LDOM_Text.hxx>
29 #include <LDOMString.hxx>
30 #include <LDOM_Element.hxx>
31
32 #include <UnitsAPI.hxx>
33 #include <Units_Dimensions.hxx>
34
35 #include <TColStd_MapOfReal.hxx>
36 #include <TColStd_SequenceOfAsciiString.hxx>
37
38 IMPLEMENT_STANDARD_HANDLE(DDS_DicItem, MMgt_TShared)
39 IMPLEMENT_STANDARD_RTTIEXT(DDS_DicItem, MMgt_TShared)
40
41 /*!
42   \class DDS_DicItem
43   \brief This class provides an information about datum (phisical characteristic parameter).
44 */
45
46 /*!
47   \brief Constructor.
48
49   Creates the instance of empty dictionary item.
50 */
51 DDS_DicItem::DDS_DicItem()
52 : myType( 0 ),
53   myMax( 0 ),
54   myMin( 0 ),
55   myDefValue( 0 ),
56   myMinZoom( 0.1 ),
57   myMaxZoom( 10 ),
58   myZoomOrder( 2 )
59 {
60 }
61
62 /*!
63   \brief Copy constructor (put in private section to prevent object copying).
64 */
65 DDS_DicItem::DDS_DicItem( const DDS_DicItem& )
66 {
67 }
68
69 /*!
70   \brief Assignment operator (put in private section to prevent object copying).
71 */
72 void DDS_DicItem::operator=( const DDS_DicItem& )
73 {
74 }
75
76 /*!
77   \brief Get the identifier of parameter.
78   \return parameter ID
79 */
80 TCollection_AsciiString DDS_DicItem::GetId() const
81 {
82   return myId;
83 }
84
85 /*!
86   \brief Get the type of parameter.
87   \return parameter type
88 */
89 DDS_DicItem::Type DDS_DicItem::GetType() const
90 {
91   return (DDS_DicItem::Type)myType;
92 }
93
94 /*!
95   \brief Get the label of the parameter.
96   \return parameter label
97 */
98 TCollection_ExtendedString DDS_DicItem::GetLabel() const
99 {
100   return myLabel;
101 }
102
103 /*!
104   \brief Get the filter (regular expression) for the parameter values.
105   \return parameter filter
106 */
107 TCollection_ExtendedString DDS_DicItem::GetFilter() const
108 {
109   return myFilter;
110 }
111
112 /*!
113   \brief Get the Required attribute of the parameter.
114   \return Required attribute
115 */
116 TCollection_ExtendedString DDS_DicItem::GetRequired() const
117 {
118   return myRequired;
119 }
120
121 /*!
122   \brief Get the wrong value warning level of the parameter.
123   \return warning level
124 */
125 DDS_MsgType DDS_DicItem::GetWarningLevel() const
126 {
127   return (DDS_MsgType)myWarnLevel;
128 }
129
130 /*!
131   \brief Get the long description of the parameter.
132   \return long description
133 */
134 TCollection_ExtendedString DDS_DicItem::GetLongDescription() const
135 {
136   return myLongDescr;
137 }
138
139 /*!
140   \brief Get the short description of the parameter.
141   \return short description
142 */
143 TCollection_ExtendedString DDS_DicItem::GetShortDescription() const
144 {
145   return myShortDescr;
146 }
147
148 /*!
149   \brief Get the name of the component (parameter owner).
150   \return component name
151 */
152 TCollection_AsciiString DDS_DicItem::GetComponent() const
153 {
154   TCollection_AsciiString aCompName;
155   Handle(DDS_DicGroup) aComponent = Handle(DDS_DicGroup)::DownCast(myComponent);
156   if ( !aComponent.IsNull() )
157     aCompName = aComponent->GetName();
158   return aCompName;
159 }
160
161 /*!
162   \brief Get the parameter measure units for active units system.
163   \return parameter units
164 */
165 TCollection_AsciiString DDS_DicItem::GetUnits() const
166 {
167   return GetUnits( GetActiveUnitSystem() );
168 }
169
170 /*!
171   \brief Get the parameter measure units for specified units system \a theSystem.
172
173   If specified units system doesn't exist, empty string is returned.
174
175   \param theSystem units system
176   \return parameter units
177 */
178 TCollection_AsciiString DDS_DicItem::GetUnits( const UnitSystem& theSystem ) const
179 {
180   TCollection_AsciiString anUnits;
181   UnitData* unitData = GetUnitData( theSystem );
182   if ( unitData )
183     anUnits = unitData->myUnits;
184   return anUnits;
185 }
186
187 /*!
188   \brief Get the minimum value of the parameter for active units system.
189   
190   Returned value is converted to SI.
191   
192   \return minimum value
193 */
194 Standard_Real DDS_DicItem::GetMinValue() const
195 {
196   return GetMinValue( GetActiveUnitSystem() );
197 }
198
199 /*!
200   \brief Get the minimum value of the parameter for the specified 
201          units system \a theSystem.
202          
203   Returned value is converted to SI.
204
205   \param theUnitsSystem units system
206   \return minimum value
207 */
208 Standard_Real DDS_DicItem::GetMinValue( const UnitSystem& theUnitsSystem ) const
209 {
210   return FromSI( myMin, theUnitsSystem );
211 }
212
213 /*!
214   \brief Get the maximum value of the parameter for active units system.
215
216   Returned value converted to SI.
217   
218   \return maximum value
219 */
220 Standard_Real DDS_DicItem::GetMaxValue() const
221 {
222   return GetMaxValue( GetActiveUnitSystem() );
223 }
224
225 /*!
226   \brief Get the maximum value of the parameter for specified 
227          units system \a theSystem.
228  
229   Returned value converted to SI.
230   
231   \param theUnitsSystem units system
232   \return maximum value
233 */
234 Standard_Real DDS_DicItem::GetMaxValue( const UnitSystem& theUnitsSystem ) const
235 {
236   return FromSI( myMax, theUnitsSystem );
237 }
238
239 /*!
240   \brief Get the precision (number of digits after decimal point) 
241          of the parameter for active units system.
242   \return parameter precision
243 */
244 Standard_Integer DDS_DicItem::GetPrecision() const
245 {
246   return GetPrecision( GetActiveUnitSystem() );
247 }
248
249 /*!
250   \brief Get the precision (number of digits after decimal point) of the parameter
251   for specified units system \a theSystem. 
252
253   If specified units system doesn't exist, zero is returned.
254
255   \param theSystem units system
256   \return parameter precision
257 */
258 Standard_Integer DDS_DicItem::GetPrecision( const UnitSystem& theSystem ) const
259 {
260   Standard_Integer aRes = 0;
261   UnitData* unitData = GetUnitData( theSystem );
262   if ( unitData )
263     aRes = unitData->myPrecision;
264   return aRes;
265 }
266
267 /*!
268   \brief Get the default value of the parameter for active units system.
269   
270   Default value is returned as string.
271   If type of the value is numerical (Float or Integer) and default value
272   is defined, then the returning value is converted to SI.
273
274   \return default value
275 */
276 TCollection_ExtendedString DDS_DicItem::GetDefaultValue() const
277 {
278   return GetDefaultValue( GetActiveUnitSystem() );
279 }
280
281 /*!
282   \brief Get the default value of the parameter for specified 
283          units system \a theSystem.
284   
285   Default value is returned as string.
286   If type of the value is numerical (Float or Integer) and default value
287   is defined, then the returning value is converted to SI.
288
289   \param theSystem units system
290   \return default value
291 */
292 TCollection_ExtendedString DDS_DicItem::GetDefaultValue( const UnitSystem& theSystem ) const
293 {
294   if ( !myDefString.Length() )
295     return myDefString;
296
297   TCollection_ExtendedString aStr;
298
299   switch ( myType )
300   {
301   case Float:
302   case Integer:
303     aStr = FromSI( myDefValue, theSystem );
304     break;
305   case List:
306   case String:
307     aStr = myDefString;
308     break;
309   default:
310     break;
311   }
312   return aStr;
313 }
314
315 /*!
316   \brief Get the format string of the parameter for active units system.
317
318   If argument \a theCanonical is \c true, format string is reduced according
319   to the sprintf() specification (without extra non standard qualifiers).
320
321   \param theCanonical 'canonical form' flag
322   \return format string
323 */
324 TCollection_AsciiString DDS_DicItem::GetFormat( const Standard_Boolean theCanonical ) const
325 {
326   return GetFormat( GetActiveUnitSystem(), theCanonical );
327 }
328
329 /*!
330   \brief Get the format string of the parameter for specified 
331          units system \a theSystem.
332
333   If argument \a theCanonical is \c true, format string is reduced according
334   to the sprintf() specification (without extra non standard qualifiers).
335
336   \param theSystem units system
337   \param theCanonical 'canonical form' flag
338   \return format string
339 */
340 TCollection_AsciiString DDS_DicItem::GetFormat( const UnitSystem& theSystem,
341                                                 const Standard_Boolean theCanonical ) const
342 {
343   TCollection_AsciiString aFormat;
344   UnitData* unitData = GetUnitData( theSystem );
345   if ( unitData )
346     aFormat = unitData->myFormat;
347
348   if ( theCanonical && aFormat.Length() > 1 )
349   {
350     static TCollection_AsciiString f;
351     f = aFormat;
352     Standard_Boolean isRemoved = false;
353     while ( !isRemoved )
354     {
355       char ch = f.Value( f.Length() - 1 );
356       if ( ( ch != '%' && ch != '.' && !IsDigit( ch ) ) && f.Length() > 1 )
357         f.Remove( f.Length() - 1 );
358       else
359         isRemoved = true;
360     }
361     aFormat = f;
362   }
363
364   return aFormat;
365 }
366
367 /*!
368   \brief Get the name of a list referenced by the parameter.
369
370   This string is empty if the list reference is not defined.
371   In this case, other properties (Type, DefaultValue, MaxValue, MinValue)
372   should be used.
373   
374   \return referenced list name
375   \sa GetListOfValues()
376 */
377 TCollection_ExtendedString DDS_DicItem::GetNameOfValues() const
378 {
379   return myListName;
380 }
381
382 /*!
383   \brief Get item names and item identifiers of a list referenced
384          by the parameter.
385
386   These sequences are empty if the list reference is not defined.
387   In this case, other properties (Type, DefaultValue, MaxValue, MinValue)
388   should be used.
389
390   \param theStrings returning items names
391   \param theIntegers returning items identifiers
392   \return \c true if returning lists are not empty
393   \sa GetNameOfValues()
394 */
395 Standard_Boolean DDS_DicItem::GetListOfValues( Handle(TColStd_HArray1OfExtendedString)& theStrings,
396                                                Handle(TColStd_HArray1OfInteger)& theIntegers ) const
397 {
398   theStrings  = myListRef;
399   theIntegers = myListRefID;
400   return !theIntegers.IsNull() && !theStrings.IsNull();
401 }
402
403 /*!
404   \brief Get item names, item identifiers and item icons of a list
405          referenced by the parameter.
406
407   \overload
408
409   These sequences are empty if the list reference is not defined.
410   In this case, other properties (Type, DefaultValue, MaxValue, MinValue)
411   should be used.
412
413   \param theStrings returning items names
414   \param theIntegers returning items identifiers
415   \param theIcons returning items icons
416   \return \c true if returning lists are not empty
417   \sa GetNameOfValues()
418 */
419 Standard_Boolean DDS_DicItem::GetListOfValues( Handle(TColStd_HArray1OfExtendedString)& theStrings,
420                                                Handle(TColStd_HArray1OfInteger)& theIntegers,
421                                                Handle(TColStd_HArray1OfExtendedString)& theIcons ) const
422 {
423   theStrings  = myListRef;
424   theIntegers = myListRefID;
425   theIcons    = myListRefIcons;
426   return !theIntegers.IsNull() && !theStrings.IsNull() && !theIcons.IsNull();
427 }
428
429
430 /*!
431   \brief Get special values of the parameter.
432   \param theMap returning map of the special values
433   \return \c true if returning map is not empty
434 */
435 Standard_Boolean DDS_DicItem::GetSpecialValues( TColStd_MapOfReal& theMap ) const
436 {
437   theMap.Clear();
438   if ( !myListRef.IsNull() )
439   {
440     for ( Standard_Integer i = myListRef->Lower(); i <= myListRef->Upper(); i++ )
441     {
442       if ( myListRef->Value( i ).IsAscii() )
443       {
444         TCollection_AsciiString aStr( myListRef->Value( i ) );
445         if ( aStr.IsRealValue() )
446           theMap.Add( aStr.RealValue() );
447       }
448     }
449   }
450
451   return theMap.Extent() > 0;
452 }
453
454 /*!
455   \brief Get minimum value of lateral zooming.
456   \return lateral zooming minimum value
457 */
458 Standard_Real DDS_DicItem::GetMinZoom() const
459 {
460   return myMinZoom;
461 }
462
463 /*!
464   \brief Get maximum value of lateral zooming.
465   \return lateral zooming maximum value
466 */
467 Standard_Real DDS_DicItem::GetMaxZoom() const
468 {
469   return myMaxZoom;
470 }
471
472 /*!
473   \brief Get order of lateral zooming.
474   \return lateral zooming order
475 */
476 Standard_Real DDS_DicItem::GetZoomOrder() const
477 {
478   return myZoomOrder;
479 }
480
481 /*!
482   \brief Convert value \a theVal to the default SI units
483          according to the active units system.
484   \param theVal value being converted
485   \return value converted to SI
486 */
487 Standard_Real DDS_DicItem::ToSI( const Standard_Real theVal ) const
488 {
489   return ToSI( theVal, GetActiveUnitSystem() );
490 }
491
492 /*!
493   \brief Convert value \a theVal from the default SI units
494          according to the active units system.
495   \param theVal value being converted
496   \return value converted from SI
497 */
498 Standard_Real DDS_DicItem::FromSI( const Standard_Real theVal ) const
499 {
500   return FromSI( theVal, GetActiveUnitSystem() );
501 }
502
503 /*!
504   \brief Convert value to the default SI units according to the 
505          units system \a theUnitsSystem.
506   \param theVal value being converted
507   \param theUnitsSystem units system
508   \return value converted to the specified units system
509 */
510 Standard_Real DDS_DicItem::ToSI( const Standard_Real theVal, const UnitSystem& theUnitsSystem ) const
511 {
512   Standard_Real aRes = theVal;
513   UnitData* anUnitData = GetUnitData( theUnitsSystem );
514   if ( anUnitData )
515     aRes = anUnitData->myZero + aRes * anUnitData->myScale;
516   return aRes;
517 }
518
519 /*!
520   \brief Convert value from the default SI units according to the
521          units system \a theUnitsSystem.
522   \param theVal value being converted
523   \param theUnitsSystem units system
524   \return value converted from the specified units system
525 */
526 Standard_Real DDS_DicItem::FromSI( const Standard_Real theVal, const UnitSystem& theUnitsSystem ) const
527 {
528   Standard_Real aRes = theVal;
529   UnitData* anUnitData = GetUnitData( theUnitsSystem );
530   if ( anUnitData )
531     aRes = ( aRes - anUnitData->myZero ) / anUnitData->myScale;
532   return aRes;
533 }
534
535 /*!
536   \brief Check data existence.
537   \param flag data flag
538   \return \c true if data specified by \a flag exists
539 */
540 Standard_Boolean DDS_DicItem::HasData( const Standard_Integer flag ) const
541 {
542   return ( myData & flag ) == flag;
543 }
544
545 /*!
546   \brief Get option for specified name \a name.
547   
548   If option is not found, empty string is returned.
549
550   \param name option name
551   \return option value
552 */
553 TCollection_ExtendedString DDS_DicItem::GetOption( const TCollection_AsciiString& name ) const
554 {
555   TCollection_ExtendedString res;
556   if ( myOptions.IsBound( name ) )
557     res = myOptions.Find( name );
558   return res;
559 }
560
561 /*!
562   \brief Get names of all existing options.
563   \param names returning list of options
564   \return \c true if list is not empty
565 */
566 Standard_Boolean DDS_DicItem::GetOptionNames( TColStd_SequenceOfAsciiString& names ) const
567 {
568   names.Clear();
569
570   for ( OptionsMap::Iterator it( myOptions ); it.More(); it.Next() )
571     names.Append( it.Key() );
572
573   return !names.IsEmpty();
574 }
575
576
577 /*!
578   \brief Parse record from XML file and retrieve information relevant for 
579          the dictionary item.
580   \param theID item identifier
581   \param theDatum datum XML node
582   \param theCompElement component XML node
583   \param theDocElement document XML node
584   \param theSystems units system names
585 */
586 void DDS_DicItem::FillDataMap( TCollection_AsciiString theID, const LDOM_Element& theDatum,
587                                const LDOM_Element& theCompElement, const LDOM_Element& theDocElement,
588                                const TColStd_SequenceOfAsciiString& theSystems )
589 {
590   TCollection_AsciiString aLabel    = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_LABEL" ) );
591   TCollection_AsciiString aFormat   = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_FORMAT" ) );
592   TCollection_AsciiString aFilter   = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_FILTER" ) );
593   TCollection_AsciiString aRequired = theDatum.getAttribute( DDS_Dictionary::KeyWord( "DATUM_REQUIRED" ) );
594
595   TCollection_AsciiString aBaseKeyWord = DDS_Dictionary::KeyWord( "DATUM_UNITS" );
596
597   for ( Standard_Integer j = 1; j <= theSystems.Length(); j++ )
598   {
599     UnitSystem anUnitSystem = theSystems.Value( j );
600     if ( !anUnitSystem.Length() )
601       continue;
602
603     TCollection_AsciiString aUnitKeyword = anUnitSystem + aBaseKeyWord;
604
605     if ( !myUnitData.IsBound( anUnitSystem ) )
606       myUnitData.Bind( anUnitSystem, UnitData() );
607
608     UnitData& anUnitData = myUnitData.ChangeFind( anUnitSystem );
609     anUnitData.myUnits = theDatum.getAttribute( LDOMString( aUnitKeyword.ToCString() ) );
610   }
611
612   if ( theSystems.Length() && myUnitData.IsBound( theSystems.First() ) &&
613        !myUnitData.Find( theSystems.First() ).myUnits.Length() )
614   {
615     TCollection_AsciiString units = theDatum.getAttribute( LDOMString( aBaseKeyWord.ToCString() ) );
616     if ( units.Length() )
617       myUnitData.ChangeFind( theSystems.First() ).myUnits = units;
618   }
619
620   TCollection_AsciiString units;
621   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator iter( myUnitData ); iter.More() && units.IsEmpty(); iter.Next() )
622     units = iter.Value().myUnits;
623
624   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator itr( myUnitData ); itr.More(); itr.Next() )
625   {
626     UnitData& dataUnits = itr.ChangeValue();
627     if ( dataUnits.myUnits.IsEmpty() )
628       dataUnits.myUnits = units;
629   }
630   
631   // 2. Elements ( domain, description )
632   Standard_Real aRealMinV = 0;
633   Standard_Real aRealMaxV = 0;
634   Standard_Real aRealDefV = 0;
635
636   TCollection_AsciiString aType;
637
638   DDS_MsgType aWrongValue = DDS_MT_NONE;
639   DDS_DicItem::Type aEnumType = DDS_DicItem::Unknown;
640
641   TCollection_AsciiString aMinV;
642   TCollection_AsciiString aMaxV;
643   TCollection_AsciiString aDefV;
644   TCollection_AsciiString aListName;
645
646   TCollection_AsciiString aLongD;
647   TCollection_AsciiString aShortD;
648
649   TColStd_SequenceOfInteger aSeqOfValueID;
650   TColStd_SequenceOfExtendedString aSeqOfValue;
651   TColStd_SequenceOfExtendedString aSeqOfValueIconName;
652
653   // Presentation
654   Standard_Real aMinZoom   = 0;
655   Standard_Real aMaxZoom   = 0;
656   Standard_Real aZoomOrder = 0;
657
658   // Datum::Reports tags (if any)
659   LDOM_Element aWLev = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "WARNING_LEVEL" ) );
660   if ( !aWLev.isNull() )
661   {
662     TCollection_AsciiString aWrongValWL = aWLev.getAttribute( DDS_Dictionary::KeyWord( "WRONG_VALUE" ) );
663     if ( aWrongValWL.IsEqual( "Info" ) )
664       aWrongValue = DDS_MT_INFO;
665     else if ( aWrongValWL.IsEqual( "Warning" ) )
666       aWrongValue = DDS_MT_WARNING;
667     else if ( aWrongValWL.IsEqual( "Alarm" ) )
668       aWrongValue = DDS_MT_ALARM;
669     else if ( aWrongValWL.IsEqual( "Error" ) )
670       aWrongValue = DDS_MT_ERROR;
671   }
672
673   // Datum::Presentation
674   LDOM_Element aPrs = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "PRS" ) );
675   if ( !aPrs.isNull() )
676   {
677     LDOM_Element aLateralZoom = aPrs.GetChildByTagName( DDS_Dictionary::KeyWord( "LATERAL_ZOOM" ) );
678     if ( !aLateralZoom.isNull() )
679     {
680       TCollection_AsciiString aMinZoomStr   = aLateralZoom.getAttribute( DDS_Dictionary::KeyWord( "LZ_MINV" ) );
681       TCollection_AsciiString aMaxZoomStr   = aLateralZoom.getAttribute( DDS_Dictionary::KeyWord( "LZ_MAXV" ) );
682       TCollection_AsciiString aZoomOrderStr = aLateralZoom.getAttribute( DDS_Dictionary::KeyWord( "LZ_ORDER" ) );
683       
684       aMinZoomStr.RemoveAll( ' ' );
685       if ( aMinZoomStr.IsRealValue() )
686         aMinZoom = aMinZoomStr.RealValue();
687
688       aMaxZoomStr.RemoveAll( ' ' );
689       if ( aMaxZoomStr.IsRealValue() )
690         aMaxZoom = aMaxZoomStr.RealValue();
691
692       aZoomOrderStr.RemoveAll( ' ' );
693       if ( aZoomOrderStr.IsRealValue() )
694         aZoomOrder = aZoomOrderStr.RealValue();
695     }
696   }
697
698   // Quantity::Domain record as the only child of that tag name
699   LDOM_Element aDomain = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "DY_DOMAIN" ) );
700   if ( !aDomain.isNull() )
701   {
702     LDOM_Element aValueDescr = aDomain.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_DESCR" ) );
703     if ( !aValueDescr.isNull() )
704     {
705       // read: valueDescr? (type?,min?,max?,default?)
706       aType = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_TYPE" ) );
707       if ( aType.IsEqual( "String" ) )
708         aEnumType = String;
709       else if ( aType.IsEqual( "Float" ) )
710         aEnumType = Float;
711       else if ( aType.IsEqual( "Integer" ) )
712         aEnumType = Integer;
713
714       if ( !aValueDescr.getAttributeNode( DDS_Dictionary::KeyWord( "VD_MINV" ) ).isNull() )
715         myData |= MinValue;
716       aMinV = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_MINV" ) );
717       aMinV.RemoveAll( ' ' );
718       if ( aMinV.IsRealValue() )
719         aRealMinV = aMinV.RealValue();
720       if ( !aValueDescr.getAttributeNode( DDS_Dictionary::KeyWord( "VD_MAXV" ) ).isNull() )
721         myData |= MaxValue;
722       aMaxV = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_MAXV" ) );
723       aMaxV.RemoveAll( ' ' );
724       if ( aMaxV.IsRealValue() )
725         aRealMaxV = aMaxV.RealValue();
726       aDefV = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_DEFV" ) );
727       if ( !aValueDescr.getAttributeNode( DDS_Dictionary::KeyWord( "VD_DEFV" ) ).isNull() )
728         myData |= DefaultValue;
729
730       aDefV.RemoveAll( ' ' );
731       if ( aDefV.IsRealValue() )
732         aRealDefV = aDefV.RealValue();
733
734       TCollection_AsciiString aSpecVal = aValueDescr.getAttribute( DDS_Dictionary::KeyWord( "VD_SPEC" ) );
735       Split( aSpecVal, myListRef );
736     }
737     else
738     {
739       //  read: listRef? (list?)
740       LDOM_Element aListRef = aDomain.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST_REF" ) );
741       if ( !aListRef.isNull() )
742       {
743         aType = "List";
744         aEnumType = List;                       
745         LDOMString aListId = aListRef.getAttribute( DDS_Dictionary::KeyWord( "VLR_LIST" ) );
746         aDefV = aListRef.getAttribute( DDS_Dictionary::KeyWord( "VD_DEFV" ) );
747         aDefV.RemoveAll( ' ' );
748         LDOM_Element foundListItem;
749         for ( LDOM_Element aListItem = theCompElement.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST" ) );
750               aListItem != NULL && foundListItem == NULL; aListItem = aListItem.GetSiblingByTagName() )
751         {
752           if ( aListItem.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_ID" ) ).equals( aListId ) )
753             foundListItem = aListItem;
754
755         }
756         for ( LDOM_Element aLstItem = theDocElement.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST" ) );
757               aLstItem != NULL && foundListItem == NULL; aLstItem = aLstItem.GetSiblingByTagName() )
758         {
759           if ( aLstItem.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_ID" ) ).equals( aListId ) )
760             foundListItem = aLstItem;
761         }
762
763         if ( foundListItem != NULL )
764         {
765           //  The appropriate list of values is found: store the list name
766           aListName = foundListItem.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_NAME" ) );
767           //  Iteration through the list of values
768           LDOM_Element aListItemValue = foundListItem.GetChildByTagName( DDS_Dictionary::KeyWord( "VALUE_LIST_VALUE" ) );
769           while ( aListItemValue != NULL )
770           {
771             // read value ID
772             TCollection_AsciiString aListValueID = aListItemValue.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_VALUEID" ) );
773             if ( aListValueID.IsIntegerValue() )
774             {
775               //  Read the text in the element "value"
776               //LDOM_Text aListItemTxt = (const LDOM_Text&)aListItemValue.getFirstChild();
777               LDOM_Node aNode = aListItemValue.getFirstChild();
778               const LDOM_Text& aText = (const LDOM_Text&) aNode;
779               LDOM_Text aListItemTxt(aText);
780               if ( !aListItemTxt.isNull() )
781               {
782                 // adding ID and text value to sequence
783                 aSeqOfValueID.Append( aListValueID.IntegerValue() );
784                 aSeqOfValue.Append( aListItemTxt.getData() );
785                 // adding icon file name (optional) to sequence
786                 TCollection_ExtendedString aListValueIcon = aListItemValue.getAttribute( DDS_Dictionary::KeyWord( "VALUE_LIST_VALUEICON" ) );
787                 aSeqOfValueIconName.Append( aListValueIcon );
788               }
789               aListItemValue = aListItemValue.GetSiblingByTagName();
790             }
791           }
792         }
793       }
794     }
795   }
796
797   // Quantity::Description record as the only child of that tag name
798   LDOM_Element aDescr = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "DESCR" ) );
799   if ( !aDescr.isNull() )
800   {
801     // short description (#PCDATA)*
802     LDOM_Element aShDescr = aDescr.GetChildByTagName( DDS_Dictionary::KeyWord( "SHORT_D" ) );
803     if ( !aShDescr.isNull() )
804     {
805       // text is always a sub-node of element, containing it
806       //LDOM_Text aShDescrTxt = (const LDOM_Text&)aShDescr.getFirstChild();
807       LDOM_Node aNode = aShDescr.getFirstChild();
808       const LDOM_Text& aText = (const LDOM_Text&) aNode;
809       LDOM_Text aShDescrTxt(aText);
810       if ( !aShDescrTxt.isNull() )
811         aShortD = aShDescrTxt.getData();
812     }
813
814     // long description (#PCDATA)*
815     LDOM_Element aLDescr = aDescr.GetChildByTagName( DDS_Dictionary::KeyWord( "LONG_D" ) );
816     if ( !aLDescr.isNull() )
817     {
818       // text is always a sub-node of element, containing it
819       //LDOM_Text aLDescrTxt = (const LDOM_Text&)aLDescr.getFirstChild();
820       LDOM_Node aNode = aLDescr.getFirstChild();
821       const LDOM_Text& aText = (const LDOM_Text&) aNode;
822       LDOM_Text aLDescrTxt(aText);
823       if ( !aLDescrTxt.isNull() )
824         aLongD = aLDescrTxt.getData();
825     }
826   }
827
828   // Quantity::Options
829   LDOM_Element anOpt = theDatum.GetChildByTagName( DDS_Dictionary::KeyWord( "OPTIONS" ) );
830   if ( !anOpt.isNull() )
831   {
832     LDOM_NodeList anOptions = anOpt.GetAttributesList();//anOpt.getElementsByTagName( DDS_Dictionary::KeyWord( "OPTION" ) );
833     for ( Standard_Integer oi = 0; oi < anOptions.getLength(); oi++ )
834     {
835       LDOM_Node node = anOptions.item( oi );
836       LDOM_Node::NodeType t = node.getNodeType();
837
838       TCollection_AsciiString name;
839       TCollection_ExtendedString value;
840
841       if( t==LDOM_Node::ELEMENT_NODE )
842       {
843         const LDOM_Element& elem = ( const LDOM_Element& )node;
844         name = elem.getAttribute( DDS_Dictionary::KeyWord( "OPTION_NAME" ) );
845         
846         const LDOM_Node aNode = elem.getFirstChild();
847         LDOM_Text anOptTxt( (const LDOM_Text&)(aNode) );
848         if ( !anOptTxt.isNull() )
849           value = anOptTxt.getData();
850       }
851       else if( t==LDOM_Node::ATTRIBUTE_NODE )
852       {
853         const LDOM_Attr& attr = ( const LDOM_Attr& )node;
854         name = ( Standard_CString )attr.getName().GetString();
855         LDOMString v = attr.getValue();
856         if( v.Type()==LDOMBasicString::LDOM_Integer )
857         {
858                 Standard_Integer ival;
859                 v.GetInteger( ival );
860                 value = TCollection_ExtendedString( ival );
861         }
862         else
863                 value = ( Standard_CString )v.GetString();
864       }
865       else
866         continue;
867
868       if ( !name.IsEmpty() && value.Length() && !myOptions.IsBound( name ) )
869         myOptions.Bind( name, value );
870     }
871   }
872
873   NCollection_DataMap<UnitSystem, Handle(Units_Dimensions)> aDimMap;
874
875   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator it( myUnitData ); it.More(); it.Next() )
876   {
877     UnitData& anUnitData = it.ChangeValue();
878
879     // check units
880     anUnitData.myZero  = 0.;
881     anUnitData.myScale = 1.;
882     try {
883       Standard_CString aUnitDataStr;
884       aUnitDataStr = (Standard_CString)anUnitData.myUnits.ToCString();
885       if ( anUnitData.myUnits.ToCString()[0] && strcmp( anUnitData.myUnits.ToCString(), "%" ) )
886       {
887         Handle(Units_Dimensions) aDim;
888         anUnitData.myZero  = UnitsAPI::AnyToSI( 0.0, aUnitDataStr, aDim );
889         anUnitData.myScale = UnitsAPI::AnyToSI( 1.0, aUnitDataStr, aDim ) - anUnitData.myZero;
890         UnitsAPI::AnyFromSI( 1.0, aUnitDataStr );
891         if ( !aDimMap.IsBound( it.Key() ) )
892           aDimMap.Bind( it.Key(), aDim );
893       }
894       else if ( anUnitData.myUnits.ToCString()[0] ) // treat '%' as unit with scale 100
895         anUnitData.myScale = 0.01;
896     }
897           catch( Standard_Failure ) {
898       anUnitData.myUnits.Clear();
899     }
900
901     Handle(Units_Dimensions) aPrev;
902     Standard_Boolean aStatus = Standard_True;
903     for ( NCollection_DataMap<UnitSystem, Handle(Units_Dimensions)>::Iterator itr( aDimMap );
904           itr.More() && aStatus; itr.Next() )
905     {
906       if ( itr.Value().IsNull() )
907         continue;
908
909       if ( aPrev.IsNull() )
910         aPrev = itr.Value();
911
912       aStatus = aPrev->IsEqual( itr.Value() );
913     }
914
915     if ( !aStatus )
916       printf( "Error in DataDictionary: Different dimensions for %s item", theID.ToCString() );
917   }
918
919   myId                = theID;
920   myType              = aEnumType;
921   myWarnLevel         = aWrongValue;
922   myLabel             = aLabel.ToCString();
923   myFilter            = aFilter.ToCString();
924   myLongDescr         = aLongD.ToCString();
925   myShortDescr        = aShortD.ToCString();
926   myMin               = aRealMinV;
927   myMax               = aRealMaxV;
928   myDefValue          = aRealDefV;
929   myDefString         = aDefV.ToCString();
930   myRequired          = aRequired.ToCString();
931   myListName          = aListName.ToCString();
932   myMinZoom           = aMinZoom;
933   myMaxZoom           = aMaxZoom;
934   myZoomOrder         = aZoomOrder;
935
936   // prepare formats
937   PrepareFormats( aFormat );
938
939   const Standard_Integer aLength = aSeqOfValue.Length();
940   if ( aLength > 0 )
941   {
942     myListRef      = new TColStd_HArray1OfExtendedString( 1, aLength );
943     myListRefID    = new TColStd_HArray1OfInteger( 1, aLength );
944     myListRefIcons = new TColStd_HArray1OfExtendedString( 1, aLength );
945     for ( Standard_Integer i = aLength; i > 0; i-- )
946     {
947       myListRef->ChangeValue( i ) = aSeqOfValue.Value( i );
948       myListRefID->ChangeValue( i ) = aSeqOfValueID.Value( i );
949       myListRefIcons->ChangeValue( i ) = aSeqOfValueIconName.Value( i );
950     }
951   }
952
953   if ( myType == List && myDefString == "" && !myListRef.IsNull() && myListRef->Length() > 0 )
954     myDefString = myListRef->Value( myListRef->Lower() );
955 }
956
957 /*!
958   \brief Restore default formats for all the units systems.
959 */
960 void DDS_DicItem::GetDefaultFormat()
961 {
962   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator it( myUnitData ); it.More(); it.Next() )
963   {
964     UnitData& anUnitData = it.ChangeValue();
965
966     switch ( myType )
967     {
968     case Integer:
969       anUnitData.myFormat = "%d";
970       break;
971     case Float:
972       anUnitData.myFormat = "%g";
973       break;
974     case String:
975     default:
976       anUnitData.myFormat.Clear();
977       break;;
978     }
979   }
980 }
981
982 /*!
983   \brief Get format for the string.
984   \param theFlags format flags
985   \param theWidth field width
986   \param thePrecision precision
987   \param theTypePrefix type prefix
988   \param theFormat returning format string
989 */
990 void DDS_DicItem::GetStringFormat( const TCollection_AsciiString& theFlags,
991                                    const TCollection_AsciiString& theWidth,
992                                    const TCollection_AsciiString& thePrecision,
993                                    const TCollection_AsciiString& theTypePrefix,
994                                    TCollection_AsciiString& theFormat )
995 {
996   theFormat = "%";
997   theFormat += theFlags;
998   theFormat += theWidth;
999
1000   if ( !thePrecision.IsEmpty() ) 
1001   {
1002     theFormat += ".";
1003     theFormat += thePrecision;
1004   }
1005
1006   theFormat += theTypePrefix;
1007   theFormat += "s";
1008 }
1009
1010 /*!
1011   \brief Get format for the integer.
1012   \param theFlags format flags
1013   \param theWidth field width
1014   \param thePrecision precision
1015   \param theTypePrefix type prefix
1016   \param theType integer value type 
1017   \param theFormat returning format string
1018 */
1019 void DDS_DicItem::GetIntegerFormat( const TCollection_AsciiString& theFlags,
1020                                     const TCollection_AsciiString& theWidth,
1021                                     const TCollection_AsciiString& thePrecision,
1022                                     const TCollection_AsciiString& theTypePrefix,
1023                                     const Standard_Character theType,
1024                                     TCollection_AsciiString& theFormat )
1025 {
1026   Standard_Integer aPrecision = 0;
1027   if ( !thePrecision.IsEmpty() )
1028     aPrecision = thePrecision.IntegerValue();
1029   Standard_Integer aWidth = 0;
1030
1031   if ( !theWidth.IsEmpty() )
1032     aWidth = theWidth.IntegerValue();
1033
1034   if ( !thePrecision.IsEmpty() && aPrecision < 0 )
1035   {
1036     // possible value 0.1 will be 10.0
1037     aWidth -= aPrecision;
1038     aPrecision = 0;
1039   }
1040
1041   if ( !thePrecision.IsEmpty() && aPrecision > ( aWidth - 2 ) )
1042     aWidth = aPrecision + 2;
1043
1044   theFormat = "%";
1045
1046   theFormat += theFlags;
1047   if ( !theWidth.IsEmpty() )
1048     theFormat += aWidth;
1049
1050   theFormat += theTypePrefix;
1051   theFormat += theType;
1052 }
1053
1054 /*!
1055   \brief Returns format for the float.
1056   \param theFlags format flags
1057   \param theWidth field width
1058   \param thePrecision precision
1059   \param theTypePrefix type prefix
1060   \param theType floating point value type 
1061   \param theFormat returning format string
1062 */
1063 void DDS_DicItem::GetFloatFormat( const TCollection_AsciiString& theFlags,
1064                                   const TCollection_AsciiString& theWidth,
1065                                   const TCollection_AsciiString& thePrecision,
1066                                   const TCollection_AsciiString& theTypePrefix,
1067                                   const Standard_Character theType,
1068                                   TCollection_AsciiString& theFormat )
1069 {
1070   Standard_Integer aPrecision = 0;
1071   if ( !thePrecision.IsEmpty() )
1072     aPrecision = thePrecision.IntegerValue();
1073   Standard_Integer aWidth = 0;
1074
1075   if (!theWidth.IsEmpty() )
1076     aWidth = theWidth.IntegerValue();
1077
1078   if (!thePrecision.IsEmpty() && aPrecision < 0 )
1079   {
1080     // possible value 0.1 will be 10.0
1081     aWidth -= aPrecision;
1082     aPrecision = 0;
1083   }
1084
1085   if ( !thePrecision.IsEmpty() && aPrecision > ( aWidth - 2 ) )
1086   {
1087     aWidth = aPrecision + 2;
1088   }
1089
1090   theFormat = "%";
1091   theFormat += theFlags;
1092
1093   if ( !theWidth.IsEmpty() ) 
1094     theFormat += aWidth;
1095
1096   if ( !thePrecision.IsEmpty() ) 
1097   {
1098     theFormat += ".";
1099     theFormat += aPrecision;
1100   }
1101
1102   theFormat += theTypePrefix;
1103   theFormat += theType;
1104 }
1105
1106 /*!
1107   \brief Prepare formats for all units systems.
1108   \param theFormat format string
1109 */
1110 void DDS_DicItem::PrepareFormats( const TCollection_AsciiString& theFormat )
1111 {
1112   for ( NCollection_DataMap<UnitSystem, UnitData>::Iterator it( myUnitData ); it.More(); it.Next() )
1113   {
1114     UnitData& anUnitData = it.ChangeValue();
1115
1116     anUnitData.myFormat = theFormat;
1117     anUnitData.myPrecision = 0;
1118   }
1119
1120   TCollection_AsciiString aPrecisionStr;
1121   if ( theFormat.IsEmpty() && myType == List )
1122     return;
1123
1124   // checking % presenting
1125   if ( *theFormat.ToCString() != '%' )
1126   {
1127     GetDefaultFormat();
1128     return;
1129   }
1130
1131   TCollection_AsciiString aStr = ( theFormat.ToCString() + 1 );
1132   Standard_Character aType = aStr.Value( aStr.Length() );
1133
1134   if ( ( aType != 's' && myType == String ) ||
1135        ( aType != 'd' && myType == Integer ) ||
1136        ( aType != 'f' && aType != 'g' && aType != 'e' && aType != 'G' && aType != 'E' && myType == Float ) )
1137   {
1138     GetDefaultFormat();
1139     return;
1140   }
1141
1142   // removing type character
1143   aStr.Trunc( aStr.Length() - 1 );
1144
1145   TCollection_AsciiString aFlags;
1146   while ( !aStr.IsEmpty() && aStr.Value( 1 ) != '.' && ( aStr.Value( 1 ) < '0' || aStr.Value( 1 ) > '9' ) )
1147   {
1148     aFlags = aFlags + aStr.Value( 1 );
1149     aStr.Remove( 1 );
1150   }
1151
1152   Standard_Integer aPos = 1;
1153   while ( aPos <= aStr.Length() && ( aStr.Value( aPos ) == '.' ||
1154           ( aStr.Value( aPos ) >= '0' && aStr.Value( aPos ) <= '9' ) ) )
1155     aPos++;
1156
1157   TCollection_AsciiString aTypePrefix;
1158   if ( aPos <= aStr.Length() )
1159   {
1160     aTypePrefix = aStr.SubString( aPos, aStr.Length() );
1161     aStr.Trunc( aPos - 1 );
1162   }
1163
1164   Standard_Integer aBasePrecision = 0;
1165
1166   // taking width and precision
1167   TCollection_AsciiString aPrecision;
1168
1169   aPos = aStr.Search( "." );
1170   if ( aPos >= 0 ) 
1171   {
1172     // aPrecision is defined
1173     aPrecision = aStr.Split( aPos );
1174     aStr.Remove( aStr.Length() );
1175     if ( !aPrecision.IsEmpty() )
1176     {
1177       if ( !aPrecision.IsIntegerValue() ) 
1178       { 
1179         GetDefaultFormat();
1180         return;
1181       }
1182       else
1183       {
1184         aPrecisionStr  = aPrecision;
1185         aBasePrecision = aPrecision.IntegerValue();
1186       }
1187     }
1188   }
1189
1190   if ( !aStr.IsEmpty() && !aStr.IsIntegerValue() )
1191   {
1192     GetDefaultFormat();
1193     return;
1194   }
1195
1196   NCollection_DataMap<UnitSystem, UnitData>::Iterator itr;
1197
1198   switch ( myType )
1199   {
1200   case String:
1201     for ( itr.Initialize( myUnitData ); itr.More(); itr.Next() )
1202     {
1203       if ( aType != 'f' && aType != 'g' && aType != 'e' && aType != 'G' && aType != 'E' )
1204         GetStringFormat( aFlags, aStr, aPrecisionStr, aTypePrefix, itr.ChangeValue().myFormat );
1205     }
1206     break;
1207   case Float:
1208   case Integer:
1209     for ( itr.Initialize( myUnitData ); itr.More(); itr.Next() )
1210     {
1211       UnitData& anUnitData = itr.ChangeValue();
1212       Standard_Integer aAmendment =
1213         (Standard_Integer)log10( 10.0 / DDS_Dictionary::FromSI( 10.0, anUnitData.myUnits.ToCString() ) );
1214       anUnitData.myPrecision = aBasePrecision + aAmendment;
1215       aPrecisionStr = TCollection_AsciiString( anUnitData.myPrecision );
1216
1217       // create a formats
1218       if ( myType == Integer )
1219         GetIntegerFormat( aFlags, aStr, aPrecisionStr, aTypePrefix, aType, anUnitData.myFormat );
1220       else
1221         GetFloatFormat( aFlags, aStr, aPrecisionStr, aTypePrefix, aType, anUnitData.myFormat );
1222     }
1223     break;
1224   default:;
1225     GetDefaultFormat();
1226     break;
1227   }
1228 }
1229
1230 /*!
1231   \brief Split the string \a theStr separated by spaces.
1232   \param theStr source string
1233   \param aRes returning  substrings array
1234 */
1235 void DDS_DicItem::Split( const TCollection_AsciiString& theStr, Handle(TColStd_HArray1OfExtendedString)& aRes )
1236 {
1237   aRes.Nullify();
1238
1239   if ( theStr.Length() > 0 )
1240   {
1241     TCollection_AsciiString aStr = theStr;
1242     TColStd_SequenceOfAsciiString aSeq;
1243     Standard_Integer anIndex = aStr.SearchFromEnd( (Standard_CString)" " );
1244     while( anIndex > 1 )
1245     {
1246       TCollection_AsciiString tmpStr = aStr.Split( anIndex - 1 );
1247       tmpStr.RemoveAll( ( Standard_Character )' ' );
1248       if ( tmpStr.Length() > 0 )
1249         aSeq.Append( tmpStr );
1250       anIndex = aStr.SearchFromEnd( (Standard_CString)" " );
1251     }
1252
1253     aStr.RemoveAll( ( Standard_Character )' ' );
1254     if ( aStr.Length() > 0 )
1255       aSeq.Append( aStr );
1256
1257     if ( aSeq.Length() > 0 )
1258     {
1259       aRes = new TColStd_HArray1OfExtendedString( 1, aSeq.Length() );
1260       for ( int i = 1, n = aSeq.Length(); i <= n; i++ )
1261         aRes->ChangeValue( i ) = aSeq( i );
1262     }
1263   }
1264 }
1265
1266 /*!
1267   \brief Get units structure for specified units system \a sys.
1268   \param sys units system
1269   \return units system information structure
1270 */
1271 DDS_DicItem::UnitData* DDS_DicItem::GetUnitData( const UnitSystem& sys ) const
1272 {
1273   UnitData* unit = 0;
1274
1275   if ( myUnitData.IsBound( sys ) )
1276     unit = (UnitData*)&myUnitData.Find( sys );
1277
1278   return unit;
1279 }
1280
1281 /*!
1282   \brief Get the active units system.
1283   \return active units system
1284 */
1285 DDS_DicItem::UnitSystem DDS_DicItem::GetActiveUnitSystem() const
1286 {
1287   UnitSystem aSystem;
1288   Handle(DDS_DicGroup) aComponent = Handle(DDS_DicGroup)::DownCast(myComponent);
1289   if ( !aComponent.IsNull() )
1290     aSystem = aComponent->GetActiveUnitSystem();
1291   return aSystem;
1292 }