2013-02-02 21:52:49 +01:00
|
|
|
//
|
|
|
|
// Document.cpp
|
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
//
|
|
|
|
// Library: MongoDB
|
|
|
|
// Package: MongoDB
|
|
|
|
// Module: Document
|
|
|
|
//
|
|
|
|
// Implementation of the Document class.
|
|
|
|
//
|
|
|
|
// Copyright (c) 2012, Applied Informatics Software Engineering GmbH.
|
|
|
|
// and Contributors.
|
|
|
|
//
|
2014-05-04 21:02:42 +02:00
|
|
|
// SPDX-License-Identifier: BSL-1.0
|
2013-02-02 21:52:49 +01:00
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#include "Poco/MongoDB/Document.h"
|
|
|
|
#include "Poco/MongoDB/Binary.h"
|
|
|
|
#include "Poco/MongoDB/ObjectId.h"
|
|
|
|
#include "Poco/MongoDB/Array.h"
|
2013-02-15 22:32:24 +01:00
|
|
|
#include "Poco/MongoDB/RegularExpression.h"
|
|
|
|
#include "Poco/MongoDB/JavaScriptCode.h"
|
2013-03-17 19:34:36 +01:00
|
|
|
#include <sstream>
|
2013-02-02 21:52:49 +01:00
|
|
|
|
2013-03-17 19:34:36 +01:00
|
|
|
|
|
|
|
namespace Poco {
|
|
|
|
namespace MongoDB {
|
2013-02-02 21:52:49 +01:00
|
|
|
|
|
|
|
|
|
|
|
Document::Document()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-03-17 19:34:36 +01:00
|
|
|
|
2013-02-02 21:52:49 +01:00
|
|
|
Document::~Document()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2013-02-15 22:32:24 +01:00
|
|
|
|
2013-02-19 22:32:40 +01:00
|
|
|
Element::Ptr Document::get(const std::string& name) const
|
2013-02-15 22:32:24 +01:00
|
|
|
{
|
|
|
|
Element::Ptr element;
|
|
|
|
|
2013-02-19 22:32:40 +01:00
|
|
|
ElementSet::const_iterator it = std::find_if(_elements.begin(), _elements.end(), ElementFindByName(name));
|
2013-02-15 22:32:24 +01:00
|
|
|
if ( it != _elements.end() )
|
|
|
|
{
|
|
|
|
return *it;
|
|
|
|
}
|
|
|
|
|
|
|
|
return element;
|
|
|
|
}
|
|
|
|
|
2015-12-12 17:15:55 +01:00
|
|
|
Int64 Document::getInteger(const std::string& name) const
|
|
|
|
{
|
|
|
|
Element::Ptr element = get(name);
|
|
|
|
if ( element.isNull() ) throw NotFoundException(name);
|
|
|
|
|
|
|
|
if ( ElementTraits<double>::TypeId == element->type() )
|
|
|
|
{
|
|
|
|
ConcreteElement<double>* concrete = dynamic_cast<ConcreteElement<double>* >(element.get());
|
|
|
|
if ( concrete != NULL ) return concrete->value();
|
|
|
|
}
|
|
|
|
else if ( ElementTraits<Int32>::TypeId == element->type() )
|
|
|
|
{
|
|
|
|
ConcreteElement<Int32>* concrete = dynamic_cast<ConcreteElement<Int32>* >(element.get());
|
|
|
|
if ( concrete != NULL ) return concrete->value();
|
|
|
|
}
|
|
|
|
else if ( ElementTraits<Int64>::TypeId == element->type() )
|
|
|
|
{
|
|
|
|
ConcreteElement<Int64>* concrete = dynamic_cast<ConcreteElement<Int64>* >(element.get());
|
|
|
|
if ( concrete != NULL ) return concrete->value();
|
|
|
|
}
|
|
|
|
throw BadCastException("Invalid type mismatch!");
|
|
|
|
}
|
2013-02-15 22:32:24 +01:00
|
|
|
|
2013-02-02 21:52:49 +01:00
|
|
|
void Document::read(BinaryReader& reader)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
reader >> size;
|
|
|
|
|
|
|
|
unsigned char type;
|
|
|
|
reader >> type;
|
|
|
|
|
|
|
|
while( type != '\0' )
|
|
|
|
{
|
|
|
|
Element::Ptr element;
|
|
|
|
|
|
|
|
std::string name = BSONReader(reader).readCString();
|
|
|
|
|
|
|
|
switch(type)
|
|
|
|
{
|
|
|
|
case ElementTraits<double>::TypeId:
|
|
|
|
element = new ConcreteElement<double>(name, 0);
|
|
|
|
break;
|
|
|
|
case ElementTraits<Int32>::TypeId:
|
|
|
|
element = new ConcreteElement<Int32>(name, 0);
|
|
|
|
break;
|
|
|
|
case ElementTraits<std::string>::TypeId:
|
|
|
|
element = new ConcreteElement<std::string>(name, "");
|
|
|
|
break;
|
|
|
|
case ElementTraits<Document::Ptr>::TypeId:
|
|
|
|
element = new ConcreteElement<Document::Ptr>(name, new Document());
|
|
|
|
break;
|
|
|
|
case ElementTraits<Array::Ptr>::TypeId:
|
|
|
|
element = new ConcreteElement<Array::Ptr>(name, new Array());
|
|
|
|
break;
|
|
|
|
case ElementTraits<Binary::Ptr>::TypeId:
|
|
|
|
element = new ConcreteElement<Binary::Ptr>(name, new Binary());
|
|
|
|
break;
|
|
|
|
case ElementTraits<ObjectId::Ptr>::TypeId:
|
|
|
|
element = new ConcreteElement<ObjectId::Ptr>(name, new ObjectId());
|
|
|
|
break;
|
|
|
|
case ElementTraits<bool>::TypeId:
|
|
|
|
element = new ConcreteElement<bool>(name, false);
|
|
|
|
break;
|
|
|
|
case ElementTraits<Poco::Timestamp>::TypeId:
|
|
|
|
element = new ConcreteElement<Poco::Timestamp>(name, Poco::Timestamp());
|
|
|
|
break;
|
|
|
|
case ElementTraits<NullValue>::TypeId:
|
|
|
|
element = new ConcreteElement<NullValue>(name, NullValue(0));
|
|
|
|
break;
|
|
|
|
case ElementTraits<RegularExpression::Ptr>::TypeId:
|
|
|
|
element = new ConcreteElement<RegularExpression::Ptr>(name, new RegularExpression());
|
|
|
|
break;
|
|
|
|
case ElementTraits<JavaScriptCode::Ptr>::TypeId:
|
|
|
|
element = new ConcreteElement<JavaScriptCode::Ptr>(name, new JavaScriptCode());
|
|
|
|
break;
|
|
|
|
case ElementTraits<Int64>::TypeId:
|
|
|
|
element = new ConcreteElement<Int64>(name, 0);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
{
|
|
|
|
std::stringstream ss;
|
|
|
|
ss << "Element " << name << " contains an unsupported type " << std::hex << (int) type;
|
|
|
|
throw Poco::NotImplementedException(ss.str());
|
|
|
|
}
|
|
|
|
//TODO: x0F -> JavaScript code with scope
|
|
|
|
// xFF -> Min Key
|
|
|
|
// x7F -> Max Key
|
|
|
|
}
|
|
|
|
|
|
|
|
element->read(reader);
|
2015-05-14 18:34:57 +02:00
|
|
|
_elements.push_back(element);
|
2013-02-02 21:52:49 +01:00
|
|
|
|
|
|
|
reader >> type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-15 22:32:24 +01:00
|
|
|
std::string Document::toString(int indent) const
|
2013-02-02 21:52:49 +01:00
|
|
|
{
|
|
|
|
std::ostringstream oss;
|
2013-03-01 21:59:50 +01:00
|
|
|
|
2013-03-09 20:45:22 +01:00
|
|
|
oss << '{';
|
|
|
|
|
|
|
|
if ( indent > 0 ) oss << std::endl;
|
|
|
|
|
2013-03-01 21:59:50 +01:00
|
|
|
|
2013-02-13 19:10:57 +01:00
|
|
|
for(ElementSet::const_iterator it = _elements.begin(); it != _elements.end(); ++it)
|
2013-02-02 21:52:49 +01:00
|
|
|
{
|
2013-02-14 22:51:51 +01:00
|
|
|
if ( it != _elements.begin() )
|
|
|
|
{
|
2013-03-09 20:45:22 +01:00
|
|
|
oss << ',';
|
|
|
|
if ( indent > 0 ) oss << std::endl;
|
2013-02-17 18:41:36 +01:00
|
|
|
}
|
2013-03-09 20:45:22 +01:00
|
|
|
|
|
|
|
for(int i = 0; i < indent; ++i) oss << ' ';
|
|
|
|
|
|
|
|
oss << '"' << (*it)->name() << '"';
|
|
|
|
oss << (( indent > 0 ) ? " : " : ":");
|
|
|
|
|
|
|
|
oss << (*it)->toString(indent > 0 ? indent + 2 : 0);
|
2013-02-17 18:41:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( indent > 0 )
|
|
|
|
{
|
|
|
|
oss << std::endl;
|
2013-03-09 20:45:22 +01:00
|
|
|
if ( indent >= 2 ) indent -= 2;
|
|
|
|
|
|
|
|
for(int i = 0; i < indent; ++i) oss << ' ';
|
2013-02-02 21:52:49 +01:00
|
|
|
}
|
2013-02-17 18:41:36 +01:00
|
|
|
|
2013-03-09 20:45:22 +01:00
|
|
|
oss << '}';
|
2013-03-01 21:59:50 +01:00
|
|
|
|
2013-02-02 21:52:49 +01:00
|
|
|
return oss.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Document::write(BinaryWriter& writer)
|
|
|
|
{
|
|
|
|
if ( _elements.empty() )
|
|
|
|
{
|
|
|
|
writer << 5;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::stringstream sstream;
|
|
|
|
Poco::BinaryWriter tempWriter(sstream);
|
|
|
|
for(ElementSet::iterator it = _elements.begin(); it != _elements.end(); ++it)
|
|
|
|
{
|
2013-03-17 19:34:36 +01:00
|
|
|
tempWriter << static_cast<unsigned char>((*it)->type());
|
2013-02-02 21:52:49 +01:00
|
|
|
BSONWriter(tempWriter).writeCString((*it)->name());
|
|
|
|
Element::Ptr element = *it;
|
|
|
|
element->write(tempWriter);
|
|
|
|
}
|
|
|
|
tempWriter.flush();
|
2015-12-12 17:15:55 +01:00
|
|
|
|
2013-03-17 19:34:36 +01:00
|
|
|
Poco::Int32 len = static_cast<Poco::Int32>(5 + sstream.tellp()); /* 5 = sizeof(len) + 0-byte */
|
2013-02-02 21:52:49 +01:00
|
|
|
writer << len;
|
|
|
|
writer.writeRaw(sstream.str());
|
|
|
|
}
|
|
|
|
writer << '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-03-12 04:49:54 +01:00
|
|
|
} } // namespace Poco::MongoDB
|