ObjectMap.h

Go to the documentation of this file.
00001 /***************************************************************************
00002  *
00003  * Copyright (C) 2009-2011 Cassio Neri Moreira
00004  *
00005  * This file is part of the KeyValue library.
00006  *
00007  * The KeyValue library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License as published
00009  * by the Free Software Foundation, either version 3 of the License, or (at
00010  * your option) any later version.
00011  *
00012  * The KeyValue library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
00015  * Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License along
00018  * with KeyValue. If not, see <http://www.gnu.org/licenses/>.
00019  *
00020  * If you modify this library, or any covered work, by linking or combining
00021  * it with Excel (or a modified version of that program), containing parts
00022  * covered by the terms of End-User License Agreement for Microsoft
00023  * Software, the licensors of KeyValue grant you additional permission to
00024  * convey the resulting work.
00025  *
00026  **************************************************************************/
00027 
00035 #ifndef KEYVALUE_KEY_MAP_OBJECTMAP_H_
00036 #define KEYVALUE_KEY_MAP_OBJECTMAP_H_
00037 
00038 #include <boost/utility.hpp>
00039 
00040 #include "keyvalue/extern/String.h"
00041 #include "keyvalue/frontend/LexicalToolKit.h"
00042 #include "keyvalue/mngt/BuilderFrom.h"
00043 #include "keyvalue/mngt/DataSet.h"
00044 #include "keyvalue/mngt/ProcessorMngr.h"
00045 #include "keyvalue/mngt/Repository.h"
00046 #include "keyvalue/sys/exception/Exception.h"
00047 #include "keyvalue/sys/exception/KV_ASSERT.h"
00048 #include "keyvalue/util/Global.h"
00049 #include "keyvalue/value/Variant.h"
00050 
00051 namespace keyvalue {
00052 namespace key {
00053 
00074 template <typename ObjectType>
00075 class ObjectMap :
00076 
00077   private ::boost::noncopyable {
00078 
00079 public:
00080 
00081   typedef typename value::PtrTraits<ObjectType>::Type_ OutputType_;
00082 
00090   OutputType_
00091   map(const value::Variant& variant) const;
00092 
00093 private:
00094 
00100   virtual string
00101   getName() const = 0;
00102 
00103 }; // class ObjectMap
00104 
00105 /*--------------------------------------------------------------------------
00106  * map()
00107  *------------------------------------------------------------------------*/
00108 
00109 template <typename ObjectType>
00110 typename ObjectMap<ObjectType>::OutputType_
00111 ObjectMap<ObjectType>::map(const value::Variant& variant) const {
00112 
00113   string name;
00114 
00115   // Try to get object by its name.
00116 
00117   if (variant.is<string>(frontend::LexicalToolKit::input)) {
00118 
00119     name = variant.get<string>(frontend::LexicalToolKit::input);
00120 
00121     try {
00122       shared_ptr<const DataSet>
00123         data(util::Global<Repository>::get()->getDataSet(name));
00124       return data->build<ObjectType>();
00125     }
00126 
00127     catch(Repository::NotFound& error) {
00128       if (error.getName() != name)
00129         throw;
00130     }
00131   }
00132 
00133   // Try to build directly from variant.
00134 
00135   const AbstractBuilder* const builder =
00136       util::Global<ProcessorMngr>::get()->findBuilder(typeid(ObjectType));
00137 
00138   if (!builder) {
00139     if (name.empty())
00140       throw RuntimeError() & "No builder can build object expected by key "
00141         "'" & getName() & "'. (Value is '" & variant & "'.)";
00142     else
00143       throw RuntimeError() & "No object named '" & name & "' exists and no "
00144         "builder can build object expected by key '" & getName() & "' from "
00145         "this string.";
00146   }
00147 
00148   typedef BuilderFrom<ObjectType, value::Variant> const BuilderFromVariant;
00149 
00150   const BuilderFromVariant* bfv(dynamic_cast<BuilderFromVariant*>(builder));
00151 
00152   if (!bfv)
00153     throw RuntimeError() & "Builder '" & builder->getName() & "' needs a "
00154       "data set. It cannot satisfy key '" & getName() & "' and build from "
00155       "input '" & variant & "'.";
00156 
00157   return bfv->getObject(variant);
00158 }
00159 
00160 } // namespace key
00161 } // namespace keyvalue
00162 
00163 #endif // KEYVALUE_KEY_MAP_OBJECTMAP_H_