454 lines
12 KiB
C++
454 lines
12 KiB
C++
|
|
/*
|
||
|
|
----
|
||
|
|
This file is part of SECONDO.
|
||
|
|
|
||
|
|
Copyright (C) 2004-2009, University in Hagen, Faculty of Mathematics
|
||
|
|
and Computer Science, Database Systems for New Applications.
|
||
|
|
|
||
|
|
SECONDO is free software; you can redistribute it and/or modify
|
||
|
|
it under the terms of the GNU General Public License as published by
|
||
|
|
the Free Software Foundation; either version 2 of the License, or
|
||
|
|
(at your option) any later version.
|
||
|
|
|
||
|
|
SECONDO is distributed in the hope that it will be useful,
|
||
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
GNU General Public License for more details.
|
||
|
|
|
||
|
|
You should have received a copy of the GNU General Public License
|
||
|
|
along with SECONDO; if not, write to the Free Software
|
||
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
|
----
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "AttrArray.h"
|
||
|
|
|
||
|
|
#include "Algebras/FText/FTextAlgebra.h"
|
||
|
|
#include "TypeConstructors/GAttrArrayTC.h"
|
||
|
|
#include "TypeConstructors/GSpatialAttrArrayTC.h"
|
||
|
|
#include "TypeConstructors/IntsTC.h"
|
||
|
|
#include "TypeConstructors/LinesTC.h"
|
||
|
|
#include "LogMsg.h"
|
||
|
|
#include "Algebras/Standard-C++/LongInt.h"
|
||
|
|
#include "TypeConstructors/LongIntsTC.h"
|
||
|
|
#include <map>
|
||
|
|
#include "TypeConstructors/RealsTC.h"
|
||
|
|
#include "SecondoSystem.h"
|
||
|
|
#include "SmiUtils.h"
|
||
|
|
#include "Algebras/Spatial/SpatialAlgebra.h"
|
||
|
|
#include "StandardTypes.h"
|
||
|
|
#include "TypeConstructors/StringsTC.h"
|
||
|
|
#include "Symbols.h"
|
||
|
|
#include "TypeConstructors/TextsTC.h"
|
||
|
|
#include "TypeConstructor.h"
|
||
|
|
#include "TypeUtils.h"
|
||
|
|
|
||
|
|
using namespace CRelAlgebra;
|
||
|
|
|
||
|
|
using std::string;
|
||
|
|
using std::map;
|
||
|
|
|
||
|
|
extern CMsg cmsg;
|
||
|
|
extern NestedList *nl;
|
||
|
|
|
||
|
|
//AttrArray---------------------------------------------------------------------
|
||
|
|
|
||
|
|
AttrArrayTypeConstructor *AttrArray::GetTypeConstructor(ListExpr type,
|
||
|
|
bool checkKind)
|
||
|
|
{
|
||
|
|
TypeConstructor *typeConstructor = CRelAlgebra::GetTypeConstructor(type);
|
||
|
|
|
||
|
|
if (typeConstructor != nullptr &&
|
||
|
|
(!checkKind || typeConstructor->MemberOf(Kind::ATTRARRAY())))
|
||
|
|
{
|
||
|
|
return (AttrArrayTypeConstructor*)typeConstructor;
|
||
|
|
}
|
||
|
|
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
//AttrArrayManager--------------------------------------------------------------
|
||
|
|
|
||
|
|
AttrArrayManager::AttrArrayManager() :
|
||
|
|
m_refCount(1)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
AttrArrayManager::~AttrArrayManager()
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
void AttrArrayManager::IncRef() const
|
||
|
|
{
|
||
|
|
++m_refCount;
|
||
|
|
}
|
||
|
|
|
||
|
|
void AttrArrayManager::DecRef() const
|
||
|
|
{
|
||
|
|
if (--m_refCount == 0)
|
||
|
|
{
|
||
|
|
delete this;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
uint64_t AttrArrayManager::GetRefCount() const
|
||
|
|
{
|
||
|
|
return m_refCount;
|
||
|
|
}
|
||
|
|
|
||
|
|
//AttrArrayTypeConstructor------------------------------------------------------
|
||
|
|
|
||
|
|
/*
|
||
|
|
The default ATTRARRAY types are determined by searching a map for the passed
|
||
|
|
attribute type's name.
|
||
|
|
|
||
|
|
If no default type is found we return a corresponding generic ATTRARRAY type.
|
||
|
|
|
||
|
|
Because Secondo can't stand static ~ListExpr~s we store functions.
|
||
|
|
|
||
|
|
*/
|
||
|
|
ListExpr AttrArrayTypeConstructor::GetDefaultAttrArrayType(
|
||
|
|
ListExpr attributeType, bool numeric)
|
||
|
|
{
|
||
|
|
static map<string, ListExpr(*)()> types =
|
||
|
|
{
|
||
|
|
{ CcInt::BasicType(), [](){ return IntsTI(false).GetTypeExpr(); } },
|
||
|
|
{ LongInt::BasicType(), [](){ return LongIntsTI(false).GetTypeExpr(); } },
|
||
|
|
{ CcReal::BasicType(), [](){ return RealsTI(false).GetTypeExpr(); } },
|
||
|
|
{ CcString::BasicType(), [](){ return StringsTI(false).GetTypeExpr(); } },
|
||
|
|
{ FText::BasicType(), [](){ return TextsTI(false).GetTypeExpr(); } },
|
||
|
|
{ Line::BasicType(), [](){ return LinesTI(false).GetTypeExpr(); } }
|
||
|
|
};
|
||
|
|
|
||
|
|
TypeConstructor *typeConstructor = GetTypeConstructor(attributeType);
|
||
|
|
|
||
|
|
if (typeConstructor == nullptr)
|
||
|
|
{
|
||
|
|
return nl->Empty();
|
||
|
|
}
|
||
|
|
|
||
|
|
map<string, ListExpr(*)()>::iterator result =
|
||
|
|
types.find(typeConstructor->Name());
|
||
|
|
|
||
|
|
if (result != types.end())
|
||
|
|
{
|
||
|
|
const ListExpr type = result->second();
|
||
|
|
|
||
|
|
return numeric ? SecondoSystem::GetCatalog()->NumericType(type) : type;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeConstructor->MemberOf(Kind::SPATIAL1D()))
|
||
|
|
{
|
||
|
|
GSpatialAttrArrayTI<1> genericTypeInfo = GSpatialAttrArrayTI<1>(numeric);
|
||
|
|
|
||
|
|
genericTypeInfo.SetAttributeType(attributeType);
|
||
|
|
|
||
|
|
return genericTypeInfo.GetTypeExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeConstructor->MemberOf(Kind::SPATIAL2D()))
|
||
|
|
{
|
||
|
|
GSpatialAttrArrayTI<2> genericTypeInfo = GSpatialAttrArrayTI<2>(numeric);
|
||
|
|
|
||
|
|
genericTypeInfo.SetAttributeType(attributeType);
|
||
|
|
|
||
|
|
return genericTypeInfo.GetTypeExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeConstructor->MemberOf(Kind::SPATIAL3D()))
|
||
|
|
{
|
||
|
|
GSpatialAttrArrayTI<3> genericTypeInfo = GSpatialAttrArrayTI<3>(numeric);
|
||
|
|
|
||
|
|
genericTypeInfo.SetAttributeType(attributeType);
|
||
|
|
|
||
|
|
return genericTypeInfo.GetTypeExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeConstructor->MemberOf(Kind::SPATIAL4D()))
|
||
|
|
{
|
||
|
|
GSpatialAttrArrayTI<4> genericTypeInfo = GSpatialAttrArrayTI<4>(numeric);
|
||
|
|
|
||
|
|
genericTypeInfo.SetAttributeType(attributeType);
|
||
|
|
|
||
|
|
return genericTypeInfo.GetTypeExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeConstructor->MemberOf(Kind::SPATIAL8D()))
|
||
|
|
{
|
||
|
|
GSpatialAttrArrayTI<8> genericTypeInfo = GSpatialAttrArrayTI<8>(numeric);
|
||
|
|
|
||
|
|
genericTypeInfo.SetAttributeType(attributeType);
|
||
|
|
|
||
|
|
return genericTypeInfo.GetTypeExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
GAttrArrayTI genericTypeInfo = GAttrArrayTI(numeric);
|
||
|
|
|
||
|
|
genericTypeInfo.SetAttributeType(attributeType);
|
||
|
|
|
||
|
|
return genericTypeInfo.GetTypeExpr();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
We use all possible default functions.
|
||
|
|
|
||
|
|
*/
|
||
|
|
AttrArrayTypeConstructor::AttrArrayTypeConstructor(const std::string& name,
|
||
|
|
TypeProperty typeProperty, TypeCheckFunction typeCheck,
|
||
|
|
AttrArrayTypeFunction attributeType, AttrArrayManagerFunction manager) :
|
||
|
|
AttrArrayTypeConstructor(name, typeProperty, DefaultOut, DefaultIn,
|
||
|
|
DefaultCreate, DefaultDelete, DefaultOpen,
|
||
|
|
DefaultSave, DefaultClose, DefaultClone, DefaultCast,
|
||
|
|
DefaultSizeOf, typeCheck, attributeType, manager)
|
||
|
|
{
|
||
|
|
}
|
||
|
|
|
||
|
|
AttrArrayTypeConstructor::AttrArrayTypeConstructor(const string& name,
|
||
|
|
TypeProperty typeProperty, OutObject out, InObject in, ObjectCreation create,
|
||
|
|
ObjectDeletion del, ObjectOpen open, ObjectSave save, ObjectClose close,
|
||
|
|
ObjectClone clone, ObjectCast cast, ObjectSizeof sizeOf,
|
||
|
|
TypeCheckFunction typeCheck, AttrArrayTypeFunction attributeType,
|
||
|
|
AttrArrayManagerFunction manager) :
|
||
|
|
TypeConstructor(name, typeProperty, out, in, nullptr, nullptr, create, del,
|
||
|
|
open, save, close, clone, cast, sizeOf, typeCheck),
|
||
|
|
m_getAttributeType(attributeType),
|
||
|
|
m_createManager(manager)
|
||
|
|
{
|
||
|
|
AssociateKind(Kind::ATTRARRAY());
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr AttrArrayTypeConstructor::GetAttributeType(ListExpr typeExpr,
|
||
|
|
bool numeric)
|
||
|
|
{
|
||
|
|
return m_getAttributeType(typeExpr, numeric);
|
||
|
|
}
|
||
|
|
|
||
|
|
AttrArrayManager *AttrArrayTypeConstructor::CreateManager(
|
||
|
|
ListExpr attributeType)
|
||
|
|
{
|
||
|
|
return m_createManager(attributeType);
|
||
|
|
}
|
||
|
|
|
||
|
|
Word AttrArrayTypeConstructor::DefaultIn(ListExpr typeExpr, ListExpr value,
|
||
|
|
int errorPos, ListExpr &errorInfo,
|
||
|
|
bool &correct)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
AttrArrayTypeConstructor *typeConstructor =
|
||
|
|
(AttrArrayTypeConstructor*)GetTypeConstructor(typeExpr);
|
||
|
|
|
||
|
|
const SmiFileId fileId =
|
||
|
|
SecondoSystem::GetCatalog()->GetFlobFile()->GetFileId();
|
||
|
|
|
||
|
|
const ListExpr attrType = typeConstructor->GetAttributeType(typeExpr,
|
||
|
|
true);
|
||
|
|
|
||
|
|
const InObject attrIn = GetInFunction(attrType);
|
||
|
|
|
||
|
|
AttrArrayManager *manager = typeConstructor->CreateManager(attrType);
|
||
|
|
|
||
|
|
AttrArray *result = manager->Create(fileId);
|
||
|
|
|
||
|
|
manager->DecRef();
|
||
|
|
|
||
|
|
ListExpr attributeValues = value;
|
||
|
|
|
||
|
|
if (nl->IsAtom(attributeValues))
|
||
|
|
{
|
||
|
|
cmsg.inFunError(nl->ToString(typeExpr) +
|
||
|
|
": Expected list of attribute values.");
|
||
|
|
|
||
|
|
correct = false;
|
||
|
|
|
||
|
|
result->DecRef();
|
||
|
|
|
||
|
|
return Word();
|
||
|
|
}
|
||
|
|
|
||
|
|
std::string error;
|
||
|
|
|
||
|
|
uint64_t row = 0;
|
||
|
|
|
||
|
|
while (!nl->IsEmpty(attributeValues))
|
||
|
|
{
|
||
|
|
Word attrInResult = attrIn(attrType, nl->First(attributeValues),
|
||
|
|
row++, errorInfo, correct);
|
||
|
|
|
||
|
|
if (!correct)
|
||
|
|
{
|
||
|
|
cmsg.inFunError("Attribute InFunction failed: "+
|
||
|
|
nl->ToString(errorInfo));
|
||
|
|
|
||
|
|
result->DecRef();
|
||
|
|
|
||
|
|
return Word();
|
||
|
|
}
|
||
|
|
|
||
|
|
Attribute *attribute = (Attribute*)attrInResult.addr;
|
||
|
|
|
||
|
|
result->Append(*attribute);
|
||
|
|
|
||
|
|
attribute->DeleteIfAllowed();
|
||
|
|
|
||
|
|
attributeValues = nl->Rest(attributeValues);
|
||
|
|
}
|
||
|
|
|
||
|
|
correct = true;
|
||
|
|
|
||
|
|
return Word(result);
|
||
|
|
}
|
||
|
|
catch (const std::exception &e)
|
||
|
|
{
|
||
|
|
cmsg.inFunError(nl->ToString(typeExpr) + ": " + e.what());
|
||
|
|
|
||
|
|
correct = false;
|
||
|
|
|
||
|
|
return Word();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
ListExpr AttrArrayTypeConstructor::DefaultOut(ListExpr typeExpr, Word value)
|
||
|
|
{
|
||
|
|
AttrArrayTypeConstructor *typeConstructor =
|
||
|
|
(AttrArrayTypeConstructor*)GetTypeConstructor(typeExpr);
|
||
|
|
|
||
|
|
const ListExpr attrType = typeConstructor->GetAttributeType(typeExpr,
|
||
|
|
true);
|
||
|
|
|
||
|
|
const OutObject attrOut = GetOutFunction(attrType);
|
||
|
|
|
||
|
|
AttrArray &instance = *(AttrArray*)value.addr;
|
||
|
|
|
||
|
|
ListExpr attributeValues = nl->OneElemList(nl->Empty()),
|
||
|
|
attributeValuesEnd = attributeValues;
|
||
|
|
|
||
|
|
for (AttrArrayEntry &entry : instance.GetFilter())
|
||
|
|
{
|
||
|
|
Attribute *attr = entry.GetAttribute();
|
||
|
|
|
||
|
|
attributeValuesEnd = nl->Append(attributeValuesEnd, attrOut(attrType,
|
||
|
|
attr));
|
||
|
|
|
||
|
|
attr->DeleteIfAllowed();
|
||
|
|
}
|
||
|
|
|
||
|
|
return nl->Rest(attributeValues);
|
||
|
|
}
|
||
|
|
|
||
|
|
Word AttrArrayTypeConstructor::DefaultCreate(const ListExpr typeExpr)
|
||
|
|
{
|
||
|
|
const SmiFileId fileId =
|
||
|
|
SecondoSystem::GetCatalog()->GetFlobFile()->GetFileId();
|
||
|
|
|
||
|
|
AttrArrayTypeConstructor *typeConstructor =
|
||
|
|
(AttrArrayTypeConstructor*)GetTypeConstructor(typeExpr);
|
||
|
|
|
||
|
|
const ListExpr attrType = typeConstructor->GetAttributeType(typeExpr,
|
||
|
|
true);
|
||
|
|
|
||
|
|
AttrArrayManager *manager = typeConstructor->CreateManager(attrType);
|
||
|
|
|
||
|
|
AttrArray *result = manager->Create(fileId);
|
||
|
|
|
||
|
|
manager->DecRef();
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
void AttrArrayTypeConstructor::DefaultDelete(const ListExpr typeExpr,
|
||
|
|
Word &value)
|
||
|
|
{
|
||
|
|
AttrArray &instance = *(AttrArray*)value.addr;
|
||
|
|
|
||
|
|
instance.DeleteRecords();
|
||
|
|
instance.DecRef();
|
||
|
|
|
||
|
|
value.addr = nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AttrArrayTypeConstructor::DefaultOpen(SmiRecord &valueRecord,
|
||
|
|
size_t &offset,
|
||
|
|
const ListExpr typeExpr, Word &value)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
SmiReader source = SmiReader(valueRecord, offset);
|
||
|
|
|
||
|
|
AttrArrayTypeConstructor *typeConstructor =
|
||
|
|
(AttrArrayTypeConstructor*)GetTypeConstructor(typeExpr);
|
||
|
|
|
||
|
|
const ListExpr attrType = typeConstructor->GetAttributeType(typeExpr, true);
|
||
|
|
|
||
|
|
AttrArrayManager *manager = typeConstructor->CreateManager(attrType);
|
||
|
|
|
||
|
|
AttrArray *result = manager->Load(source);
|
||
|
|
|
||
|
|
manager->DecRef();
|
||
|
|
|
||
|
|
offset = source.GetPosition();
|
||
|
|
|
||
|
|
value = Word(result);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception &e)
|
||
|
|
{
|
||
|
|
value = Word();
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
bool AttrArrayTypeConstructor::DefaultSave(SmiRecord &valueRecord,
|
||
|
|
size_t &offset,
|
||
|
|
const ListExpr typeExpr, Word &value)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
SmiWriter target = SmiWriter(valueRecord, offset);
|
||
|
|
|
||
|
|
((AttrArray*)value.addr)->Save(target, true);
|
||
|
|
|
||
|
|
offset = target.GetPosition();
|
||
|
|
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
catch (const std::exception &e)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
void AttrArrayTypeConstructor::DefaultClose(const ListExpr typeExpr,
|
||
|
|
Word &value)
|
||
|
|
{
|
||
|
|
((AttrArray*)value.addr)->DecRef();
|
||
|
|
|
||
|
|
value.addr = nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
void *AttrArrayTypeConstructor::DefaultCast(void *addr)
|
||
|
|
{
|
||
|
|
return nullptr;
|
||
|
|
}
|
||
|
|
|
||
|
|
int AttrArrayTypeConstructor::DefaultSizeOf()
|
||
|
|
{
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
Word AttrArrayTypeConstructor::DefaultClone(const ListExpr typeExpr,
|
||
|
|
const Word &value)
|
||
|
|
{
|
||
|
|
AttrArray &instance = *(AttrArray*)value.addr;
|
||
|
|
|
||
|
|
AttrArray *result = (AttrArray*)DefaultCreate(typeExpr).addr;
|
||
|
|
|
||
|
|
for (AttrArrayEntry &entry : instance.GetFilter())
|
||
|
|
{
|
||
|
|
result->Append(entry);
|
||
|
|
}
|
||
|
|
|
||
|
|
return Word(result);
|
||
|
|
}
|