~zorba-coders/zorba/bug_897616

« back to all changes in this revision

Viewing changes to src/api/uri_resolver_wrappers.cpp

Support for user-provided Thesauri using standard Zorba URI Resolver mechanism. Approved: Paul J. Lucas, Matthias Brantner

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
#include "uri_resolver_wrappers.h"
19
19
#include "uriresolverimpl.h"
20
20
#include "unmarshaller.h"
 
21
#include <zorba/thesaurus.h>
 
22
#include <runtime/full_text/thesaurus.h>
 
23
#include <context/thesaurus_wrappers.h>
21
24
 
22
25
namespace zorba
23
26
{
24
 
 
25
 
  class EntityDataWrapper : public EntityData
 
27
  // "Convenience" class for passing an internal EntityData object to
 
28
  // external mappers/resolvers. This can serve as a plain EntityData or
 
29
  // a ThesaurusEntityData. However, when there's another EntityData subclass
 
30
  // in future, this won't work as EntityData becomes an ambiguous base class...
 
31
  class EntityDataWrapper : public ThesaurusEntityData
26
32
  {
27
33
  public:
28
 
    static EntityDataWrapper const* create(impl::EntityData::Kind aKind) {
 
34
    static EntityDataWrapper const* create(internal::EntityData const* aData) {
29
35
      // More ugly: Create a public-API EntityData with the same Entity Kind,
30
36
      // but only if it's one of the publicly-supported kinds
31
 
      switch (aKind) {
32
 
      case impl::EntityData::MODULE:
 
37
      switch (aData->getKind()) {
 
38
      case internal::EntityData::MODULE:
33
39
        return new EntityDataWrapper(EntityData::MODULE);
34
 
      case impl::EntityData::SCHEMA:
 
40
      case internal::EntityData::SCHEMA:
35
41
        return new EntityDataWrapper(EntityData::SCHEMA);
36
 
      case impl::EntityData::THESAURUS:
37
 
        return new EntityDataWrapper(EntityData::THESAURUS);
38
 
      case impl::EntityData::STOP_WORDS:
 
42
      case internal::EntityData::THESAURUS:
 
43
      {
 
44
        EntityDataWrapper* retval = new EntityDataWrapper(EntityData::THESAURUS);
 
45
        retval->theThesaurusLang =
 
46
            dynamic_cast<const internal::ThesaurusEntityData*>(aData)->getLanguage();
 
47
        return retval;
 
48
      }
 
49
      case internal::EntityData::STOP_WORDS:
39
50
        return new EntityDataWrapper(EntityData::STOP_WORDS);
40
 
      case impl::EntityData::COLLECTION:
 
51
      case internal::EntityData::COLLECTION:
41
52
        return new EntityDataWrapper(EntityData::COLLECTION);
42
 
      case impl::EntityData::DOCUMENT:
 
53
      case internal::EntityData::DOCUMENT:
43
54
        return new EntityDataWrapper(EntityData::DOCUMENT);
44
55
      default:
45
56
        return NULL;
50
61
      return theKind;
51
62
    }
52
63
 
 
64
    virtual zorba::locale::iso639_1::type getLanguage() const {
 
65
      return theThesaurusLang;
 
66
    }
 
67
 
53
68
  private:
54
69
    EntityDataWrapper(EntityData::Kind aKind)
55
70
      : theKind(aKind)
56
71
    {}
57
72
 
58
73
    EntityData::Kind const theKind;
 
74
    zorba::locale::iso639_1::type theThesaurusLang;
59
75
  };
60
76
 
61
77
  URIMapperWrapper::URIMapperWrapper(zorba::URIMapper& aUserMapper)
68
84
  void
69
85
  URIMapperWrapper::mapURI
70
86
  (const zstring& aUri,
71
 
    impl::EntityData const* aEntityData,
 
87
    internal::EntityData const* aEntityData,
72
88
    static_context const& aSctx,
73
89
    std::vector<zstring>& oUris)
74
90
  {
75
91
    std::auto_ptr<const EntityDataWrapper> lDataWrap
76
 
        (EntityDataWrapper::create(aEntityData->getKind()));
 
92
        (EntityDataWrapper::create(aEntityData));
77
93
    if (lDataWrap.get() == NULL) {
78
94
      return;
79
95
    }
80
96
 
81
97
    std::vector<zorba::String> lUserUris;
82
98
    // QQQ should public API have a StaticContext on it?
83
 
    theUserMapper.mapURI(zorba::String(aUri.c_str()),
84
 
      lDataWrap.get(), lUserUris);
 
99
    theUserMapper.mapURI(zorba::String(aUri.c_str()), lDataWrap.get(),
 
100
                         lUserUris);
85
101
    std::vector<zorba::String>::iterator iter;
86
102
    for (iter = lUserUris.begin(); iter != lUserUris.end(); iter++) {
87
103
      oUris.push_back(Unmarshaller::getInternalString(*iter));
88
104
    }
89
105
  }
90
106
 
91
 
  impl::URIMapper::Kind
 
107
  internal::URIMapper::Kind
92
108
  URIMapperWrapper::mapperKind()
93
109
  {
94
110
    // Still so ugly.
95
111
    switch (theUserMapper.mapperKind()) {
96
112
      case URIMapper::COMPONENT:
97
 
        return impl::URIMapper::COMPONENT;
 
113
        return internal::URIMapper::COMPONENT;
98
114
      case URIMapper::CANDIDATE:
99
 
        return impl::URIMapper::CANDIDATE;
 
115
        return internal::URIMapper::CANDIDATE;
100
116
    }
101
117
 
102
118
    assert(false);
103
119
    // dummy return
104
 
    return impl::URIMapper::COMPONENT;
 
120
    return internal::URIMapper::COMPONENT;
105
121
  }
106
122
 
107
123
 
112
128
  URLResolverWrapper::~URLResolverWrapper()
113
129
  {}
114
130
 
115
 
  impl::Resource*
 
131
  internal::Resource*
116
132
  URLResolverWrapper::resolveURL
117
133
  (const zstring& aUrl,
118
 
    impl::EntityData const* aEntityData)
 
134
    internal::EntityData const* aEntityData)
119
135
  {
120
136
    std::auto_ptr<const EntityDataWrapper> lDataWrap
121
 
        (EntityDataWrapper::create(aEntityData->getKind()));
 
137
        (EntityDataWrapper::create(aEntityData));
122
138
    if (lDataWrap.get() == NULL) {
123
139
      return NULL;
124
140
    }
125
141
 
126
 
    impl::StreamResource* lRetval = nullptr;
127
 
    // Get the user's Resource. It's OK to use an auto_ptr here for safety,
128
 
    // because the Resource will have been created by a factory method inside
129
 
    // libzorba (no cross-DLL memory allocation issue).
130
 
    std::auto_ptr<Resource> lUserPtr
 
142
    internal::Resource* lRetval = nullptr;
 
143
    // Get the user's Resource.
 
144
    Resource::ptr lUserPtr
131
145
      (theUserResolver.resolveURL(zorba::String(aUrl.c_str()),
132
146
                                  lDataWrap.get()));
133
147
    if (lUserPtr.get() != NULL) {
134
 
      // This will get a bit more complicated when we publicly support more than
135
 
      // one kind of Resource subclass.
 
148
      // Sooo ugly... have to try down-casting to each subclass in turn to
 
149
      // figure out what kind of Resource we've got.
136
150
      StreamResourceImpl* lUserStream =
137
151
          dynamic_cast<StreamResourceImpl*>(lUserPtr.get());
138
152
      if (lUserStream != NULL) {
139
153
        // Here we pass memory ownership of the std::istream to the internal
140
154
        // StreamResource, by passing the StreamReleaser to it and setting the
141
155
        // user's StreamResource's StreamReleaser to nullptr.
142
 
        lRetval = new impl::StreamResource(lUserStream->getStream(),
 
156
        lRetval = new internal::StreamResource(lUserStream->getStream(),
143
157
                                           lUserStream->getStreamReleaser());
144
158
        lUserStream->setStreamReleaser(nullptr);
145
159
      }
146
160
      else {
147
 
        assert(false);
 
161
        Thesaurus* lUserThesaurus = dynamic_cast<Thesaurus*>(lUserPtr.get());
 
162
        if (lUserThesaurus != NULL) {
 
163
          // Here we pass memory ownership of the actual Thesaurus to the
 
164
          // internal ThesaurusWrapper.
 
165
          lRetval = new internal::ThesaurusWrapper
 
166
              (Thesaurus::ptr(lUserThesaurus));
 
167
          lUserPtr.release();
 
168
        }
 
169
        else {
 
170
          assert(false);
 
171
        }
148
172
      }
149
173
    }
150
174
    return lRetval;