IWORKContainerContext.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /*
00003  * This file is part of the libetonyek project.
00004  *
00005  * This Source Code Form is subject to the terms of the Mozilla Public
00006  * License, v. 2.0. If a copy of the MPL was not distributed with this
00007  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
00008  */
00009 
00010 #ifndef IWORKCONTAINERCONTEXT_H_INCLUDED
00011 #define IWORKCONTAINERCONTEXT_H_INCLUDED
00012 
00013 #include <cassert>
00014 #include <deque>
00015 
00016 #include <boost/optional.hpp>
00017 
00018 #include "IWORKTypes_fwd.h"
00019 #include "IWORKRefContext.h"
00020 #include "IWORKXMLContextBase.h"
00021 
00022 namespace libetonyek
00023 {
00024 
00025 template<typename Type, class NestedParser, template<typename T, class C> class Collector, unsigned Id, unsigned RefId = 0>
00026 class IWORKContainerContext : public IWORKXMLElementContextBase
00027 {
00028   typedef boost::unordered_map<ID_t, Type> Dict_t;
00029 
00030 public:
00031   IWORKContainerContext(IWORKXMLParserState &state, std::deque<Type> &elements)
00032     : IWORKXMLElementContextBase(state)
00033     , m_dict(0)
00034     , m_elements(elements)
00035     , m_collector(elements)
00036   {
00037   }
00038 
00039   IWORKContainerContext(IWORKXMLParserState &state, Dict_t &dict, std::deque<Type> &elements)
00040     : IWORKXMLElementContextBase(state)
00041     , m_dict(&dict)
00042     , m_elements(elements)
00043     , m_collector(elements)
00044   {
00045   }
00046 
00047 protected:
00048   virtual IWORKXMLContextPtr_t element(const int name)
00049   {
00050     if (m_ref && m_dict)
00051       handleRef();
00052     else if (m_collector.pending())
00053       m_collector.push();
00054 
00055     if (name == Id)
00056       return m_collector.template makeContext<NestedParser>(getState());
00057     else if ((RefId != 0) && (name == RefId))
00058       return makeContext<IWORKRefContext>(getState(), m_ref);
00059     return IWORKXMLContextPtr_t();
00060   }
00061 
00062   virtual void endOfElement()
00063   {
00064     if (m_ref && m_dict)
00065       handleRef();
00066     else if (m_collector.pending())
00067       m_collector.push();
00068   }
00069 
00070 private:
00071   void handleRef()
00072   {
00073     assert(m_dict);
00074 
00075     const typename Dict_t::const_iterator it = m_dict->find(get(m_ref));
00076     if (it == m_dict->end())
00077       m_elements.push_back(Type());
00078     else
00079       m_elements.push_back(it->second);
00080   }
00081 
00082 private:
00083   Dict_t *const m_dict;
00084   boost::optional<ID_t> m_ref;
00085   std::deque<Type> &m_elements;
00086   Collector<Type, std::deque<Type> > m_collector;
00087 };
00088 
00089 }
00090 
00091 #endif // IWORKCONTAINERCONTEXT_H_INCLUDED
00092 
00093 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */