summaryrefslogtreecommitdiff
path: root/ACE/ace/XML_Utils/XMLSchema/id_map.hpp
blob: 559d461665fc9ebfa3b780b60748624919e271d7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
// -*- C++ -*-
//=============================================================================
/**
 * @file    id_map.hpp
 *
 * This file contains the ID_Map class which has the responsibility of linking
 * XML IDREF objects to their XML ID counterparts.  In the output files, this
 * means that a <IDREF name>_ptr() will return a pointer to the identified
 * object.
 *
 * Exception NULL_PTR_Entry is thrown when a program attempts to add a NULL_PTR
 * to either the id_map or idref_map.
 *
 * Exception Unresolved_IDREF is thrown if an element in an XML document attempts
 * to reference an ID that does not exist.
 *
 * @author Jason R. Cody <jason.r.cody@vanderbilt.edu; jason.r.cody@gmail.com>
 */
//=============================================================================

#ifndef _ID_MAP_H
#define _ID_MAP_H

//ID_Map makes use of the Types::idref_ data member to set it to the appropriate
//object created during parsing
#include "ace/XML_Utils/XMLSchema/Types.hpp"

//The ID_Map is a Thread Specific Storage element.
#include "ace/TSS_T.h"
#include "ace/ace_wchar.h"

 /**
 * @class ID_Map
 *
 * @brief A class that handles the mapping of IDREF objects to objects with the
 *  respective ID.
 */
  class ID_Map
  {
    public:

    //Trait to allow for ease of thread specific storage.
    typedef ACE_TSS<ID_Map> TSS_ID_Map;
    typedef std::map<std::basic_string<ACE_TCHAR>, XSCRT::Type*>::iterator id_iterator;
    typedef std::multimap<std::basic_string<ACE_TCHAR>, XSCRT::Type*>::iterator idref_iterator;
    typedef std::map<std::basic_string<ACE_TCHAR>, XSCRT::Type*> ID_MAP;
    typedef std::multimap<std::basic_string<ACE_TCHAR>, XSCRT::Type*> IDREF_MAP;


    //Exception Classes
    //NULL_PTR_Entry thrown when a NULL PTR is added to the
    //ID_Map
    class NULL_PTR_Entry {};

    //Unresolved_IDREF thrown when there are IDREF's in the
    //XML document.
    class Unresolved_IDREF {
      public:
        explicit Unresolved_IDREF(const std::basic_string<ACE_TCHAR> &message) : message(message)
        {}
        ~Unresolved_IDREF(){}
        std::basic_string<ACE_TCHAR> get_message ( void )
        {
          return message;
        }
       private:
         std::basic_string<ACE_TCHAR> message;
    };

    //Only a default constructor and destructor are needed
    //Constructor
    ID_Map ()
    {
    }

    //Destructor
    ~ID_Map ()
    {
    }

    // Add an ID to the ID map
    void add_id (const std::basic_string<ACE_TCHAR>& id, XSCRT::Type *obj_ref)
    {
      if (obj_ref)
      {
        this->id_map_.insert (ID_MAP::value_type(id, obj_ref));
      }
      else
      {
        throw NULL_PTR_Entry();
      }
    }

    // Add an IDREF to the IDREF map
    void add_idref (const std::basic_string<ACE_TCHAR>& idref, XSCRT::Type *obj_ref)
    {
      if (obj_ref)
      {
          this->idref_map_.insert (IDREF_MAP::value_type(idref, obj_ref));
      }
      else
      {
        throw NULL_PTR_Entry();
      }
    }

    void resolve_single_idref (const std::basic_string<ACE_TCHAR>& idref, ::XSCRT::Type * element)
    {
       ID_Map::id_iterator id_iterator = this->id_map_.find(idref);
       if (id_iterator != this->id_map_.end())
       {
         element->set_idref(idref, id_iterator->second);
       }
       else
       {
          throw Unresolved_IDREF(idref);
       }
    }

    //Sets the referencing elements XSCRT::Type::idref_ to point to the
    //referenced element.
    //Note: The pointer is of type "XSCRT::Type*"
    void resolve_idref ( void )
    {
      // Declare iterators to navigate the maps
      for (ID_Map::idref_iterator idref_iterator = this->idref_map_.begin();
           idref_iterator != this->idref_map_.end();
           ++idref_iterator)
      {
        //Find the ID that matches the IDREF element
        ID_Map::id_iterator id_iterator = this->id_map_.find(idref_iterator->first);
        if (id_iterator != this->id_map_.end())
        {
          // Add the IDREF identifier and the reference to the
          // identified object
          std::basic_string<ACE_TCHAR> temp_id = id_iterator->first;
          idref_iterator->second->set_idref(temp_id, id_iterator->second);
        }
        else
        {
          throw Unresolved_IDREF(idref_iterator->first);
        }
      }
    }

    void reset (void)
    {
      id_map_.clear ();
      idref_map_.clear ();
    }

    private:
    /// Maps the ID string to the element with the
    /// ID attribute
    ID_MAP id_map_;
    /// Multimap that maps the IDREF string to the
    /// element with the IDREF attribute
    IDREF_MAP idref_map_;
  };

#endif /* _ID_MAP_HPP */