You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltacloud.apache.org by mf...@apache.org on 2012/10/11 10:33:28 UTC
[2/7] git commit: CIMI: call a 'prepare' method on models before
serializing
CIMI: call a 'prepare' method on models before serializing
This gives us an opportunity to
* set the count of collections to the number of entries
* generate id's for collections embedded in other objects
TrackedAt: http://tracker.deltacloud.org/patch/b358598ddf5196da612692b6b8791a566507d434
Project: http://git-wip-us.apache.org/repos/asf/deltacloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltacloud/commit/01feb536
Tree: http://git-wip-us.apache.org/repos/asf/deltacloud/tree/01feb536
Diff: http://git-wip-us.apache.org/repos/asf/deltacloud/diff/01feb536
Branch: refs/heads/master
Commit: 01feb53669c5c22697ca1b903715b64ae6708d6f
Parents: d7dd769
Author: David Lutterkort <lu...@redhat.com>
Authored: Fri Oct 5 17:30:52 2012 -0700
Committer: Michal fojtik <mf...@redhat.com>
Committed: Thu Oct 11 10:31:08 2012 +0200
----------------------------------------------------------------------
server/lib/cimi/models/base.rb | 6 +
server/lib/cimi/models/collection.rb | 18 +++
server/lib/cimi/models/schema.rb | 4 +
server/tests/cimi/spec/cimi/data/container.json | 8 +
server/tests/cimi/spec/cimi/data/container.xml | 9 ++
.../tests/cimi/spec/cimi/model/collection_spec.rb | 109 +++++++++++++++
6 files changed, 154 insertions(+), 0 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/01feb536/server/lib/cimi/models/base.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/base.rb b/server/lib/cimi/models/base.rb
index 2e66694..fe6016d 100644
--- a/server/lib/cimi/models/base.rb
+++ b/server/lib/cimi/models/base.rb
@@ -166,6 +166,12 @@ class CIMI::Model::Base
def []=(a, v)
@attribute_values[a] = self.class.schema.convert(a, v)
end
+
+ # Prepare to serialize
+ def prepare
+ self.class.schema.collections.map { |coll| coll.name }.each do |n|
+ self[n].href = "#{self.id}/#{n}" unless self[n].href
+ end
end
#
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/01feb536/server/lib/cimi/models/collection.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/collection.rb b/server/lib/cimi/models/collection.rb
index 86fa09b..db08047 100644
--- a/server/lib/cimi/models/collection.rb
+++ b/server/lib/cimi/models/collection.rb
@@ -27,12 +27,30 @@ module CIMI::Model
if values[:entries]
values[self.class.entry_name] = values.delete(:entries)
end
+ values[self.class.entry_name] ||= []
super(values)
end
def entries
self[self.class.entry_name]
end
+
+ # Prepare to serialize
+ def prepare
+ self.count = self.entries.size
+ self.count = nil if self.count == 0
+ if self.class.embedded
+ ["id", "href"].each { |a| self[a] = nil if self[a] == "" }
+ # Handle href and id, which are really just aliases of one another
+ unless self.href || self.id
+ raise "Collection #{self.class.name} must have one of id and href set"
+ end
+ if self.href && self.id && self.href != self.id
+ raise "id and href must be identical for collection #{self.class.name}, id = #{id.inspect}, href = #{href.inspect}"
+ end
+ self.href ||= self.id
+ self.id ||= self.href
+ end
end
def [](a)
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/01feb536/server/lib/cimi/models/schema.rb
----------------------------------------------------------------------
diff --git a/server/lib/cimi/models/schema.rb b/server/lib/cimi/models/schema.rb
index cf8381a..e9504e9 100644
--- a/server/lib/cimi/models/schema.rb
+++ b/server/lib/cimi/models/schema.rb
@@ -234,6 +234,7 @@ class CIMI::Model::Schema
end
def to_xml(model, xml)
+ model[name].prepare
if model[name].count.nil?
xml[xml_name] = { "href" => model[name].href }
else
@@ -242,6 +243,7 @@ class CIMI::Model::Schema
end
def to_json(model, json)
+ model[name].prepare
if model[name].count.nil?
json[json_name] = { "href" => model[name].href }
else
@@ -294,6 +296,7 @@ class CIMI::Model::Schema
def to_xml(model, xml = nil)
xml ||= OrderedHash.new
@attributes.freeze
+ model.prepare if model.respond_to?(:prepare)
@attributes.each { |attr| attr.to_xml(model, xml) }
xml
end
@@ -309,6 +312,7 @@ class CIMI::Model::Schema
def to_json(model, json = {})
@attributes.freeze
+ model.prepare if model.respond_to?(:prepare)
@attributes.each { |attr| attr.to_json(model, json) }
json
end
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/01feb536/server/tests/cimi/spec/cimi/data/container.json
----------------------------------------------------------------------
diff --git a/server/tests/cimi/spec/cimi/data/container.json b/server/tests/cimi/spec/cimi/data/container.json
new file mode 100644
index 0000000..522c6f2
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/container.json
@@ -0,0 +1,8 @@
+{ "id": "http://example.com/cimi",
+ "models": {
+ "href": "http://example.com/cimi/models",
+ "count": 2,
+ "id": "http://example.com/cimi/models",
+ "models": [ {"text":"m1"}, {"text":"m2"} ]
+ }
+}
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/01feb536/server/tests/cimi/spec/cimi/data/container.xml
----------------------------------------------------------------------
diff --git a/server/tests/cimi/spec/cimi/data/container.xml b/server/tests/cimi/spec/cimi/data/container.xml
new file mode 100644
index 0000000..eec6ab7
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/data/container.xml
@@ -0,0 +1,9 @@
+<Container xmlns="http://schemas.dmtf.org/cimi/1">
+ <id>http://example.com/cimi</id>
+ <models href="http://example.com/cimi/models">
+ <id>http://example.com/cimi/models</id>
+ <count>2</count>
+ <Model text="m1" />
+ <Model text="m2" />
+ </models>
+</Container>
http://git-wip-us.apache.org/repos/asf/deltacloud/blob/01feb536/server/tests/cimi/spec/cimi/model/collection_spec.rb
----------------------------------------------------------------------
diff --git a/server/tests/cimi/spec/cimi/model/collection_spec.rb b/server/tests/cimi/spec/cimi/model/collection_spec.rb
new file mode 100644
index 0000000..a3a43c0
--- /dev/null
+++ b/server/tests/cimi/spec/cimi/model/collection_spec.rb
@@ -0,0 +1,109 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you 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.
+#
+require 'rubygems'
+require 'require_relative' if RUBY_VERSION < '1.9'
+
+require_relative '../../spec_helper.rb' if require 'minitest/autorun'
+
+require 'nokogiri'
+require 'json'
+
+describe "Collection class" do
+
+ BASE_URL = "http://example.com/cimi"
+ COLL_URL = BASE_URL + "/models"
+
+ class Model < CIMI::Model::Base
+ scalar :text
+ end
+
+ class Container < CIMI::Model::Base
+ collection :models, :class => Model
+ end
+
+ before do
+ @models = ["m1", "m2"].map { |s| Model.new(:text => s) }
+ @xml = IO::read(File::join(DATA_DIR, "container.xml"))
+ @json = IO::read(File::join(DATA_DIR, "container.json"))
+ end
+
+ describe "XML serialization" do
+ it "empty collection only has href" do
+ cont = Container.new(:id => BASE_URL)
+ doc = to_dom(cont)
+
+ (doc/"/c:Container/c:models/@href").text.must_equal COLL_URL
+ (doc/"/c:Container/c:models/c:id").size.must_equal 0
+ end
+
+ it "contains count of models" do
+ cont = Container.new(:id => BASE_URL, :models => @models)
+ doc = to_dom(cont)
+
+ (doc/"/c:Container/c:models/c:count").text.must_equal "2"
+ (doc/"/c:Container/c:models/c:Model").size.must_equal 2
+ end
+ end
+
+ describe "JSON serialization" do
+ it "empty collection only has href" do
+ cont = Container.new(:id => BASE_URL)
+ json = to_json(cont)
+
+ json["models"]["href"].must_equal COLL_URL
+ json["models"].keys.must_equal ["href"]
+ end
+
+ it "contains count of models" do
+ cont = Container.new(:id => BASE_URL, :models => @models)
+ json = to_json(cont)
+
+ json["models"]["count"].must_equal 2
+ json["models"]["models"].size.must_equal 2
+ end
+ end
+
+ it "deserializes from XML" do
+ cont = Container.from_xml(@xml)
+ cont.id.must_equal BASE_URL
+ cont.models.count.must_equal "2"
+ cont.models.entries.size.must_equal 2
+ cont.models.entries[0].text.must_equal "m1"
+ cont.models.entries[1].text.must_equal "m2"
+ end
+
+ it "deserializes from JSON" do
+ cont = Container.from_json(@json)
+ cont.id.must_equal BASE_URL
+ # FIXME: This is a very annoying difference between XML and JSON; in XML
+ # all scalars are strings, in JSON, strings that look like integers are
+ # converted to integer objects
+ cont.models.count.must_equal 2
+ cont.models.entries.size.must_equal 2
+ cont.models.entries[0].text.must_equal "m1"
+ cont.models.entries[1].text.must_equal "m2"
+ end
+
+ def to_dom(model)
+ doc = Nokogiri::XML(model.to_xml)
+ doc.root.add_namespace("c", doc.namespaces["xmlns"])
+ doc
+ end
+
+ def to_json(model)
+ JSON.parse(model.to_json)
+ end
+end