2005/5/9

     
 

MetaAttribute.cpp

artefaktur
// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*- 
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
// 
// 
// This library 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 
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
//                         ACDK
// 
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
// 
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/dmi/MetaAttribute.cpp,v 1.25 2005/02/11 11:06:24 kommer Exp $
#include <acdk.h>

#include "MetaAttribute.h"
#include "ClazzAttributesRes.h"
#include "../Integer.h"
#include "../Long.h"

namespace acdk {
namespace lang {
namespace dmi {

void*
ClazzAttributeResValue::cloneObjectPtr(int restype, void* ptr)
{
  if (ptr == 0)
    return 0;
  acdk::lang::Object* sptr = reinterpret_cast<acdk::lang::Object*>(ptr);
  sptr->addRef();
  return ptr;
}

void*
ClazzAttributeResValue::releaseObjectPtr(int restype, void* ptr)
{
  if (ptr == 0)
    return 0;
  acdk::lang::Object* sptr = reinterpret_cast<acdk::lang::Object*>(ptr);
  sptr->releaseRef();
  return 0;
}

acdk::lang::Object 
ClazzAttributeResValue::castObjectPtr(int restype, void *ptr)
{
  switch (restype)
  {
    case EmptyResType:
      return Nil;
    case CharPtrResType:
      return (acdk::lang::Object)SCS((const char*)ptr);
    case StringResType:
    case ObjectPtrResType:
      return reinterpret_cast<acdk::lang::Object*>(ptr);
    case ScriptVarResType:
      return reinterpret_cast<ScriptVar*>(ptr)->getObjectVar();
    default:
      return Nil;
  }
}

void* 
cloneCharPtr(int restype, void* ptr)
{
  if (ptr == 0)
    return 0;
  char* sptr = reinterpret_cast<char*>(ptr);
  char* nptr = ::new char[strlen(sptr) + 1];
  strcpy(nptr, sptr);
  return (void*)nptr;
}

void* 
releaseCharPtr(int restype, void* ptr)
{
  if (ptr == 0)
    return 0;
  char* sptr = reinterpret_cast<char*>(ptr);
  delete[] sptr;
  return 0;
}

acdk::lang::Object
makeStringOfRes(int type, void* ptr)
{
  if (ptr == 0)
    return (acdk::lang::Object)String::emptyString();
  if (type == CharPtrResType)
    return &SCS((const char*)ptr);
  else if (type == StringResType)
  {
    acdk::lang::Object ret = (String*)ptr;
    return ret;
  }
  return Nil;
}


void* 
cloneFunctionPtr(int restype, void* ptr)
{
  return ptr;
}

void* 
releaseFunctionPtr(int restype, void* ptr)
{
  return ptr;
}

acdk::lang::Object 
castFunctionPtr(int restype, void *ptr)
{
#if defined(ACDK_64_BIT_PTR)
  return new Long((jlong)ptr);
#else
/FONT>
  return new Integer((int)ptr);
#endif
/FONT>
}

ScriptVar
castFunctionPtr2ScriptVar(int restype, void *ptr)
{
#if defined(ACDK_64_BIT_PTR)
  return ScriptVar(inOf(jlong(ptr)));
#else
/FONT>
  return ScriptVar(inOf(int(ptr)));
#endif
/FONT>
}

ACDK_DECL_CLASS(InstanceAttributeData);

class ACDK_CORE_PUBLIC InstanceAttributeData
: extends acdk::lang::Object
{
public:
  typedef KeyValue<acdk::lang::Object*, ClazzAttributesRes> InstanceAttr;
  typedef acdk::lang::sys::core_vector<InstanceAttr> InstanceAttrMap;
  InstanceAttrMap _data;
  InstanceAttributeData() {}
  ~InstanceAttributeData()
  {
  }
  ClazzAttributeResValue getAttribute(acdk::lang::Object* o, const char* ptr)
  {
    InstanceAttrMap::iterator it = _data.find(InstanceAttr(o, ClazzAttributesRes()));
    if (it == _data.end())
      return ClazzAttributeResValue();
    return it->value.get(ptr);
  }
  bool hasEntry(acdk::lang::Object* o, const char* ptr)
  {
    InstanceAttrMap::iterator it = _data.find(InstanceAttr(o, ClazzAttributesRes()));
    if (it == _data.end())
      return false;
    return it->value.hasEntry(ptr);
  }
  ClazzAttributesRes getTable(acdk::lang::Object* o)
  {
    InstanceAttrMap::iterator it = _data.find(InstanceAttr(o, ClazzAttributesRes()));
    if (it == _data.end())
      return ClazzAttributesRes();
    return it->value;
  }
  void put(acdk::lang::Object* o, const StringRes& key, const ClazzAttributeResValue& val)
  {
    InstanceAttrMap::iterator it = _data.find(InstanceAttr(o, ClazzAttributesRes()));
    if (it == _data.end())
    {
      _data.push_back(InstanceAttr(o, ClazzAttributesRes()));
      it = _data.find(InstanceAttr(o, ClazzAttributesRes()));
    }
    it->value.put(key, val);
  }
  void remove(acdk::lang::Object* o, const char* ptr)
  {
    InstanceAttrMap::iterator it = _data.find(InstanceAttr(o, ClazzAttributesRes()));
    if (it == _data.end())
      return;
    it->value.remove(ptr);
  }
  void releaseObject(acdk::lang::Object* o)
  {
    InstanceAttrMap::iterator it = _data.find(InstanceAttr(o, ClazzAttributesRes()));
    if (it == _data.end())
      return;
    _data.erase(it, it + 1);
  }
  
};

ClazzAttributeResValue::ClazzAttributeResValue(int restype, void* d, CloneAttributeValFnc clonfnc, 
                                                                  ReleaseAttributeValFnc releasefnc, 
                                                                  CastAttributeToObjectFnc castfnc,
                                                                  CastAttributeToScriptVarFnc castsvfnc)
: resType(restype)
, data(d)
, cloneFnc(clonfnc)
, releaseFnc(releasefnc)
, castObjectFnc(castfnc)
, castScriptVarFnc(castsvfnc)
{
  if (cloneFnc != 0)
    data = cloneFnc(restype, data);
}

ClazzAttributeResValue::~ClazzAttributeResValue()
{
  if (releaseFnc)
    data = releaseFnc(resType, data);
}

ClazzAttributeResValue::ClazzAttributeResValue(const ClazzAttributeResValue& other)
: resType(other.resType)
, data(other.data)
, cloneFnc(other.cloneFnc)
, releaseFnc(other.releaseFnc)
, castObjectFnc(other.castObjectFnc)
, castScriptVarFnc(other.castScriptVarFnc)
{
   if (cloneFnc != 0)
    data = cloneFnc(resType, data);
}

ClazzAttributeResValue
ClazzAttributeResValue::makeStringRes(IN(RString) str)
{
  if (str->stringFlags() & ConstSST)
    return ClazzAttributeResValue(CharPtrResType, (void*)str->c_str(), cloneCharPtr, releaseCharPtr, makeStringOfRes);
  /*String* sptr = &str;
  sptr->addRef();
  */
  return ClazzAttributeResValue(StringResType, &str, cloneObjectPtr, releaseObjectPtr, castObjectPtr);
}

//static 
ClazzAttributeResValue 
ClazzAttributeResValue::makeObjectRes(IN(acdk::lang::Object) obj)
{
  return ClazzAttributeResValue(ObjectPtrResType, &obj, cloneObjectPtr, releaseObjectPtr, castObjectPtr);
}

//static 
ClazzAttributeResValue 
ClazzAttributeResValue::makeStringRes(const char* text, bool deleteRes)
{
  if (deleteRes == true)
    return ClazzAttributeResValue(CharPtrResType, (void*)text, cloneCharPtr, releaseCharPtr, makeStringOfRes);
  return ClazzAttributeResValue(CharPtrResType, (void*)text, 0, 0, makeStringOfRes);
}

//static 
ClazzAttributeResValue 
ClazzAttributeResValue::makeScriptVarRes(IN(ScriptVar) sv)
{
  ScriptVar* svptr = ::new ScriptVar(sv);
  return ClazzAttributeResValue(ScriptVarResType, (void*)svptr, cloneScriptVarPtr, releaseScriptVarPtr, 0, castScriptVar);
}

//static 
ClazzAttributeResValue 
ClazzAttributeResValue::makeFunctionPtrRes(void* callback)
{
  return ClazzAttributeResValue(FunctionPtrResType, callback, cloneFunctionPtr, releaseFunctionPtr, castFunctionPtr, castFunctionPtr2ScriptVar);
}


//static 
void* 
ClazzAttributeResValue::cloneScriptVarPtr(int restype, void* ptr)
{
  return (void*)new ScriptVar(*reinterpret_cast<ScriptVar*>(ptr));
}

//static 
void* 
ClazzAttributeResValue::releaseScriptVarPtr(int restype, void* ptr)
{
  delete reinterpret_cast<ScriptVar*>(ptr);
  return 0;
}

//static 
ScriptVar 
ClazzAttributeResValue::castScriptVar(int restype, void *ptr)
{
  if (ptr == 0)
    return ScriptVar();
  if (restype == ScriptVarResType)
    return *reinterpret_cast<ScriptVar*>(ptr);
  if (restype == ObjectPtrResType || restype == StringResType)
    return inOf(acdk::lang::Object(reinterpret_cast<acdk::lang::Object*>(ptr)));
  if (restype == CharPtrResType)
    return inOf(RString(reinterpret_cast<char*>(ptr)));
  return ScriptVar();
}

acdk::lang::Object 
ClazzAttributeResValue::getAsObject()
{
  if (castObjectFnc != 0)
    return castObjectFnc(resType, data);
  if (castScriptVarFnc != 0)
    return castScriptVarFnc(resType, data).getObjectVar();
  return Nil;
}

ScriptVar 
ClazzAttributeResValue::getAsScriptVar()
{
  if (castScriptVarFnc != 0)
    return castScriptVarFnc(resType, data);
  if (castObjectFnc != 0)
    return inOf(castObjectFnc(resType, data));
  return ScriptVar();
}

ClazzAttributeResValue 
ClazzAttributesRes::get(const char* key)
{
  ResTable::iterator it = _entries.begin();
  ResTable::iterator end = _entries.end();
  for (; it < end; ++it)
  {
    if (strcmp((*it).key, key) == 0)
    {
      return (*it).value;
    }
  }
  return ClazzAttributeResValue();
}


ClazzAttributeResValue 
ClazzAttributesRes::getInstance(acdk::lang::Object* obj, const char* key)
{
  ResTable::iterator it = _entries.find(ResTableEntry("__instd_acdk_dmi", ClazzAttributeResValue()));
  if (it == _entries.end())
    return ClazzAttributeResValue();
  RInstanceAttributeData o = (RInstanceAttributeData)it->value.getAsObject();
  return o->getAttribute(obj, key);
}

bool 
ClazzAttributesRes::hasEntry(const char* key)
{
  ResTable::iterator it = _entries.begin();
  ResTable::iterator end = _entries.end();
  for (; it < end; ++it)
  {
    if (strcmp((*it).key, key) == 0)
    {
      return true;
    }
  }
  return false;
}

bool 
ClazzAttributesRes::hasInstanceEntry(acdk::lang::Object* obj, const char* key)
{
  ResTable::iterator it = _entries.find(ResTableEntry("__instd_acdk_dmi", ClazzAttributeResValue()));
  if (it == _entries.end())
    return false;
  RInstanceAttributeData o = (RInstanceAttributeData)it->value.getAsObject();
  return o->hasEntry(obj, key);
}

void 
ClazzAttributesRes::put(const StringRes& key, const ClazzAttributeResValue& val)
{
  ResTable::iterator it = _entries.begin();
  ResTable::iterator end = _entries.end();
  for (; it < end; ++it)
  {

    if ((*it).key != 0 && strcmp((*it).key, (const char*)key) == 0)
    {
      (*it).value = val;
      return;
    }
  }
  _entries.push_back(KeyValue<StringRes, ClazzAttributeResValue>(key, val));
}

void 
ClazzAttributesRes::putInstance(acdk::lang::Object* obj, const StringRes& key, const ClazzAttributeResValue& val)
{
  ResTable::iterator it = _entries.find(ResTableEntry("__instd_acdk_dmi", ClazzAttributeResValue()));
  if (it == _entries.end())
  {
    _entries.push_back(ResTableEntry("__instd_acdk_dmi", ClazzAttributeResValue::makeObjectRes(new InstanceAttributeData())));
    it = _entries.find(ResTableEntry("__instd_acdk_dmi", ClazzAttributeResValue()));
  }
  RInstanceAttributeData o = (RInstanceAttributeData)it->value.getAsObject();
  o->put(obj, key, val);
}

void 
ClazzAttributesRes::removeAll()
{
  _entries.erase(_entries.begin(), _entries.end());
}

void 
ClazzAttributesRes::remove(const StringRes& key)
{
  ResTable::iterator it = _entries.find(ResTableEntry(key, ClazzAttributeResValue()));
  if (it == _entries.end())
    return;
  _entries.erase(it, it + 1);
}
  
void 
ClazzAttributesRes::removeInstance(acdk::lang::Object* obj, const StringRes& key)
{
  ResTable::iterator it = _entries.find(ResTableEntry("__instd_acdk_dmi", ClazzAttributeResValue()));
  if (it == _entries.end())
    return;
  RInstanceAttributeData o = (RInstanceAttributeData)it->value.getAsObject();
  o->remove(obj, key);
}

//static 
void 
ClazzAttributesRes::attachAttribute(MetaInfo* mi, const StringRes& key, const ClazzAttributeResValue& val)
{
  if (mi->attributeRes == 0)
    mi->attributeRes = (void*)new ClazzAttributesRes();
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  ar->put(key, val);
}

//static 
void 
ClazzAttributesRes::attachInstanceAttribute(MetaInfo* mi, const StringRes& key, acdk::lang::Object* obj, const ClazzAttributeResValue& val)
{
  if (mi->attributeRes == 0)
    mi->attributeRes = (void*)new ClazzAttributesRes();
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  ar->putInstance(obj, key, val);
}

//static 
ClazzAttributeResValue
ClazzAttributesRes::getAttribute(MetaInfo* mi, IN(RString) key)
{
  if (mi->attributeRes == 0)
    return ClazzAttributeResValue();
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  return ar->get(key->c_str());
  /*
  for (int i = 0; i < ar->_entries.size(); ++i)
  {
    const char* k = ar->_entries[i].key;
    if (strcmp(k, key->c_str()) == 0)
      return ar->_entries[i];
  }
  return KeyValue<StringRes, ClazzAttributeResValue> (0, ClazzAttributeResValue());
  */
}

//static 
bool 
ClazzAttributesRes::hasAttribute(MetaInfo* mi, IN(RString) key)
{
  if (mi->attributeRes == 0)
    return false;
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  return ar->hasEntry(key->c_str());
}

//static 
ClazzAttributeResValue
ClazzAttributesRes::getInstanceAttribute(MetaInfo* mi, acdk::lang::Object* obj, IN(RString) key)
{
  if (mi->attributeRes == 0)
    return ClazzAttributeResValue();
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  return ar->getInstance(obj, key->c_str());
}

//static 
bool 
ClazzAttributesRes::hasInstanceAttribute(MetaInfo* mi, acdk::lang::Object* obj, IN(RString) key)
{
  if (mi->attributeRes == 0)
    return false;
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  return ar->hasInstanceEntry(obj, key->c_str());
}


//static 
ClazzAttributesRes::ResTable 
ClazzAttributesRes::getAttributes(MetaInfo* mi)
{
  if (mi->attributeRes == 0)
    return ResTable(0);
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  return ar->_entries;
}

//static 
void 
ClazzAttributesRes::deleteMetaAttributes(MetaInfo* mi)
{
  if (mi->attributeRes == 0)
    return;
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  ar->removeAll();
}

//static 
void 
ClazzAttributesRes::deleteMetaAttribute(MetaInfo* mi, IN(RString) key)
{
  if (mi->attributeRes == 0)
    return;
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  ar->remove(key->c_str());
}

//static 
void 
ClazzAttributesRes::deleteInstanceMetaAttribute(MetaInfo* mi, acdk::lang::Object* o, IN(RString) key)
{
  if (mi->attributeRes == 0)
    return;
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  ar->removeInstance(o, key->c_str());

}

//static 
ClazzAttributesRes::ResTable 
ClazzAttributesRes::getInstanceAttributes(MetaInfo* mi, acdk::lang::Object* o)
{
  if (mi->attributeRes == 0)
    return ResTable(0);
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  ClazzAttributeResValue carv = ar->get("__instd_acdk_dmi");
  if (carv.data == 0)
    return ResTable(0);
  RInstanceAttributeData iad = (RInstanceAttributeData)carv.getAsObject();
  ClazzAttributesRes catr = iad->getTable(o);
  return catr._entries;
}

//static 
void 
ClazzAttributesRes::releaseInstanceData2(MetaInfo* mi, acdk::lang::Object* o)
{
  ClazzAttributesRes* ar = (ClazzAttributesRes*)mi->attributeRes;
  ClazzAttributeResValue carv = ar->get("__instd_acdk_dmi");
  if (carv.data == 0)
    return;
  RInstanceAttributeData iad = (RInstanceAttributeData)carv.getAsObject();
  iad->releaseObject(o);
}

} // dmi
} // lang
} // acdk