Skip to content

Commit

Permalink
add map_exists and map_deleted extensions for resetting map values
Browse files Browse the repository at this point in the history
  • Loading branch information
ninjudd committed Dec 4, 2012
1 parent 6251038 commit 0730f8f
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 11 deletions.
2 changes: 2 additions & 0 deletions resources/proto/flatland/protobuf/extensions.proto
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ extend google.protobuf.FieldOptions {
optional string map_by = 52003;
optional bool counter = 52004;
optional bool succession = 52005;
optional string map_deleted = 52006;
optional string map_exists = 52007;
optional string meta = 52010;
optional bool nullable = 52020;
optional string null_string = 52021;
Expand Down
47 changes: 41 additions & 6 deletions src/flatland/protobuf/PersistentProtocolBufferMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,35 @@ public Object clojureEnumValue(Descriptors.EnumValueDescriptor enum_value) {
protected Object mapFieldBy(Descriptors.FieldDescriptor field) {
return intern(field.getOptions().getExtension(Extensions.mapBy));
}

protected PersistentProtocolBufferMap mapValue(Descriptors.FieldDescriptor field,
PersistentProtocolBufferMap left,
PersistentProtocolBufferMap right) {
if (left == null) {
return right;
} else {
Object map_exists = intern(field.getOptions().getExtension(Extensions.mapExists));
if (map_exists != null) {
if (left.valAt(map_exists) == Boolean.FALSE &&
right.valAt(map_exists) == Boolean.TRUE) {
return right;
} else {
return left.append(right);
}
}

Object map_deleted = intern(field.getOptions().getExtension(Extensions.mapDeleted));
if (map_deleted != null) {
if (left.valAt(map_deleted) == Boolean.TRUE &&
right.valAt(map_deleted) == Boolean.FALSE) {
return right;
} else {
return left.append(right);
}
}
return right.append(left);
}
}
}

public final Def def;
Expand Down Expand Up @@ -385,11 +414,7 @@ protected Object fromProtoValue(Descriptors.FieldDescriptor field, Object value,
(PersistentProtocolBufferMap)fromProtoValue(field, iterator.next());
Object k = v.valAt(map_field_by);
PersistentProtocolBufferMap existing = (PersistentProtocolBufferMap)map.valAt(k);
if (existing != null) {
map = map.assoc(k, existing.append(v));
} else {
map = map.assoc(k, v);
}
map = map.assoc(k, def.mapValue(field, existing, v));
}
return map.persistent();
} else if (options.getExtension(Extensions.counter)) {
Expand All @@ -411,7 +436,12 @@ protected Object fromProtoValue(Descriptors.FieldDescriptor field, Object value,
Object k = fromProtoValue(key_field, message.getField(key_field));
Object v = fromProtoValue(val_field, message.getField(val_field));
Object existing = map.valAt(k);
if (existing instanceof IPersistentCollection) {

if (existing instanceof PersistentProtocolBufferMap) {
map = map.assoc(k, def.mapValue(field,
(PersistentProtocolBufferMap)existing,
(PersistentProtocolBufferMap)v));
} else if (existing instanceof IPersistentCollection) {
map = map.assoc(k, ((IPersistentCollection)existing).cons(v));
} else {
map = map.assoc(k, v);
Expand Down Expand Up @@ -702,6 +732,11 @@ public Object getValAt(Object key, Object notFound, boolean use_extensions) {
}
}

protected boolean getBoolean (Object key) {
Object val = valAt(key);
return val != null && val != Boolean.FALSE;
}

@Override
public PersistentProtocolBufferMap assoc(Object key, Object value) {
DynamicMessage.Builder builder = builder();
Expand Down
98 changes: 93 additions & 5 deletions test/flatland/protobuf/core_test.clj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
(def Bar (protodef flatland.protobuf.test.Core$Bar))
(def Response (protodef flatland.protobuf.test.Core$Response))
(def ErrorMsg (protodef flatland.protobuf.test.Core$ErrorMsg))
(def Maps (protodef flatland.protobuf.test.Maps$Struct))

(deftest test-conj
(let [p (protobuf Foo :id 5 :tags ["little" "yellow"] :doubles [1.2 3.4 5.6] :floats [0.01 0.02 0.03])]
Expand Down Expand Up @@ -141,19 +142,106 @@
(is (= ["check" "it" "out"] (p "tags"))))))

(deftest test-append-bytes
(let [p (protobuf Foo :id 5 :label "rad" :tags ["sweet"] :tag-set #{"foo" "bar" "baz"})
q (protobuf Foo :id 43 :tags ["savory"] :tag-set {"bar" false "foo" false "bap" true})
(let [p (protobuf Foo :id 5 :label "rad" :deleted true
:tags ["sweet"] :tag-set #{"foo" "bar" "baz"})
q (protobuf Foo :id 43 :deleted false
:tags ["savory"] :tag-set {"bar" false "foo" false "bap" true})
r (protobuf Foo :label "bad")
s (protobuf-load Foo (catbytes (protobuf-dump p) (protobuf-dump q)))
t (protobuf-load Foo (catbytes (protobuf-dump p) (protobuf-dump r)))]
(is (= 43 (s :id))) ; make sure an explicit default overwrites on append
(is (= 5 (t :id))) ; make sure a missing default doesn't overwrite on append
(is (= 43 (s :id))) ; make sure an explicit default overwrites on append
(is (= 5 (t :id))) ; make sure a missing default doesn't overwrite on append
(is (= "rad" (s :label)))
(is (= "bad" (t :label)))
(is (= ["sweet"] (t :tags)))
(is (= ["sweet" "savory"] (s :tags)))
(is (= #{"foo" "bar" "baz"} (p :tag-set)))
(is (= #{"bap" "baz"} (s :tag-set)))))
(is (= #{"bap" "baz"} (s :tag-set)))
(is (= false (r :deleted)))))

(deftest test-manual-append
(let [p (protobuf Foo :id 5 :label "rad" :deleted true
:tags ["sweet"] :tag-set #{"foo" "bar" "baz"})
q (protobuf Foo :id 43 :deleted false
:tags ["savory"] :tag-set {"bar" false "foo" false "bap" true})
r (protobuf Foo :label "bad")
s (.append p q)
t (.append p r)]
(is (= 43 (s :id))) ; make sure an explicit default overwrites on append
(is (= 5 (t :id))) ; make sure a missing default doesn't overwrite on append
(is (= "rad" (s :label)))
(is (= "bad" (t :label)))
(is (= ["sweet"] (t :tags)))
(is (= ["sweet" "savory"] (s :tags)))
(is (= #{"foo" "bar" "baz"} (p :tag-set)))
(is (= #{"bap" "baz"} (s :tag-set)))
(is (= false (r :deleted)))))

(deftest test-map-exists
(doseq [map-key [:element-map-e :element-by-id-e]]
(let [p (protobuf Maps map-key {"A" {:foo 1}
"B" {:foo 2}
"C" {:foo 3}
"D" {:foo 4 :exists true}
"E" {:foo 5 :exists true}
"F" {:foo 6 :exists true}
"G" {:foo 7 :exists false}
"H" {:foo 8 :exists false}
"I" {:foo 9 :exists false}})
q (protobuf Maps map-key {"A" {:bar 1}
"B" {:bar 2 :exists true}
"C" {:bar 3 :exists false}
"D" {:bar 4}
"E" {:bar 5 :exists true}
"F" {:bar 6 :exists false}
"G" {:bar 7}
"H" {:bar 8 :exists true}
"I" {:bar 9 :exists false}})
r (protobuf-load Maps (catbytes (protobuf-dump p) (protobuf-dump q)))]
(are [key vals] (= vals (map (get-in r [map-key key])
[:foo :bar :exists]))
"A" [1 1 nil ]
"B" [2 2 true ]
"C" [3 3 false]
"D" [4 4 true ]
"E" [5 5 true ]
"F" [6 6 false]
"G" [7 7 false]
"H" [nil 8 true ]
"I" [9 9 false]))))

(deftest test-map-deleted
(doseq [map-key [:element-map-d :element-by-id-d]]
(let [p (protobuf Maps map-key {"A" {:foo 1}
"B" {:foo 2}
"C" {:foo 3}
"D" {:foo 4 :deleted true}
"E" {:foo 5 :deleted true}
"F" {:foo 6 :deleted true}
"G" {:foo 7 :deleted false}
"H" {:foo 8 :deleted false}
"I" {:foo 9 :deleted false}})
q (protobuf Maps map-key {"A" {:bar 1}
"B" {:bar 2 :deleted true}
"C" {:bar 3 :deleted false}
"D" {:bar 4}
"E" {:bar 5 :deleted true}
"F" {:bar 6 :deleted false}
"G" {:bar 7}
"H" {:bar 8 :deleted true}
"I" {:bar 9 :deleted false}})
r (protobuf-load Maps (catbytes (protobuf-dump p) (protobuf-dump q)))]
(are [key vals] (= vals (map (get-in r [map-key key])
[:foo :bar :deleted]))
"A" [1 1 nil ]
"B" [2 2 true ]
"C" [3 3 false]
"D" [4 4 true ]
"E" [5 5 true ]
"F" [nil 6 false]
"G" [7 7 false]
"H" [8 8 true ]
"I" [9 9 false]))))

(deftest test-coercing
(let [p (protobuf Foo :lat 5 :long 6)]
Expand Down

0 comments on commit 0730f8f

Please sign in to comment.