/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ #include "qmf/PrivateImplRef.h" #include "qmf/exceptions.h" #include "qmf/QueryImpl.h" #include "qmf/DataAddrImpl.h" #include "qmf/SchemaIdImpl.h" #include "qpid/messaging/AddressParser.h" using namespace std; using namespace qmf; using qpid::types::Variant; typedef PrivateImplRef PI; Query::Query(QueryImpl* impl) { PI::ctor(*this, impl); } Query::Query(const Query& s) : qmf::Handle() { PI::copy(*this, s); } Query::~Query() { PI::dtor(*this); } Query& Query::operator=(const Query& s) { return PI::assign(*this, s); } Query::Query(QueryTarget t, const string& pr) { PI::ctor(*this, new QueryImpl(t, pr)); } Query::Query(QueryTarget t, const string& c, const string& p, const string& pr) { PI::ctor(*this, new QueryImpl(t, c, p, pr)); } Query::Query(QueryTarget t, const SchemaId& s, const string& pr) { PI::ctor(*this, new QueryImpl(t, s, pr)); } Query::Query(const DataAddr& a) { PI::ctor(*this, new QueryImpl(a)); } QueryTarget Query::getTarget() const { return impl->getTarget(); } const DataAddr& Query::getDataAddr() const { return impl->getDataAddr(); } const SchemaId& Query::getSchemaId() const { return impl->getSchemaId(); } void Query::setPredicate(const Variant::List& pr) { impl->setPredicate(pr); } const Variant::List& Query::getPredicate() const { return impl->getPredicate(); } bool Query::matchesPredicate(const qpid::types::Variant::Map& map) const { return impl->matchesPredicate(map); } QueryImpl::QueryImpl(const Variant::Map& map) : predicateCompiled(false) { Variant::Map::const_iterator iter; iter = map.find("_what"); if (iter == map.end()) throw QmfException("Query missing _what element"); const string& targetString(iter->second.asString()); if (targetString == "OBJECT") target = QUERY_OBJECT; else if (targetString == "OBJECT_ID") target = QUERY_OBJECT_ID; else if (targetString == "SCHEMA") target = QUERY_SCHEMA; else if (targetString == "SCHEMA_ID") target = QUERY_SCHEMA_ID; else throw QmfException("Query with invalid _what value: " + targetString); iter = map.find("_object_id"); if (iter != map.end()) { auto_ptr addrImpl(new DataAddrImpl(iter->second.asMap())); dataAddr = DataAddr(addrImpl.release()); } iter = map.find("_schema_id"); if (iter != map.end()) { auto_ptr sidImpl(new SchemaIdImpl(iter->second.asMap())); schemaId = SchemaId(sidImpl.release()); } iter = map.find("_where"); if (iter != map.end()) predicate = iter->second.asList(); } Variant::Map QueryImpl::asMap() const { Variant::Map map; string targetString; switch (target) { case QUERY_OBJECT : targetString = "OBJECT"; break; case QUERY_OBJECT_ID : targetString = "OBJECT_ID"; break; case QUERY_SCHEMA : targetString = "SCHEMA"; break; case QUERY_SCHEMA_ID : targetString = "SCHEMA_ID"; break; } map["_what"] = targetString; if (dataAddr.isValid()) map["_object_id"] = DataAddrImplAccess::get(dataAddr).asMap(); if (schemaId.isValid()) map["_schema_id"] = SchemaIdImplAccess::get(schemaId).asMap(); if (!predicate.empty()) map["_where"] = predicate; return map; } bool QueryImpl::matchesPredicate(const qpid::types::Variant::Map& data) const { if (predicate.empty()) return true; if (!predicateCompiled) { expression.reset(new Expression(predicate)); predicateCompiled = true; } return expression->evaluate(data); } void QueryImpl::parsePredicate(const string& pred) { if (pred.empty()) return; if (pred[0] == '[') { // // Parse this as an AddressParser list. // qpid::messaging::AddressParser parser(pred); parser.parseList(predicate); } else throw QmfException("Invalid predicate format"); } QueryImpl& QueryImplAccess::get(Query& item) { return *item.impl; } const QueryImpl& QueryImplAccess::get(const Query& item) { return *item.impl; }