All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
UnitsOfMeasureManager.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2008 National Institute For Space Research (INPE) - Brazil.
2 
3  This file is part of the TerraLib - a Framework for building GIS enabled applications.
4 
5  TerraLib is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published by
7  the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  TerraLib is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with TerraLib. See COPYING. If not, write to
17  TerraLib Team at <terralib-team@terralib.org>.
18  */
19 
20 /*!
21  \file terralib/common/UnitsOfMeasureManager.cpp
22 
23  \brief A singleton class for dealing with units-of-measurement.
24 */
25 
26 // TerraLib
27 #include "Exception.h"
28 #include "PlatformUtils.h"
29 #include "STLUtils.h"
30 #include "StringUtils.h"
31 #include "Translator.h"
32 #include "UnitOfMeasure.h"
33 #include "UnitsOfMeasureManager.h"
34 
35 // STL
36 #include <algorithm>
37 #include <cassert>
38 
39 // Boost
40 #include <boost/algorithm/string.hpp>
41 #include <boost/foreach.hpp>
42 #include <boost/format.hpp>
43 #include <boost/property_tree/json_parser.hpp>
44 #include <boost/property_tree/ptree.hpp>
45 
47 {}
48 
50 {
51  clear();
52 }
53 
55 {
56  m_uoms.clear();
57  m_uomsIdxByName.clear();
58 }
59 
61 {
62  assert(uom.get());
63 
64  const_iterator it = m_uoms.find(uom->getId());
65  if(it != m_uoms.end())
66  return;
67 
68  m_uoms.insert(std::pair<unsigned int, UnitOfMeasurePtr>(uom->getId(),uom));
69 
70  std::string upstr = boost::to_upper_copy(uom->getName());
71  m_uomsIdxByName.insert(std::pair<std::string, unsigned int>(upstr,uom->getId()));
72 }
73 
74 void te::common::UnitsOfMeasureManager::insert(UnitOfMeasurePtr& uom, const std::vector<std::string>& alternativeNames)
75 {
76  insert(uom);
77 
78  for(std::size_t i=0; i<alternativeNames.size(); ++i)
79  {
80  std::string upstr = boost::to_upper_copy(alternativeNames[i]);
81  m_uomsIdxByName.insert(std::pair<std::string, unsigned int>(upstr,uom->getId()));
82  }
83 }
84 
86 {
87  assert(uom.get());
88 
89  iterator it = m_uoms.find(uom->getId());
90  if (it == m_uoms.end())
91  return;
92 
93  m_uoms.erase(it);
94 
95  for (std::map<std::string, unsigned int>::iterator itn = m_uomsIdxByName.begin(); itn != m_uomsIdxByName.end();)
96  {
97  if (itn->second == uom->getId())
98  m_uomsIdxByName.erase(itn++);
99  else
100  ++itn;
101  }
102 }
103 
106 {
107  const_iterator it = m_uoms.find(id);
108  if (it == m_uoms.end())
109  return UnitOfMeasurePtr();
110 
111  return it->second;
112 }
113 
115 te::common::UnitsOfMeasureManager::find(const std::string& name) const
116 {
117  std::string upstr = boost::to_upper_copy(name);
118 
119  std::map<std::string, unsigned int>::const_iterator it = m_uomsIdxByName.find(upstr);
120 
121  if(it != m_uomsIdxByName.end())
122  {
123  const_iterator it2 = m_uoms.find(it->second);
124  if (it2 != m_uoms.end())
125  return it2->second;
126  }
127 
128  return UnitOfMeasurePtr();
129 }
130 
132 te::common::UnitsOfMeasureManager::findBySymbol(const std::string& symbol) const
133 {
134  const_iterator it = m_uoms.begin();
135  while (it != m_uoms.end())
136  {
137  if (it->second->getSymbol() == symbol)
138  return it->second;
139  ++it;
140  }
141  return UnitOfMeasurePtr();
142 }
143 
144 void te::common::UnitsOfMeasureManager::getNames(UnitOfMeasurePtr& uom, std::vector<std::string>& names) const
145 {
146  std::map<std::string, unsigned int>::const_iterator it = m_uomsIdxByName.begin();
147  while (it != m_uomsIdxByName.end())
148  {
149  if (it->second == uom->getId())
150  names.push_back(it->first);
151  ++it;
152  }
153 }
154 
155 double te::common::UnitsOfMeasureManager::getConversion(const std::string& unitFromName, const std::string& unitToName) const
156 {
157  UnitOfMeasurePtr uFrom = this->find(unitFromName);
158  UnitOfMeasurePtr uTo = this->find(unitToName);
159 
160  if (uFrom->getType() != uTo->getType())
161  throw Exception(TE_TR("There is not conversion between units for different types of measures."));
162 
163  if (uFrom->getBaseUnitId() == uTo->getId()) // converting from derived to base
164  {
165  return (uFrom->getConversionValue());
166  }
167  else if (uTo->getBaseUnitId() == uFrom->getId()) // converting from base to derived
168  {
169  double a, b, c, d;
170 
171  uTo->getConversionFactors(a,b,c,d);
172  return ((b-d)/(c-a));
173  }
174  throw Exception(TE_TR("There is no known conversion."));
175 }
176 
177 bool te::common::UnitsOfMeasureManager::areConvertible(const std::string& unitFromName, const std::string& unitToName) const
178 {
179  UnitOfMeasurePtr uFrom = this->find(unitFromName);
180  UnitOfMeasurePtr uTo = this->find(unitToName);
181 
182  if (uFrom->getType() != uTo->getType())
183  return false;
184 
185  if ((uFrom->getBaseUnitId() == uTo->getId()) ||
186  (uTo->getBaseUnitId() == uFrom->getId()))
187  return true;
188 
189  return false;
190 }
191 
193 {
194  if(!m_uoms.empty())
195  throw Exception(TE_TR("The unit of measure manager is already initialized!"));
196 
197  std::string uom_file = FindInTerraLibPath("share/terralib/json/uom.json");
198 
199  if(uom_file.empty())
200  throw Exception(TE_TR("The unit of measure JSON file could not be found!"));
201 
202  boost::property_tree::ptree pt;
203 
204  boost::property_tree::json_parser::read_json(uom_file, pt);
205 
206  BOOST_FOREACH(boost::property_tree::ptree::value_type& v, pt.get_child("units"))
207  {
208  unsigned int id = v.second.get<unsigned int>("id");
209  std::string name = v.second.get<std::string>("name");
210  std::string symbol = v.second.get<std::string>("symbol");
211  std::string stype = v.second.get<std::string>("type");
212  std::string description = v.second.get<std::string>("description");
213  unsigned int targetUOM = v.second.get<unsigned int>("target_uom");
214  double a = v.second.get<double>("factor_a");
215  double b = v.second.get<double>("factor_b");
216  double c = v.second.get<double>("factor_c");
217  double d = v.second.get<double>("factor_d");
218 
219  MeasureType t = Length;
220 
221  if(stype == "length")
222  t = Length;
223  else if(stype == "area")
224  t = Area;
225  else if(stype == "volume")
226  t = Volume;
227  else if(stype == "angle")
228  t = Angle;
229  else if(stype == "scale")
230  t = Scale;
231  else if(stype == "time")
232  t = Time;
233  else if(stype == "speed")
234  t = Speed;
235  else
236  {
237  throw Exception((boost::format(TE_TR("Invalid unit of measure type: %1%!")) % stype).str());
238  }
239 
240  UnitOfMeasurePtr uom(new UnitOfMeasure(id, name, symbol, t, targetUOM, a, b, c, d, description));
241 
242  insert(uom);
243  }
244 }
245 
void remove(UnitOfMeasurePtr &uom)
Removes a unit of measure from the manager.
This file is a wrapper around platform specific include files.
void insert(UnitOfMeasurePtr &uom)
Inserts a new unit of measure to be managed.
void init()
It initializes the list of well kown units of measure.
TECOMMONEXPORT std::string FindInTerraLibPath(const std::string &p)
Returns the path relative to a directory or file in the context of TerraLib.
A singleton class for dealing with units-of-measure.
UnitOfMeasurePtr findBySymbol(const std::string &symbol) const
Returns a unit of measure identified by its symbol.
void clear()
Removes all units from the catalogue.
#define TE_TR(message)
It marks a string in order to get translated.
Definition: Translator.h:347
void getNames(UnitOfMeasurePtr &uom, std::vector< std::string > &names) const
Retrieves the alternative names for a unit of measure.
std::map< unsigned int, UnitOfMeasurePtr >::const_iterator const_iterator
mydialect insert("+", new te::da::BinaryOpEncoder("+"))
A class for representing a unit of measure.
double getConversion(const std::string &unitFromName, const std::string &unitToName) const
Calculates a multiplicative factor to convert from a given unit to its base unit and vice-versa...
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
Definition: Exception.h:58
This class is designed for dealing with multi-language text translation in TerraLib.
boost::shared_ptr< UnitOfMeasure > UnitOfMeasurePtr
MeasureType
Defines the possible types of unit of measurements.
Definition: Enums.h:76
A class to represent units of measure.
Definition: UnitOfMeasure.h:74
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
bool areConvertible(const std::string &unitFromName, const std::string &unitToName) const
Check if two units of measure are compatible.
Utility functions for dealing with strings.
UnitOfMeasurePtr find(unsigned int id) const
Returns a unit of measure identified by its identificaton.
UnitsOfMeasureManager()
It initializes the Singleton.
This file contains several utility functions for dealing with STL containers.
std::map< unsigned int, UnitOfMeasurePtr >::iterator iterator