1 /*
2  * Copyright (c) 2011-2021, The DART development contributors
3  * All rights reserved.
4  *
5  * The list of contributors can be found at:
6  *   https://github.com/dartsim/dart/blob/master/LICENSE
7  *
8  * This file is provided under the following "BSD-style" License:
9  *   Redistribution and use in source and binary forms, with or
10  *   without modification, are permitted provided that the following
11  *   conditions are met:
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *   * Redistributions in binary form must reproduce the above
15  *     copyright notice, this list of conditions and the following
16  *     disclaimer in the documentation and/or other materials provided
17  *     with the distribution.
18  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19  *   CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20  *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  *   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  *   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23  *   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26  *   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  *   AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  *   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  *   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  *   POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #ifndef DART_COMMON_DETAIL_NAMEMANAGER_HPP_
34 #define DART_COMMON_DETAIL_NAMEMANAGER_HPP_
35 
36 #include <cassert>
37 #include <sstream>
38 #include "dart/common/Console.hpp"
39 #include "dart/common/NameManager.hpp"
40 
41 namespace dart {
42 namespace common {
43 
44 //==============================================================================
45 template <class T>
NameManager(const std::string & _managerName,const std::string & _defaultName)46 NameManager<T>::NameManager(
47     const std::string& _managerName, const std::string& _defaultName)
48   : mManagerName(_managerName),
49     mDefaultName(_defaultName),
50     mNameBeforeNumber(true),
51     mPrefix(""),
52     mInfix("("),
53     mAffix(")")
54 {
55   // Do nothing
56 }
57 
58 //==============================================================================
59 template <class T>
setPattern(const std::string & _newPattern)60 bool NameManager<T>::setPattern(const std::string& _newPattern)
61 {
62   std::size_t name_start = _newPattern.find("%s");
63   std::size_t number_start = _newPattern.find("%d");
64 
65   if (name_start == std::string::npos || number_start == std::string::npos)
66     return false;
67 
68   if (name_start < number_start)
69     mNameBeforeNumber = true;
70   else
71     mNameBeforeNumber = false;
72 
73   std::size_t prefix_end = std::min(name_start, number_start);
74   std::size_t infix_end = std::max(name_start, number_start);
75 
76   mPrefix = _newPattern.substr(0, prefix_end);
77   mInfix = _newPattern.substr(prefix_end + 2, infix_end - prefix_end - 2);
78   mAffix = _newPattern.substr(infix_end + 2);
79 
80   return true;
81 }
82 
83 //==============================================================================
84 template <class T>
issueNewName(const std::string & _name) const85 std::string NameManager<T>::issueNewName(const std::string& _name) const
86 {
87   if (!hasName(_name))
88     return _name;
89 
90   int count = 1;
91   std::string newName;
92   do
93   {
94     std::stringstream ss;
95     if (mNameBeforeNumber)
96       ss << mPrefix << _name << mInfix << count++ << mAffix;
97     else
98       ss << mPrefix << count++ << mInfix << _name << mAffix;
99     newName = ss.str();
100   } while (hasName(newName));
101 
102   dtmsg << "[NameManager::issueNewName] (" << mManagerName << ") The name ["
103         << _name << "] is a duplicate, so it has been renamed to [" << newName
104         << "]\n";
105 
106   return newName;
107 }
108 
109 //==============================================================================
110 template <class T>
issueNewNameAndAdd(const std::string & _name,const T & _obj)111 std::string NameManager<T>::issueNewNameAndAdd(
112     const std::string& _name, const T& _obj)
113 {
114   const std::string& checkEmpty = _name.empty() ? mDefaultName : _name;
115   const std::string& newName = issueNewName(checkEmpty);
116   addName(newName, _obj);
117 
118   return newName;
119 }
120 
121 //==============================================================================
122 template <class T>
addName(const std::string & _name,const T & _obj)123 bool NameManager<T>::addName(const std::string& _name, const T& _obj)
124 {
125   if (_name.empty())
126   {
127     dtwarn << "[NameManager::addName] (" << mManagerName
128            << ") Empty name is not allowed!\n";
129     return false;
130   }
131 
132   if (hasName(_name))
133   {
134     dtwarn << "[NameManager::addName] (" << mManagerName << ") The name ["
135            << _name << "] already exists!\n";
136     return false;
137   }
138 
139   mMap.insert(std::pair<std::string, T>(_name, _obj));
140   mReverseMap.insert(std::pair<T, std::string>(_obj, _name));
141 
142   assert(mReverseMap.size() == mMap.size());
143 
144   return true;
145 }
146 
147 //==============================================================================
148 template <class T>
removeName(const std::string & _name)149 bool NameManager<T>::removeName(const std::string& _name)
150 {
151   assert(mReverseMap.size() == mMap.size());
152 
153   typename std::map<std::string, T>::iterator it = mMap.find(_name);
154 
155   if (it == mMap.end())
156     return false;
157 
158   typename std::map<T, std::string>::iterator rit
159       = mReverseMap.find(it->second);
160 
161   if (rit != mReverseMap.end())
162     mReverseMap.erase(rit);
163 
164   mMap.erase(it);
165 
166   return true;
167 }
168 
169 //==============================================================================
170 template <class T>
removeObject(const T & _obj)171 bool NameManager<T>::removeObject(const T& _obj)
172 {
173   assert(mReverseMap.size() == mMap.size());
174 
175   typename std::map<T, std::string>::iterator rit = mReverseMap.find(_obj);
176 
177   if (rit == mReverseMap.end())
178     return false;
179 
180   typename std::map<std::string, T>::iterator it = mMap.find(rit->second);
181   if (it != mMap.end())
182     mMap.erase(it);
183 
184   mReverseMap.erase(rit);
185 
186   return true;
187 }
188 
189 //==============================================================================
190 template <class T>
removeEntries(const std::string & _name,const T & _obj)191 void NameManager<T>::removeEntries(const std::string& _name, const T& _obj)
192 {
193   removeObject(_obj);
194   removeName(_name);
195 }
196 
197 //==============================================================================
198 template <class T>
clear()199 void NameManager<T>::clear()
200 {
201   mMap.clear();
202   mReverseMap.clear();
203 }
204 
205 //==============================================================================
206 template <class T>
hasName(const std::string & _name) const207 bool NameManager<T>::hasName(const std::string& _name) const
208 {
209   return (mMap.find(_name) != mMap.end());
210 }
211 
212 //==============================================================================
213 template <class T>
hasObject(const T & _obj) const214 bool NameManager<T>::hasObject(const T& _obj) const
215 {
216   return (mReverseMap.find(_obj) != mReverseMap.end());
217 }
218 
219 //==============================================================================
220 template <class T>
getCount() const221 std::size_t NameManager<T>::getCount() const
222 {
223   return mMap.size();
224 }
225 
226 //==============================================================================
227 template <class T>
getObject(const std::string & _name) const228 T NameManager<T>::getObject(const std::string& _name) const
229 {
230   typename std::map<std::string, T>::const_iterator result = mMap.find(_name);
231 
232   if (result != mMap.end())
233     return result->second;
234   else
235     return nullptr;
236 }
237 
238 //==============================================================================
239 template <class T>
getName(const T & _obj) const240 std::string NameManager<T>::getName(const T& _obj) const
241 {
242   assert(mReverseMap.size() == mMap.size());
243 
244   typename std::map<T, std::string>::const_iterator result
245       = mReverseMap.find(_obj);
246 
247   if (result != mReverseMap.end())
248     return result->second;
249   else
250     return "";
251 }
252 
253 //==============================================================================
254 template <class T>
changeObjectName(const T & _obj,const std::string & _newName)255 std::string NameManager<T>::changeObjectName(
256     const T& _obj, const std::string& _newName)
257 {
258   assert(mReverseMap.size() == mMap.size());
259 
260   typename std::map<T, std::string>::iterator rit = mReverseMap.find(_obj);
261   if (rit == mReverseMap.end())
262     return _newName;
263 
264   if (rit->second == _newName)
265     return rit->second;
266 
267   removeName(rit->second);
268   return issueNewNameAndAdd(_newName, _obj);
269 }
270 
271 //==============================================================================
272 template <class T>
setDefaultName(const std::string & _defaultName)273 void NameManager<T>::setDefaultName(const std::string& _defaultName)
274 {
275   mDefaultName = _defaultName;
276 }
277 
278 //==============================================================================
279 template <class T>
getDefaultName() const280 const std::string& NameManager<T>::getDefaultName() const
281 {
282   return mDefaultName;
283 }
284 
285 //==============================================================================
286 template <class T>
setManagerName(const std::string & _managerName)287 void NameManager<T>::setManagerName(const std::string& _managerName)
288 {
289   mManagerName = _managerName;
290 }
291 
292 //==============================================================================
293 template <class T>
getManagerName() const294 const std::string& NameManager<T>::getManagerName() const
295 {
296   return mManagerName;
297 }
298 
299 } // namespace common
300 } // namespace dart
301 
302 #endif // DART_COMMON_DETAIL_NAMEMANAGER_HPP_
303