move property getters to object store code

This commit is contained in:
Ari Lazier 2015-10-13 15:25:06 -07:00
parent 77359f14e3
commit 385f387332
10 changed files with 149 additions and 115 deletions

View File

@ -33,7 +33,6 @@
0270BC571B7CFC0D00010E03 /* RJSSchema.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC491B7CFC0D00010E03 /* RJSSchema.mm */; };
0270BC581B7CFC0D00010E03 /* RJSUtil.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC4A1B7CFC0D00010E03 /* RJSUtil.hpp */; settings = {ATTRIBUTES = (Private, ); }; };
0270BC591B7CFC0D00010E03 /* RJSUtil.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC4B1B7CFC0D00010E03 /* RJSUtil.mm */; };
0270BC671B7CFC1C00010E03 /* object_accessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */; };
0270BC681B7CFC1C00010E03 /* object_accessor.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */; };
0270BC691B7CFC1C00010E03 /* object_schema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */; };
0270BC6A1B7CFC1C00010E03 /* object_schema.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */; };
@ -158,7 +157,6 @@
0270BC4A1B7CFC0D00010E03 /* RJSUtil.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = RJSUtil.hpp; path = src/RJSUtil.hpp; sourceTree = "<group>"; };
0270BC4B1B7CFC0D00010E03 /* RJSUtil.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = RJSUtil.mm; path = src/RJSUtil.mm; sourceTree = "<group>"; };
0270BC5A1B7CFC1300010E03 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = src/Info.plist; sourceTree = "<group>"; };
0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_accessor.cpp; path = "src/object-store/object_accessor.cpp"; sourceTree = "<group>"; };
0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = object_accessor.hpp; path = "src/object-store/object_accessor.hpp"; sourceTree = "<group>"; };
0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_schema.cpp; path = "src/object-store/object_schema.cpp"; sourceTree = "<group>"; };
0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = object_schema.hpp; path = "src/object-store/object_schema.hpp"; sourceTree = "<group>"; };
@ -223,7 +221,6 @@
0270BC3D1B7CFBFD00010E03 /* RealmJS */ = {
isa = PBXGroup;
children = (
0270BC5C1B7CFC1C00010E03 /* object_accessor.cpp */,
0270BC5D1B7CFC1C00010E03 /* object_accessor.hpp */,
0270BC5E1B7CFC1C00010E03 /* object_schema.cpp */,
0270BC5F1B7CFC1C00010E03 /* object_schema.hpp */,
@ -574,7 +571,6 @@
02601F031BA0F0C4007C91FF /* external_commit_helper.cpp in Sources */,
0270BC6B1B7CFC1C00010E03 /* object_store.cpp in Sources */,
0270BC701B7CFC1C00010E03 /* shared_realm.cpp in Sources */,
0270BC671B7CFC1C00010E03 /* object_accessor.cpp in Sources */,
0270BC4E1B7CFC0D00010E03 /* RJSArray.cpp in Sources */,
0270BC531B7CFC0D00010E03 /* RJSRealm.mm in Sources */,
);

View File

@ -210,8 +210,8 @@ JSValueRef ArraySplice(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO
return NULL;
}
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List *list) {
return RJSWrapObject<List *>(ctx, RJSArrayClass(), list);
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List &list) {
return RJSWrapObject<List *>(ctx, RJSArrayClass(), new List(list));
}
const JSStaticFunction RJSArrayFuncs[] = {

View File

@ -22,6 +22,6 @@
extern const JSStaticFunction RJSArrayFuncs[];
JSClassRef RJSArrayClass();
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List *list);
JSObjectRef RJSArrayCreate(JSContextRef ctx, realm::List &list);
JSValueRef ArrayGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* jsException);

View File

