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 "../core/translator/Translator.h"
32 #include "../core/utils/Platform.h"
33 #include "UnitOfMeasure.h"
34 #include "UnitsOfMeasureManager.h"
35 
36 // STL
37 #include <algorithm>
38 #include <cassert>
39 
40 // Boost
41 #include <boost/algorithm/string.hpp>
42 #include <boost/format.hpp>
43 #include <boost/property_tree/json_parser.hpp>
44 #include <boost/property_tree/ptree.hpp>
45 
47 
49 {
50  clear();
51 }
52 
54 {
55  m_uoms.clear();
56  m_uomsIdxByName.clear();
57 }
58 
60 {
61  assert(uom.get());
62 
63  const_iterator it = m_uoms.find(uom->getId());
64  if(it != m_uoms.end())
65  return;
66 
67  m_uoms.insert(std::pair<unsigned int, UnitOfMeasurePtr>(uom->getId(),uom));
68 
69  std::string upstr = boost::to_upper_copy(uom->getName());
70  m_uomsIdxByName.insert(std::pair<std::string, unsigned int>(upstr,uom->getId()));
71 }
72 
73 void te::common::UnitsOfMeasureManager::insert(UnitOfMeasurePtr& uom, const std::vector<std::string>& alternativeNames)
74 {
75  insert(uom);
76 
77  for(std::size_t i=0; i<alternativeNames.size(); ++i)
78  {
79  std::string upstr = boost::to_upper_copy(alternativeNames[i]);
80  m_uomsIdxByName.insert(std::pair<std::string, unsigned int>(upstr,uom->getId()));
81  }
82 }
83 
85 {
86  assert(uom.get());
87 
88  iterator it = m_uoms.find(uom->getId());
89  if (it == m_uoms.end())
90  return;
91 
92  m_uoms.erase(it);
93 
94  for (std::map<std::string, unsigned int>::iterator itn = m_uomsIdxByName.begin(); itn != m_uomsIdxByName.end();)
95  {
96  if (itn->second == uom->getId())
97  m_uomsIdxByName.erase(itn++);
98  else
99  ++itn;
100  }
101 }
102 
105 {
106  const_iterator it = m_uoms.find(id);
107  if (it == m_uoms.end())
108  return UnitOfMeasurePtr();
109 
110  return it->second;
111 }
112 
114 te::common::UnitsOfMeasureManager::find(const std::string& name) const
115 {
116  std::string upstr = boost::to_upper_copy(name);
117 
118  std::map<std::string, unsigned int>::const_iterator it = m_uomsIdxByName.find(upstr);
119 
120  if(it != m_uomsIdxByName.end())
121  {
122  const_iterator it2 = m_uoms.find(it->second);
123  if (it2 != m_uoms.end())
124  return it2->second;
125  }
126 
127  return UnitOfMeasurePtr();
128 }
129 
131 te::common::UnitsOfMeasureManager::findBySymbol(const std::string& symbol) const
132 {
133  const_iterator it = m_uoms.begin();
134  while (it != m_uoms.end())
135  {
136  if (it->second->getSymbol() == symbol)
137  return it->second;
138  ++it;
139  }
140  return UnitOfMeasurePtr();
141 }
142 
143 void te::common::UnitsOfMeasureManager::getNames(UnitOfMeasurePtr& uom, std::vector<std::string>& names) const
144 {
145  std::map<std::string, unsigned int>::const_iterator it = m_uomsIdxByName.begin();
146  while (it != m_uomsIdxByName.end())
147  {
148  if (it->second == uom->getId())
149  names.push_back(it->first);
150  ++it;
151  }
152 }
153 
154 double te::common::UnitsOfMeasureManager::getConversion(const std::string& unitFromName, const std::string& unitToName) const
155 {
156  UnitOfMeasurePtr uFrom = this->find(unitFromName);
157  UnitOfMeasurePtr uTo = this->find(unitToName);
158 
159  if (uFrom->getType() != uTo->getType())
160  throw Exception(TE_TR("There is not conversion between units for different types of measures."));
161 
162  if (uFrom->getBaseUnitId() == uTo->getId()) // converting from derived to base
163  {
164  return (uFrom->getConversionValue());
165  }
166  else if (uTo->getBaseUnitId() == uFrom->getId()) // converting from base to derived
167  {
168  double a, b, c, d;
169 
170  uTo->getConversionFactors(a,b,c,d);
171  return ((b-d)/(c-a));
172  }
173  throw Exception(TE_TR("There is no known conversion."));
174 }
175 
176 bool te::common::UnitsOfMeasureManager::areConvertible(const std::string& unitFromName, const std::string& unitToName) const
177 {
178  UnitOfMeasurePtr uFrom = this->find(unitFromName);
179  UnitOfMeasurePtr uTo = this->find(unitToName);
180 
181  if (uFrom->getType() != uTo->getType())
182  return false;
183 
184  if ((uFrom->getBaseUnitId() == uTo->getId()) ||
185  (uTo->getBaseUnitId() == uFrom->getId()))
186  return true;
187 
188  return false;
189 }
190 
192 {
193  if(!m_uoms.empty())
194  throw Exception(TE_TR("The unit of measure manager is already initialized!"));
195 
196  std::string uom_file = te::core::FindInTerraLibPath("share/terralib/json/uom.json");
197 
198  if(uom_file.empty())
199  throw Exception(TE_TR("The unit of measure JSON file could not be found!"));
200 
201  boost::property_tree::ptree pt;
202 
203  boost::property_tree::json_parser::read_json(uom_file, pt);
204 
205  for(boost::property_tree::ptree::value_type& v: pt.get_child("units"))
206  {
207  unsigned int id = v.second.get<unsigned int>("id");
208  std::string name = v.second.get<std::string>("name");
209  std::string symbol = v.second.get<std::string>("symbol");
210  std::string stype = v.second.get<std::string>("type");
211  std::string description = v.second.get<std::string>("description");
212  unsigned int targetUOM = v.second.get<unsigned int>("target_uom");
213  double a = v.second.get<double>("factor_a");
214  double b = v.second.get<double>("factor_b");
215  double c = v.second.get<double>("factor_c");
216  double d = v.second.get<double>("factor_d");
217 
218  MeasureType t = Length;
219 
220  if(stype == "length")
221  t = Length;
222  else if(stype == "area")
223  t = Area;
224  else if(stype == "volume")
225  t = Volume;
226  else if(stype == "angle")
227  t = Angle;
228  else if(stype == "scale")
229  t = Scale;
230  else if(stype == "time")
231  t = Time;
232  else if(stype == "speed")
233  t = Speed;
234  else
235  {
236  throw Exception((boost::format(TE_TR("Invalid unit of measure type: %1%!")) % stype).str());
237  }
238 
239  UnitOfMeasurePtr uom(new UnitOfMeasure(id, name, symbol, t, targetUOM, a, b, c, d, description));
240 
241  insert(uom);
242  }
243 }
245 {
246  bool initialized = !m_uoms.empty();
247 
248  return initialized;
249 }
250 
void remove(UnitOfMeasurePtr &uom)
Removes a unit of measure from the manager.
std::map< std::string, unsigned int > m_uomsIdxByName
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.
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:242
std::map< unsigned int, UnitOfMeasurePtr > m_uoms
int b
Definition: TsRtree.cpp:32
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
A class for representing a unit of measure.
static te::dt::DateTime d(2010, 8, 9, 15, 58, 39)
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. ...
boost::shared_ptr< UnitOfMeasure > UnitOfMeasurePtr
MeasureType
Defines the possible types of unit of measurements.
A class to represent units of measure.
Definition: UnitOfMeasure.h:74
TECOREEXPORT std::string FindInTerraLibPath(const std::string &path)
Returns the path relative to a directory or file in the context of 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.
This class is designed to declare objects to be thrown as exceptions by TerraLib. ...
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