require "atom" require "azure/tables/types" module Azure # Collection of XML::Node extensions for generating Atom feeds. module Atom Entry = ::Atom::Entry Feed = ::Atom::Feed # Generates a Data Property, making sure that it's in the correct namespace # (dataservices). class Property < XML::Node # Public: Set up the property. # # name - The property name, without the namespace qualification. # value - The property's value. def initialize(name, value) super("d:#{name}") self << value end # Public: Set the property's value, and sets the content type based on the # value's type. # # value - The value of the property. # # Returns self. def <<(value) self["m:type"] = Azure::Tables::Types.type_of(value) super(value) end def to_xml(*) self end end # Represent a list of properties in the proper namespace # (dataservices/metadata). class PropertyList < XML::Node include ::Atom::Xml::Parseable add_extension_namespace "d", "http://schemas.microsoft.com/ado/2007/08/dataservices" # Public: Initialize the property list. # # Yields the PropertyList. def initialize(o=nil) super("m:properties") if o && o.is_a?(LibXML::XML::Reader) o.node.children.each do |node| self << node.copy(true) unless node.blank? end end yield self if block_given? end # Public: Add several properties at the same time. # # properties - A Hash of property name => property value pairs. # # Returns the passed properties. def merge(properties) properties.each do |name, value| self[name] = value end end # Public: Add a property to this list. This will internally store a # Atom::Nodes::Property object. # # property - The name of the property to be included. # value - The value of the property. # # Returns nothing. def []=(property, value) self << Property.new(property, value) end def to_xml(*) self end end # Represent an entry's tag, ensuring it has the correct content # type and that it conforms to the Atom::Content interface so it can be used # seamlessly with Atom::Entry objects. class Content < XML::Node include ::Atom::Xml::Parseable add_extension_namespace "m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" element "m:properties", class: Azure::Atom::PropertyList # Public: Initialize the content node. # # Yields self. def initialize(o=nil) super("content") self["type"] = "application/xml" if o && o.is_a?(LibXML::XML::Reader) o.read_inner_xml o.read parse o end yield self if block_given? end # Public: Cast this object into something Atom::Entry can understand as # content. By returning itself (as a Node) the Entry won't try to escape # this as CDATA. # # Returns self. def to_xml(*) self end end end end # FIXME: The rAtom gem doesn't play well when you extend your classes, raising # weird errors, so we're monkeypatching their classes. This *sucks*. module Atom # Public: An Atom feed, that understands the Microsoft ADO namespaces for Data # services. class Feed add_extension_namespace "d", "http://schemas.microsoft.com/ado/2007/08/dataservices" add_extension_namespace "m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" end # Public: An Atom entry, that understands the Microsoft ADO namespaces for Data # services. class Entry add_extension_namespace "d", "http://schemas.microsoft.com/ado/2007/08/dataservices" add_extension_namespace "m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" element "content", class: Azure::Atom::Content # Public: Generate a list of data properties to include in this Entry's # content. # FIXME: This method isn't very confident as getter, use content.m_properties instead. # # Yields a Nodes::PropertyList. # # Example: # # entry.properties do |props| # props["one"] = 1 # props["two"] = 2 # end # # Returns the XML node for entry's . def properties(&block) if !@content @content = Azure::Atom::Content.new @m_properties = Azure::Atom::PropertyList.new @content << @m_properties end yield @m_properties if block_given? @m_properties end end end