@ -29,49 +29,15 @@ using RJSAccessor = realm::NativeAccessor<JSValueRef, JSContextRef>;
using namespace realm;
JSValueRef ObjectGetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef* exception) {
Object *obj = RJSGetInternal<Object *>(jsObject);
std::string propName = RJSStringForJSString(jsPropertyName);
ObjectSchema &objectSchema = obj->object_schema;
Property *prop = objectSchema.property_for_name(propName);
if (!prop) {
try {
Object *obj = RJSGetInternal<Object *>(jsObject);
return obj->get_property_value<JSValueRef>(ctx, RJSStringForJSString(jsPropertyName));
} catch (std::exception &ex) {
if (exception) {
*exception = RJSMakeError(ctx, ex);
}
return NULL;
}
switch (prop->type) {
case PropertyTypeBool:
return JSValueMakeBoolean(ctx, obj->row.get_bool(prop->table_column));
case PropertyTypeInt:
return JSValueMakeNumber(ctx, obj->row.get_int(prop->table_column));
case PropertyTypeFloat:
return JSValueMakeNumber(ctx, obj->row.get_float(prop->table_column));
case PropertyTypeDouble:
return JSValueMakeNumber(ctx, obj->row.get_double(prop->table_column));
case PropertyTypeString:
return RJSValueForString(ctx, obj->row.get_string(prop->table_column));
case PropertyTypeData:
return RJSValueForString(ctx, (std::string)obj->row.get_binary(prop->table_column));
case PropertyTypeAny:
*exception = RJSMakeError(ctx, "'Any' type not supported");
return NULL;
case PropertyTypeDate: {
JSValueRef time = JSValueMakeNumber(ctx, obj->row.get_datetime(prop->table_column).get_datetime());
return JSObjectMakeDate(ctx, 1, &time, exception);
}
case PropertyTypeObject: {
auto linkObjectSchema = obj->realm->config().schema->find(prop->object_type);
TableRef table = ObjectStore::table_for_object_type(obj->realm->read_group(), linkObjectSchema->name);
if (obj->row.is_null_link(prop->table_column)) {
return JSValueMakeNull(ctx);
}
return RJSObjectCreate(ctx, Object(obj->realm, *linkObjectSchema, table->get(obj->row.get_link(prop->table_column))));
}
case PropertyTypeArray: {
auto arrayObjectSchema = obj->realm->config().schema->find(prop->object_type);
return RJSArrayCreate(ctx, new List(obj->realm, *arrayObjectSchema, static_cast<LinkViewRef>(obj->row.get_linklist(prop->table_column))));
}
}
return NULL;
}
bool ObjectSetProperty(JSContextRef ctx, JSObjectRef jsObject, JSStringRef jsPropertyName, JSValueRef value, JSValueRef* exception) {
@ -133,6 +99,9 @@ template<> JSValueRef RJSAccessor::default_value_for_property(JSContextRef ctx,
template<> bool RJSAccessor::is_null(JSContextRef ctx, JSValueRef &val) {
return JSValueIsUndefined(ctx, val) || JSValueIsNull(ctx, val);
}
template<> JSValueRef RJSAccessor::null_value(JSContextRef ctx) {
return JSValueMakeNull(ctx);
}
template<> bool RJSAccessor::to_bool(JSContextRef ctx, JSValueRef &val) {
if (!JSValueIsBoolean(ctx, val)) {
@ -140,22 +109,37 @@ template<> bool RJSAccessor::to_bool(JSContextRef ctx, JSValueRef &val) {
}
return JSValueToBoolean(ctx, val);
}
template<> JSValueRef RJSAccessor::from_bool(JSContextRef ctx, bool b) {
return JSValueMakeBoolean(ctx, b);
}
template<> long long RJSAccessor::to_long(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedValueToNumber(ctx, val);
}
template<> JSValueRef RJSAccessor::from_long(JSContextRef ctx, long long l) {
return JSValueMakeNumber(ctx, l);
}
template<> float RJSAccessor::to_float(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedValueToNumber(ctx, val);
}
template<> JSValueRef RJSAccessor::from_float(JSContextRef ctx, float f) {
return JSValueMakeNumber(ctx, f);
}
template<> double RJSAccessor::to_double(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedValueToNumber(ctx, val);
}
template<> JSValueRef RJSAccessor::from_double(JSContextRef ctx, double d) {
return JSValueMakeNumber(ctx, d);
}
template<> std::string RJSAccessor::to_string(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedStringForValue(ctx, val);
}
template<> JSValueRef RJSAccessor::from_string(JSContextRef ctx, StringData s) {
return RJSValueForString(ctx, s);
}
template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val) {
JSObjectRef object = RJSValidatedValueToObject(ctx, val, "Property must be a Date");
@ -176,6 +160,10 @@ template<> DateTime RJSAccessor::to_datetime(JSContextRef ctx, JSValueRef &val)
return DateTime(utc);
}
template<> JSValueRef RJSAccessor::from_datetime(JSContextRef ctx, DateTime dt) {
JSValueRef time = JSValueMakeNumber(ctx, dt.get_datetime());
return JSObjectMakeDate(ctx, 1, &time, NULL);
}
extern JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array);
@ -193,11 +181,16 @@ template<> size_t RJSAccessor::to_object_index(JSContextRef ctx, SharedRealm &re
Object child = Object::create<JSValueRef>(ctx, realm, *object_schema, (JSValueRef)object, try_update);
return child.row.get_index();
}
template<> size_t RJSAccessor::array_size(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedArrayLength(ctx, RJSValidatedValueToObject(ctx, val));
template<> JSValueRef RJSAccessor::from_object(JSContextRef ctx, Object object) {
return RJSObjectCreate(ctx, object);
}
template<> JSValueRef RJSAccessor::array_value_at_index(JSContextRef ctx, JSValueRef &val, size_t index) {
template<> size_t RJSAccessor::list_size(JSContextRef ctx, JSValueRef &val) {
return RJSValidatedListLength(ctx, RJSValidatedValueToObject(ctx, val));
}
template<> JSValueRef RJSAccessor::list_value_at_index(JSContextRef ctx, JSValueRef &val, size_t index) {
return RJSValidatedObjectAtIndex(ctx, RJSValidatedValueToObject(ctx, val), (unsigned int)index);
}
template<> JSValueRef RJSAccessor::from_list(JSContextRef ctx, List list) {
return RJSArrayCreate(ctx, list);
}

View File

@ -221,7 +221,7 @@ JSValueRef RealmObjects(JSContextRef ctx, JSObjectRef function, JSObjectRef this
JSObjectRef RJSDictForPropertyArray(JSContextRef ctx, ObjectSchema &object_schema, JSObjectRef array) {
// copy to dictionary
if (object_schema.properties.size() != RJSValidatedArrayLength(ctx, array)) {
if (object_schema.properties.size() != RJSValidatedListLength(ctx, array)) {
throw std::runtime_error("Array must contain values for all object properties");
}
@ -283,7 +283,7 @@ JSValueRef RealmDelete(JSContextRef ctx, JSObjectRef function, JSObjectRef thisO
JSValueIsObjectOfClass(ctx, arguments[0], RJSArrayClass()))
{
JSObjectRef array = RJSValidatedValueToObject(ctx, arguments[0]);
size_t length = RJSValidatedArrayLength(ctx, array);
size_t length = RJSValidatedListLength(ctx, array);
for (long i = length-1; i >= 0; i--) {
JSValueRef object = RJSValidatedObjectAtIndex(ctx, array, (unsigned int)i);
RealmDelete(ctx, function, thisObject, 1, &object, jsException);

View File

@ -127,7 +127,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
static JSStringRef nameString = JSStringCreateWithUTF8CString("name");
objectSchema.name = RJSValidatedStringProperty(ctx, objectSchemaObject, nameString);
size_t numProperties = RJSValidatedArrayLength(ctx, propertiesObject);
size_t numProperties = RJSValidatedListLength(ctx, propertiesObject);
for (unsigned int p = 0; p < numProperties; p++) {
JSObjectRef property = RJSValidatedObjectAtIndex(ctx, propertiesObject, p);
objectSchema.properties.emplace_back(RJSParseProperty(ctx, property));
@ -163,7 +163,7 @@ static inline ObjectSchema RJSParseObjectSchema(JSContextRef ctx, JSObjectRef ob
realm::Schema RJSParseSchema(JSContextRef ctx, JSObjectRef jsonObject) {
std::vector<ObjectSchema> schema;
size_t length = RJSValidatedArrayLength(ctx, jsonObject);
size_t length = RJSValidatedListLength(ctx, jsonObject);
for (unsigned int i = 0; i < length; i++) {
JSObjectRef jsonObjectSchema = RJSValidatedObjectAtIndex(ctx, jsonObject, i);
ObjectSchema objectSchema = RJSParseObjectSchema(ctx, jsonObjectSchema);

View File

@ -153,7 +153,7 @@ static inline std::string RJSValidatedStringProperty(JSContextRef ctx, JSObjectR
return RJSValidatedStringForValue(ctx, propertyValue);
}
static inline size_t RJSValidatedArrayLength(JSContextRef ctx, JSObjectRef object) {
static inline size_t RJSValidatedListLength(JSContextRef ctx, JSObjectRef object) {
JSValueRef exception = NULL;
static JSStringRef lengthString = JSStringCreateWithUTF8CString("length");
JSValueRef lengthValue = JSObjectGetProperty(ctx, object, lengthString, &exception);

View File

@ -270,7 +270,7 @@ using RPCRequest = std::function<NSDictionary *(NSDictionary *dictionary)>;
};
}
else if (RJSIsValueArray(_context, value)) {
size_t length = RJSValidatedArrayLength(_context, jsObject);
size_t length = RJSValidatedListLength(_context, jsObject);
NSMutableArray *array = [NSMutableArray new];
for (unsigned int i = 0; i < length; i++) {
[array addObject:[self resultForJSValue:JSObjectGetPropertyAtIndex(_context, jsObject, i, NULL)]];

View File

@ -1,19 +0,0 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2015 Realm Inc.
//
// Licensed 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 "object_accessor.hpp"

View File

@ -21,43 +21,9 @@
#include <string>
#include "shared_realm.hpp"
#include "list.hpp"
namespace realm {
template<typename ValueType, typename ContextType>
class NativeAccessor {
public:
//
// Value converters - template specializations must be implemented for each platform
//
static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
static bool to_bool(ContextType ctx, ValueType &val);
static long long to_long(ContextType ctx, ValueType &val);
static float to_float(ContextType ctx, ValueType &val);
static double to_double(ContextType ctx, ValueType &val);
static std::string to_string(ContextType ctx, ValueType &val);
static DateTime to_datetime(ContextType ctx, ValueType &val);
static bool is_null(ContextType ctx, ValueType &val);
// convert value to persisted object
// for existing objects return the existing row index
// for new/updated objects return the row index
static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update);
// array value acessors
static size_t array_size(ContextType ctx, ValueType &val);
static ValueType array_value_at_index(ContextType ctx, ValueType &val, size_t index);
//
// Deprecated
//
static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); }
};
class Object {
public:
@ -67,10 +33,13 @@ namespace realm {
ObjectSchema &object_schema;
Row row;
// property setter
// property getter/setter
template<typename ValueType, typename ContextType>
inline void set_property_value(ContextType ctx, std::string prop_name, ValueType value, bool try_update);
template<typename ValueType, typename ContextType>
inline ValueType get_property_value(ContextType ctx, std::string prop_name);
// create an Object from a native representation
template<typename ValueType, typename ContextType>
static inline Object create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update);
@ -78,6 +47,53 @@ namespace realm {
private:
template<typename ValueType, typename ContextType>
inline void set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update);
template<typename ValueType, typename ContextType>
inline ValueType get_property_value_impl(ContextType ctx, Property &property);
};
//
// Value converters - template specializations must be implemented for each platform in order to call templated methods on Object
//
template<typename ValueType, typename ContextType>
class NativeAccessor {
public:
static bool dict_has_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
static ValueType dict_value_for_key(ContextType ctx, ValueType dict, const std::string &prop_name);
static bool has_default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
static ValueType default_value_for_property(ContextType ctx, const ObjectSchema &object_schema, const std::string &prop_name);
static bool to_bool(ContextType, ValueType &);
static ValueType from_bool(ContextType, bool);
static long long to_long(ContextType, ValueType &);
static ValueType from_long(ContextType, long long);
static float to_float(ContextType, ValueType &);
static ValueType from_float(ContextType, float);
static double to_double(ContextType, ValueType &);
static ValueType from_double(ContextType, double);
static std::string to_string(ContextType, ValueType &);
static ValueType from_string(ContextType, StringData);
static DateTime to_datetime(ContextType, ValueType &);
static ValueType from_datetime(ContextType, DateTime);
static bool is_null(ContextType, ValueType &);
static ValueType null_value(ContextType);
// convert value to persisted object
// for existing objects return the existing row index
// for new/updated objects return the row index
static size_t to_object_index(ContextType ctx, SharedRealm &realm, ValueType &val, std::string &type, bool try_update);
static ValueType from_object(ContextType ctx, Object);
// list value acessors
static size_t list_size(ContextType ctx, ValueType &val);
static ValueType list_value_at_index(ContextType ctx, ValueType &val, size_t index);
static ValueType from_list(ContextType ctx, List);
//
// Deprecated
//
static Mixed to_mixed(ContextType ctx, ValueType &val) { throw std::runtime_error("'Any' type is unsupported"); }
};
//
@ -93,6 +109,16 @@ namespace realm {
set_property_value_impl(ctx, *prop, value, try_update);
};
template <typename ValueType, typename ContextType>
inline ValueType Object::get_property_value(ContextType ctx, std::string prop_name)
{
Property *prop = object_schema.property_for_name(prop_name);
if (!prop) {
throw std::runtime_error("Setting invalid property '" + prop_name + "' on object '" + object_schema.name + "'.");
}
return get_property_value_impl<ValueType>(ctx, *prop);
};
template <typename ValueType, typename ContextType>
inline void Object::set_property_value_impl(ContextType ctx, Property &property, ValueType value, bool try_update)
{
@ -140,9 +166,9 @@ namespace realm {
case PropertyTypeArray: {
realm::LinkViewRef link_view = row.get_linklist(column);
link_view->clear();
size_t count = Accessor::array_size(ctx, value);
size_t count = Accessor::list_size(ctx, value);
for (size_t i = 0; i < count; i++) {
ValueType element = Accessor::array_value_at_index(ctx, value, i);
ValueType element = Accessor::list_value_at_index(ctx, value, i);
link_view->add(Accessor::to_object_index(ctx, realm, element, property.object_type, try_update));
}
break;
@ -150,6 +176,44 @@ namespace realm {
}
}
template <typename ValueType, typename ContextType>
inline ValueType Object::get_property_value_impl(ContextType ctx, Property &property)
{
using Accessor = NativeAccessor<ValueType, ContextType>;
size_t column = property.table_column;
switch (property.type) {
case PropertyTypeBool:
return Accessor::from_bool(ctx, row.get_bool(column));
case PropertyTypeInt:
return Accessor::from_long(ctx, row.get_int(column));
case PropertyTypeFloat:
return Accessor::from_float(ctx, row.get_float(column));
case PropertyTypeDouble:
return Accessor::from_double(ctx, row.get_double(column));
case PropertyTypeString:
return Accessor::from_string(ctx, row.get_string(column));
case PropertyTypeData:
return Accessor::from_string(ctx, (std::string)row.get_binary(column));
case PropertyTypeAny:
throw "Any not supported";
case PropertyTypeDate:
return Accessor::from_datetime(ctx, row.get_datetime(column));
case PropertyTypeObject: {
auto linkObjectSchema = realm->config().schema->find(property.object_type);
TableRef table = ObjectStore::table_for_object_type(realm->read_group(), linkObjectSchema->name);
if (row.is_null_link(property.table_column)) {
return Accessor::null_value(ctx);
}
return Accessor::from_object(ctx, std::move(Object(realm, *linkObjectSchema, table->get(row.get_link(column)))));
}
case PropertyTypeArray: {
auto arrayObjectSchema = realm->config().schema->find(property.object_type);
return Accessor::from_list(ctx, std::move(List(realm, *arrayObjectSchema, static_cast<LinkViewRef>(row.get_linklist(column)))));
}
}
}
template<typename ValueType, typename ContextType>
inline Object Object::create(ContextType ctx, SharedRealm realm, ObjectSchema &object_schema, ValueType value, bool try_update)
{