Floppy-amee 0.4.33 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/amee.rb +37 -1
- data/lib/amee/connection.rb +52 -27
- data/lib/amee/exceptions.rb +3 -3
- data/lib/amee/profile_category.rb +217 -10
- data/lib/amee/profile_item.rb +175 -20
- data/lib/amee/version.rb +3 -3
- metadata +2 -2
    
        data/lib/amee.rb
    CHANGED
    
    | @@ -11,6 +11,18 @@ class String | |
| 11 11 | 
             
              def is_json?
         | 
| 12 12 | 
             
                slice(0,1) == '{'
         | 
| 13 13 | 
             
              end
         | 
| 14 | 
            +
              def is_v2_json?
         | 
| 15 | 
            +
                is_json? && match('"apiVersion".*?:.*?"2.0"')
         | 
| 16 | 
            +
              end
         | 
| 17 | 
            +
              def is_xml?
         | 
| 18 | 
            +
                slice(0,5) == '<?xml'
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
              def is_v2_xml?
         | 
| 21 | 
            +
                is_xml? && include?('<Resources xmlns="http://schemas.amee.cc/2.0">')
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
              def is_v2_atom?
         | 
| 24 | 
            +
                is_xml? && (include?('<feed ') || include?('<entry ')) && include?('xmlns:amee="http://schemas.amee.cc/2.0"')
         | 
| 25 | 
            +
              end
         | 
| 14 26 | 
             
            end
         | 
| 15 27 |  | 
| 16 28 | 
             
            require 'amee/version'
         | 
| @@ -25,4 +37,28 @@ require 'amee/data_item_value' | |
| 25 37 | 
             
            require 'amee/profile'
         | 
| 26 38 | 
             
            require 'amee/profile_category'
         | 
| 27 39 | 
             
            require 'amee/profile_item'
         | 
| 28 | 
            -
            require 'amee/drill_down'
         | 
| 40 | 
            +
            require 'amee/drill_down'
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            class Date
         | 
| 43 | 
            +
              def amee2schema
         | 
| 44 | 
            +
                strftime("%Y-%m-%dT%H:%M+0000")
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
              def amee1_date
         | 
| 47 | 
            +
                strftime("%Y%m%d")
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
              def amee1_month
         | 
| 50 | 
            +
                strftime("%Y%m")
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
            end
         | 
| 53 | 
            +
             | 
| 54 | 
            +
            class Time
         | 
| 55 | 
            +
              def amee2schema
         | 
| 56 | 
            +
                strftime("%Y-%m-%dT%H:%M+0000")
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
              def amee1_date
         | 
| 59 | 
            +
                strftime("%Y%m%d")
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
              def amee1_month
         | 
| 62 | 
            +
                strftime("%Y%m")
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
            end
         | 
    
        data/lib/amee/connection.rb
    CHANGED
    
    | @@ -3,24 +3,29 @@ require 'net/http' | |
| 3 3 | 
             
            module AMEE
         | 
| 4 4 | 
             
              class Connection
         | 
| 5 5 |  | 
| 6 | 
            -
                def initialize(server, username | 
| 6 | 
            +
                def initialize(server, username, password, options = {})
         | 
| 7 | 
            +
                  unless options.is_a?(Hash)
         | 
| 8 | 
            +
                    raise AMEE::ArgumentError.new("Fourth argument must be a hash of options!")
         | 
| 9 | 
            +
                  end
         | 
| 7 10 | 
             
                  @server = server
         | 
| 8 11 | 
             
                  @username = username
         | 
| 9 12 | 
             
                  @password = password
         | 
| 10 13 | 
             
                  @auth_token = nil
         | 
| 11 | 
            -
                  @ | 
| 12 | 
            -
                  if  | 
| 13 | 
            -
                   raise " | 
| 14 | 
            +
                  @format = options[:format] || (defined?(JSON) ? :json : :xml)
         | 
| 15 | 
            +
                  if !valid?
         | 
| 16 | 
            +
                   raise "You must supply connection details - server, username and password are all required!"
         | 
| 14 17 | 
             
                  end
         | 
| 15 | 
            -
                  @enable_caching = enable_caching
         | 
| 18 | 
            +
                  @enable_caching = options[:enable_caching]
         | 
| 16 19 | 
             
                  if @enable_caching
         | 
| 17 20 | 
             
                    $cache ||= {}
         | 
| 18 21 | 
             
                  end
         | 
| 19 22 | 
             
                  # Make connection to server
         | 
| 20 23 | 
             
                  @http = Net::HTTP.new(@server)
         | 
| 21 24 | 
             
                  @http.read_timeout = 5
         | 
| 22 | 
            -
                  @http.set_debug_output($stdout) if enable_debug
         | 
| 25 | 
            +
                  @http.set_debug_output($stdout) if options[:enable_debug]
         | 
| 23 26 | 
             
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                attr_reader :format
         | 
| 24 29 |  | 
| 25 30 | 
             
                def timeout
         | 
| 26 31 | 
             
                  @http.read_timeout
         | 
| @@ -30,19 +35,21 @@ module AMEE | |
| 30 35 | 
             
                  @http.read_timeout = t
         | 
| 31 36 | 
             
                end
         | 
| 32 37 |  | 
| 38 | 
            +
                def version
         | 
| 39 | 
            +
                  @version
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 33 42 | 
             
                def valid?
         | 
| 34 | 
            -
                   | 
| 43 | 
            +
                  @username && @password && @server
         | 
| 35 44 | 
             
                end
         | 
| 36 45 |  | 
| 37 | 
            -
                def can_authenticate?
         | 
| 38 | 
            -
                  !(@username.nil? || @password.nil?)
         | 
| 39 | 
            -
                end
         | 
| 40 | 
            -
             | 
| 41 46 | 
             
                def authenticated?
         | 
| 42 47 | 
             
                  !@auth_token.nil?
         | 
| 43 48 | 
             
                end
         | 
| 44 49 |  | 
| 45 50 | 
             
                def get(path, data = {})
         | 
| 51 | 
            +
                  # Allow format override
         | 
| 52 | 
            +
                  format = data.delete(:format) || @format
         | 
| 46 53 | 
             
                  # Create URL parameters
         | 
| 47 54 | 
             
                  params = []
         | 
| 48 55 | 
             
                  data.each_pair do |key, value|
         | 
| @@ -53,12 +60,15 @@ module AMEE | |
| 53 60 | 
             
                  end
         | 
| 54 61 | 
             
                  # Send request
         | 
| 55 62 | 
             
                  return $cache[path] if @enable_caching and $cache[path]
         | 
| 56 | 
            -
                  response = do_request | 
| 63 | 
            +
                  response = do_request(Net::HTTP::Get.new(path), format)
         | 
| 57 64 | 
             
                  $cache[path] = response if @enable_caching
         | 
| 58 65 | 
             
                  return response
         | 
| 59 66 | 
             
                end
         | 
| 60 67 |  | 
| 61 68 | 
             
                def post(path, data = {})
         | 
| 69 | 
            +
                  # Allow format override
         | 
| 70 | 
            +
                  format = data.delete(:format) || @format
         | 
| 71 | 
            +
                  # Clear cache
         | 
| 62 72 | 
             
                  clear_cache
         | 
| 63 73 | 
             
                  # Create POST request
         | 
| 64 74 | 
             
                  post = Net::HTTP::Post.new(path)
         | 
| @@ -68,10 +78,13 @@ module AMEE | |
| 68 78 | 
             
                  end
         | 
| 69 79 | 
             
                  post.body = body.join '&'
         | 
| 70 80 | 
             
                  # Send request
         | 
| 71 | 
            -
                  do_request(post)
         | 
| 81 | 
            +
                  do_request(post, format)
         | 
| 72 82 | 
             
                end
         | 
| 73 83 |  | 
| 74 84 | 
             
                def put(path, data = {})
         | 
| 85 | 
            +
                  # Allow format override
         | 
| 86 | 
            +
                  format = data.delete(:format) || @format
         | 
| 87 | 
            +
                  # Clear cache
         | 
| 75 88 | 
             
                  clear_cache
         | 
| 76 89 | 
             
                  # Create PUT request
         | 
| 77 90 | 
             
                  put = Net::HTTP::Put.new(path)
         | 
| @@ -81,7 +94,7 @@ module AMEE | |
| 81 94 | 
             
                  end
         | 
| 82 95 | 
             
                  put.body = body.join '&'
         | 
| 83 96 | 
             
                  # Send request
         | 
| 84 | 
            -
                  do_request(put)
         | 
| 97 | 
            +
                  do_request(put, format)
         | 
| 85 98 | 
             
                end
         | 
| 86 99 |  | 
| 87 100 | 
             
                def delete(path)
         | 
| @@ -93,24 +106,36 @@ module AMEE | |
| 93 106 | 
             
                end
         | 
| 94 107 |  | 
| 95 108 | 
             
                def authenticate
         | 
| 96 | 
            -
                  unless can_authenticate?        
         | 
| 97 | 
            -
                    raise AMEE::AuthRequired.new("Authentication required. Please provide your username and password.")
         | 
| 98 | 
            -
                  end
         | 
| 99 109 | 
             
                  response = nil
         | 
| 100 | 
            -
                  post = Net::HTTP::Post.new("/auth")
         | 
| 110 | 
            +
                  post = Net::HTTP::Post.new("/auth/signIn")
         | 
| 101 111 | 
             
                  post.body = "username=#{@username}&password=#{@password}"
         | 
| 102 | 
            -
                  post['Accept'] = content_type
         | 
| 112 | 
            +
                  post['Accept'] = content_type(:xml)
         | 
| 103 113 | 
             
                  response = @http.request(post)
         | 
| 104 114 | 
             
                  @auth_token = response['authToken']
         | 
| 105 115 | 
             
                  unless authenticated?
         | 
| 106 116 | 
             
                    raise AMEE::AuthFailed.new("Authentication failed. Please check your username and password.") 
         | 
| 107 117 | 
             
                  end
         | 
| 118 | 
            +
                  # Detect API version
         | 
| 119 | 
            +
                  if response.body.is_json?
         | 
| 120 | 
            +
                    @version = JSON.parse(response.body)["user"]["apiVersion"].to_f
         | 
| 121 | 
            +
                  elsif response.body.is_xml?
         | 
| 122 | 
            +
                    @version = REXML::Document.new(response.body).elements['Resources'].elements['SignInResource'].elements['User'].elements['ApiVersion'].text.to_f
         | 
| 123 | 
            +
                  else
         | 
| 124 | 
            +
                    @version = 1.0
         | 
| 125 | 
            +
                  end
         | 
| 108 126 | 
             
                end
         | 
| 109 127 |  | 
| 110 128 | 
             
                protected
         | 
| 111 129 |  | 
| 112 | 
            -
                def content_type
         | 
| 113 | 
            -
                   | 
| 130 | 
            +
                def content_type(format = @format)
         | 
| 131 | 
            +
                  case format
         | 
| 132 | 
            +
                  when :xml
         | 
| 133 | 
            +
                    return 'application/xml'
         | 
| 134 | 
            +
                  when :json
         | 
| 135 | 
            +
                    return 'application/json'
         | 
| 136 | 
            +
                  when :atom
         | 
| 137 | 
            +
                    return 'application/atom+xml'
         | 
| 138 | 
            +
                  end
         | 
| 114 139 | 
             
                end
         | 
| 115 140 |  | 
| 116 141 | 
             
                def redirect?(response)
         | 
| @@ -122,21 +147,21 @@ module AMEE | |
| 122 147 | 
             
                    when '200'
         | 
| 123 148 | 
             
                      return true
         | 
| 124 149 | 
             
                    when '403'
         | 
| 125 | 
            -
                      raise AMEE::PermissionDenied.new("You do not have permission to perform the requested operation")
         | 
| 150 | 
            +
                      raise AMEE::PermissionDenied.new("You do not have permission to perform the requested operation. AMEE Response: #{response.body}")
         | 
| 126 151 | 
             
                    when '401'
         | 
| 127 152 | 
             
                      authenticate
         | 
| 128 153 | 
             
                      return false
         | 
| 129 154 | 
             
                    else
         | 
| 130 | 
            -
                      raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}")
         | 
| 155 | 
            +
                      raise AMEE::UnknownError.new("An error occurred while talking to AMEE: HTTP response code #{response.code}. AMEE Response: #{response.body}")
         | 
| 131 156 | 
             
                  end
         | 
| 132 157 | 
             
                end
         | 
| 133 158 |  | 
| 134 | 
            -
                def do_request(request)
         | 
| 159 | 
            +
                def do_request(request, format = @format)
         | 
| 135 160 | 
             
                  # Open HTTP connection
         | 
| 136 161 | 
             
                  @http.start
         | 
| 137 162 | 
             
                  # Do request
         | 
| 138 163 | 
             
                  begin
         | 
| 139 | 
            -
                    response = send_request(request)
         | 
| 164 | 
            +
                    response = send_request(request, format)
         | 
| 140 165 | 
             
                  end while !response_ok?(response)
         | 
| 141 166 | 
             
                  # Return body of response
         | 
| 142 167 | 
             
                  return response.body
         | 
| @@ -147,9 +172,9 @@ module AMEE | |
| 147 172 | 
             
                  @http.finish if @http.started?
         | 
| 148 173 | 
             
                end
         | 
| 149 174 |  | 
| 150 | 
            -
                def send_request(request)
         | 
| 175 | 
            +
                def send_request(request, format = @format)
         | 
| 151 176 | 
             
                  request['authToken'] = @auth_token
         | 
| 152 | 
            -
                  request['Accept'] = content_type
         | 
| 177 | 
            +
                  request['Accept'] = content_type(format)
         | 
| 153 178 | 
             
                  response = @http.request(request)
         | 
| 154 179 | 
             
                  # Handle 404s
         | 
| 155 180 | 
             
                  if response.code == '404'
         | 
    
        data/lib/amee/exceptions.rb
    CHANGED
    
    
| @@ -7,13 +7,15 @@ module AMEE | |
| 7 7 | 
             
                  def initialize(data = {})
         | 
| 8 8 | 
             
                    @children = data ? data[:children] : []
         | 
| 9 9 | 
             
                    @items = data ? data[:items] : []
         | 
| 10 | 
            -
                    @ | 
| 10 | 
            +
                    @total_amount = data[:total_amount]
         | 
| 11 | 
            +
                    @total_amount_unit = data[:total_amount_unit]
         | 
| 11 12 | 
             
                    super
         | 
| 12 13 | 
             
                  end
         | 
| 13 14 |  | 
| 14 15 | 
             
                  attr_reader :children
         | 
| 15 16 | 
             
                  attr_reader :items
         | 
| 16 | 
            -
                  attr_reader : | 
| 17 | 
            +
                  attr_reader :total_amount
         | 
| 18 | 
            +
                  attr_reader :total_amount_unit
         | 
| 17 19 |  | 
| 18 20 | 
             
                  def self.parse_json_profile_item(item)
         | 
| 19 21 | 
             
                    item_data = {}
         | 
| @@ -22,14 +24,33 @@ module AMEE | |
| 22 24 | 
             
                      case key
         | 
| 23 25 | 
             
                        when 'dataItemLabel', 'dataItemUid', 'name', 'path', 'uid'
         | 
| 24 26 | 
             
                          item_data[key.to_sym] = value
         | 
| 27 | 
            +
                        when 'dataItem'
         | 
| 28 | 
            +
                          item_data[:dataItemLabel] = value['Label']
         | 
| 29 | 
            +
                          item_data[:dataItemUid] = value['uid']
         | 
| 25 30 | 
             
                        when 'created', 'modified', 'label' # ignore these
         | 
| 26 31 | 
             
                          nil
         | 
| 27 32 | 
             
                        when 'validFrom'
         | 
| 28 33 | 
             
                          item_data[:validFrom] = DateTime.strptime(value, "%Y%m%d")
         | 
| 34 | 
            +
                        when 'startDate'
         | 
| 35 | 
            +
                          item_data[:startDate] = DateTime.parse(value)
         | 
| 36 | 
            +
                        when 'endDate'
         | 
| 37 | 
            +
                          item_data[:endDate] = DateTime.parse(value) rescue nil
         | 
| 29 38 | 
             
                        when 'end'
         | 
| 30 39 | 
             
                          item_data[:end] = (value == "true")
         | 
| 31 40 | 
             
                        when 'amountPerMonth'
         | 
| 32 41 | 
             
                          item_data[:amountPerMonth] = value.to_f
         | 
| 42 | 
            +
                        when 'amount'
         | 
| 43 | 
            +
                          item_data[:amount] = value['value'].to_f
         | 
| 44 | 
            +
                          item_data[:amount_unit] = value['unit']
         | 
| 45 | 
            +
                        when 'itemValues'
         | 
| 46 | 
            +
                          value.each do |itemval|
         | 
| 47 | 
            +
                            path = itemval['path'].to_sym
         | 
| 48 | 
            +
                            item_data[:values][path.to_sym] = {}
         | 
| 49 | 
            +
                            item_data[:values][path.to_sym][:name] = itemval['name']
         | 
| 50 | 
            +
                            item_data[:values][path.to_sym][:value] = itemval['value']
         | 
| 51 | 
            +
                            item_data[:values][path.to_sym][:unit] = itemval['unit']
         | 
| 52 | 
            +
                            item_data[:values][path.to_sym][:per_unit] = itemval['perUnit']
         | 
| 53 | 
            +
                          end
         | 
| 33 54 | 
             
                        else
         | 
| 34 55 | 
             
                          item_data[:values][key.to_sym] = value
         | 
| 35 56 | 
             
                      end
         | 
| @@ -72,7 +93,8 @@ module AMEE | |
| 72 93 | 
             
                    data[:profile_date] = DateTime.strptime(doc['profileDate'], "%Y%m")
         | 
| 73 94 | 
             
                    data[:name] = doc['dataCategory']['name']
         | 
| 74 95 | 
             
                    data[:path] = doc['path']
         | 
| 75 | 
            -
                    data[: | 
| 96 | 
            +
                    data[:total_amount] = doc['totalAmountPerMonth']
         | 
| 97 | 
            +
                    data[:total_amount_unit] = "kg/month"
         | 
| 76 98 | 
             
                    data[:children] = []
         | 
| 77 99 | 
             
                    if doc['children'] && doc['children']['dataCategories']
         | 
| 78 100 | 
             
                      doc['children']['dataCategories'].each do |child|
         | 
| @@ -92,6 +114,35 @@ module AMEE | |
| 92 114 | 
             
                    raise AMEE::BadData.new("Couldn't load ProfileCategory from JSON data. Check that your URL is correct.")
         | 
| 93 115 | 
             
                  end
         | 
| 94 116 |  | 
| 117 | 
            +
                  def self.from_v2_json(json)
         | 
| 118 | 
            +
                    # Parse json
         | 
| 119 | 
            +
                    doc = JSON.parse(json)
         | 
| 120 | 
            +
                    data = {}
         | 
| 121 | 
            +
                    data[:profile_uid] = doc['profile']['uid']
         | 
| 122 | 
            +
                    #data[:profile_date] = DateTime.strptime(doc['profileDate'], "%Y%m")
         | 
| 123 | 
            +
                    data[:name] = doc['dataCategory']['name']
         | 
| 124 | 
            +
                    data[:path] = doc['path']
         | 
| 125 | 
            +
                    data[:total_amount] = doc['totalAmount']['value'].to_f rescue nil
         | 
| 126 | 
            +
                    data[:total_amount_unit] = doc['totalAmount']['unit'] rescue nil
         | 
| 127 | 
            +
                    data[:children] = []
         | 
| 128 | 
            +
                    if doc['profileCategories']
         | 
| 129 | 
            +
                      doc['profileCategories'].each do |child|
         | 
| 130 | 
            +
                        data[:children] << parse_json_profile_category(child)
         | 
| 131 | 
            +
                      end
         | 
| 132 | 
            +
                    end
         | 
| 133 | 
            +
                    data[:items] = []
         | 
| 134 | 
            +
                    profile_items = []
         | 
| 135 | 
            +
                    profile_items.concat doc['profileItems'] rescue nil
         | 
| 136 | 
            +
                    profile_items << doc['profileItem'] unless doc['profileItem'].nil?
         | 
| 137 | 
            +
                    profile_items.each do |item|
         | 
| 138 | 
            +
                      data[:items] << parse_json_profile_item(item)
         | 
| 139 | 
            +
                    end
         | 
| 140 | 
            +
                    # Create object
         | 
| 141 | 
            +
                    Category.new(data)
         | 
| 142 | 
            +
                  rescue
         | 
| 143 | 
            +
                    raise AMEE::BadData.new("Couldn't load ProfileCategory from V2 JSON data. Check that your URL is correct.")
         | 
| 144 | 
            +
                  end
         | 
| 145 | 
            +
             | 
| 95 146 | 
             
                  def self.parse_xml_profile_item(item)
         | 
| 96 147 | 
             
                    item_data = {}
         | 
| 97 148 | 
             
                    item_data[:values] = {}
         | 
| @@ -149,7 +200,8 @@ module AMEE | |
| 149 200 | 
             
                    data[:profile_date] = DateTime.strptime(REXML::XPath.first(doc, "/Resources/ProfileCategoryResource/ProfileDate").text, "%Y%m")
         | 
| 150 201 | 
             
                    data[:name] = REXML::XPath.first(doc, '/Resources/ProfileCategoryResource/DataCategory/Name').text
         | 
| 151 202 | 
             
                    data[:path] = REXML::XPath.first(doc, '/Resources/ProfileCategoryResource/Path').text || ""
         | 
| 152 | 
            -
                    data[: | 
| 203 | 
            +
                    data[:total_amount] = REXML::XPath.first(doc, '/Resources/ProfileCategoryResource/TotalAmountPerMonth').text.to_f rescue nil
         | 
| 204 | 
            +
                    data[:total_amount_unit] = "kg/month"
         | 
| 153 205 | 
             
                    data[:children] = []
         | 
| 154 206 | 
             
                    REXML::XPath.each(doc, '/Resources/ProfileCategoryResource/Children/ProfileCategories/DataCategory') do |child|
         | 
| 155 207 | 
             
                      category_data = {}
         | 
| @@ -174,6 +226,135 @@ module AMEE | |
| 174 226 | 
             
                    raise AMEE::BadData.new("Couldn't load ProfileCategory from XML data. Check that your URL is correct.")
         | 
| 175 227 | 
             
                  end
         | 
| 176 228 |  | 
| 229 | 
            +
                  def self.parse_v2_xml_profile_item(item)
         | 
| 230 | 
            +
                    item_data = {}
         | 
| 231 | 
            +
                    item_data[:values] = {}
         | 
| 232 | 
            +
                    item.elements.each do |element|
         | 
| 233 | 
            +
                      key = element.name
         | 
| 234 | 
            +
                      case key.downcase
         | 
| 235 | 
            +
                        when 'name', 'path'
         | 
| 236 | 
            +
                          item_data[key.downcase.to_sym] = element.text
         | 
| 237 | 
            +
                        when 'dataitem'
         | 
| 238 | 
            +
                          item_data[:dataItemLabel] = element.elements['Label'].text
         | 
| 239 | 
            +
                          item_data[:dataItemUid] = element.attributes['uid'].to_s
         | 
| 240 | 
            +
                        when 'validfrom'
         | 
| 241 | 
            +
                          item_data[:validFrom] = DateTime.strptime(element.text, "%Y%m%d")
         | 
| 242 | 
            +
                        when 'startdate'
         | 
| 243 | 
            +
                          item_data[:startDate] = DateTime.parse(element.text)
         | 
| 244 | 
            +
                        when 'enddate'
         | 
| 245 | 
            +
                          item_data[:endDate] = DateTime.parse(element.text) if element.text
         | 
| 246 | 
            +
                        when 'end'
         | 
| 247 | 
            +
                          item_data[:end] = (element.text == "true")
         | 
| 248 | 
            +
                        when 'amount'
         | 
| 249 | 
            +
                          item_data[:amount] = element.text.to_f
         | 
| 250 | 
            +
                          item_data[:amount_unit] = element.attributes['unit'].to_s
         | 
| 251 | 
            +
                        when 'itemvalues'
         | 
| 252 | 
            +
                          element.elements.each do |itemvalue|
         | 
| 253 | 
            +
                            path = itemvalue.elements['Path'].text
         | 
| 254 | 
            +
                            item_data[:values][path.to_sym] = {}
         | 
| 255 | 
            +
                            item_data[:values][path.to_sym][:name] = itemvalue.elements['Name'].text
         | 
| 256 | 
            +
                            item_data[:values][path.to_sym][:value] = itemvalue.elements['Value'].text || "0"
         | 
| 257 | 
            +
                            item_data[:values][path.to_sym][:unit] = itemvalue.elements['Unit'].text
         | 
| 258 | 
            +
                            item_data[:values][path.to_sym][:per_unit] = itemvalue.elements['PerUnit'].text
         | 
| 259 | 
            +
                          end
         | 
| 260 | 
            +
                        else
         | 
| 261 | 
            +
                          item_data[:values][key.to_sym] = element.text
         | 
| 262 | 
            +
                      end
         | 
| 263 | 
            +
                    end
         | 
| 264 | 
            +
                    item_data[:uid] = item.attributes['uid'].to_s
         | 
| 265 | 
            +
                    item_data[:path] ||= item_data[:uid] # Fill in path if not retrieved from response
         | 
| 266 | 
            +
                    return item_data
         | 
| 267 | 
            +
                  end
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                  def self.from_v2_xml(xml)
         | 
| 270 | 
            +
                    # Parse XML
         | 
| 271 | 
            +
                    doc = REXML::Document.new(xml)
         | 
| 272 | 
            +
                    data = {}
         | 
| 273 | 
            +
                    data[:profile_uid] = REXML::XPath.first(doc, "/Resources/ProfileCategoryResource/Profile/@uid").to_s
         | 
| 274 | 
            +
                    #data[:profile_date] = DateTime.strptime(REXML::XPath.first(doc, "/Resources/ProfileCategoryResource/ProfileDate").text, "%Y%m")
         | 
| 275 | 
            +
                    data[:name] = REXML::XPath.first(doc, '/Resources/ProfileCategoryResource/DataCategory/Name').text
         | 
| 276 | 
            +
                    data[:path] = REXML::XPath.first(doc, '/Resources/ProfileCategoryResource/Path').text || ""
         | 
| 277 | 
            +
                    data[:total_amount] = REXML::XPath.first(doc, '/Resources/ProfileCategoryResource/TotalAmount').text.to_f rescue nil
         | 
| 278 | 
            +
                    data[:total_amount_unit] = REXML::XPath.first(doc, '/Resources/ProfileCategoryResource/TotalAmount/@unit').to_s rescue nil
         | 
| 279 | 
            +
                    data[:children] = []
         | 
| 280 | 
            +
                    REXML::XPath.each(doc, '/Resources/ProfileCategoryResource/ProfileCategories/DataCategory') do |child|
         | 
| 281 | 
            +
                      category_data = {}
         | 
| 282 | 
            +
                      category_data[:name] = child.elements['Name'].text
         | 
| 283 | 
            +
                      category_data[:path] = child.elements['Path'].text
         | 
| 284 | 
            +
                      category_data[:uid] = child.attributes['uid'].to_s
         | 
| 285 | 
            +
                      data[:children] << category_data
         | 
| 286 | 
            +
                    end
         | 
| 287 | 
            +
                    REXML::XPath.each(doc, '/Resources/ProfileCategoryResource/Children/ProfileCategories/ProfileCategory') do |child|
         | 
| 288 | 
            +
                      data[:children] << parse_xml_profile_category(child)
         | 
| 289 | 
            +
                    end
         | 
| 290 | 
            +
                    data[:items] = []
         | 
| 291 | 
            +
                    REXML::XPath.each(doc, '/Resources/ProfileCategoryResource/ProfileItems/ProfileItem') do |item|
         | 
| 292 | 
            +
                      data[:items] << parse_v2_xml_profile_item(item)
         | 
| 293 | 
            +
                    end
         | 
| 294 | 
            +
                    REXML::XPath.each(doc, '/Resources/ProfileCategoryResource/ProfileItem') do |item|
         | 
| 295 | 
            +
                      data[:items] << parse_v2_xml_profile_item(item)
         | 
| 296 | 
            +
                    end
         | 
| 297 | 
            +
                    # Create object
         | 
| 298 | 
            +
                    Category.new(data)
         | 
| 299 | 
            +
                  rescue
         | 
| 300 | 
            +
                    raise AMEE::BadData.new("Couldn't load ProfileCategory from V2 XML data. Check that your URL is correct.")
         | 
| 301 | 
            +
                  end
         | 
| 302 | 
            +
             | 
| 303 | 
            +
                  def self.from_v2_atom(response)
         | 
| 304 | 
            +
                    # Parse XML
         | 
| 305 | 
            +
                    doc = REXML::Document.new(response)
         | 
| 306 | 
            +
                    data = {}
         | 
| 307 | 
            +
                    data[:profile_uid] = REXML::XPath.first(doc, "/feed/@xml:base").to_s.match("/profiles/(.*?)/")[1]
         | 
| 308 | 
            +
            #        data[:profile_date] = DateTime.strptime(REXML::XPath.first(doc, "/Resources/ProfileCategoryResource/ProfileDate").text, "%Y%m")
         | 
| 309 | 
            +
            #        data[:name] = REXML::XPath.first(doc, '/feed/title').text
         | 
| 310 | 
            +
                    data[:path] = REXML::XPath.first(doc, "/feed/@xml:base").to_s.match("/profiles/.*?(/.*)")[1]
         | 
| 311 | 
            +
                    data[:total_amount] = REXML::XPath.first(doc, '/feed/amee:totalAmount').text.to_f rescue nil
         | 
| 312 | 
            +
                    data[:total_amount_unit] = REXML::XPath.first(doc, '/feed/amee:totalAmount/@unit').to_s rescue nil
         | 
| 313 | 
            +
                    data[:children] = []
         | 
| 314 | 
            +
            #        REXML::XPath.each(doc, '/Resources/ProfileCategoryResource/ProfileCategories/DataCategory') do |child|
         | 
| 315 | 
            +
            #          category_data = {}
         | 
| 316 | 
            +
            #          category_data[:name] = child.elements['Name'].text
         | 
| 317 | 
            +
            #          category_data[:path] = child.elements['Path'].text
         | 
| 318 | 
            +
            #          category_data[:uid] = child.attributes['uid'].to_s
         | 
| 319 | 
            +
            #          data[:children] << category_data
         | 
| 320 | 
            +
            #        end
         | 
| 321 | 
            +
            #        REXML::XPath.each(doc, '/Resources/ProfileCategoryResource/Children/ProfileCategories/ProfileCategory') do |child|
         | 
| 322 | 
            +
            #          data[:children] << parse_xml_profile_category(child)
         | 
| 323 | 
            +
            #        end
         | 
| 324 | 
            +
                    data[:items] = []
         | 
| 325 | 
            +
                    REXML::XPath.each(doc, '/feed/entry') do |entry|
         | 
| 326 | 
            +
                      item = {}
         | 
| 327 | 
            +
                      item[:uid] = entry.elements['id'].text.match("urn:item:(.*)")[1]
         | 
| 328 | 
            +
                      item[:name] = entry.elements['title'].text
         | 
| 329 | 
            +
                      item[:path] = item[:uid]
         | 
| 330 | 
            +
            #          data[:dataItemLabel].should == "gas"
         | 
| 331 | 
            +
            #          data[:dataItemUid].should == "66056991EE23"
         | 
| 332 | 
            +
                      item[:amount] = entry.elements['amee:amount'].text.to_f rescue nil
         | 
| 333 | 
            +
                      item[:amount_unit] = entry.elements['amee:amount'].attributes['unit'].to_s rescue nil
         | 
| 334 | 
            +
                      item[:startDate] = DateTime.parse(entry.elements['amee:startDate'].text)
         | 
| 335 | 
            +
                      item[:endDate] = DateTime.parse(entry.elements['amee:endDate'].text) rescue nil
         | 
| 336 | 
            +
                      item[:values] = {}
         | 
| 337 | 
            +
                      entry.elements.each do |itemvalue|
         | 
| 338 | 
            +
                        if itemvalue.name == 'itemValue'
         | 
| 339 | 
            +
                          path = itemvalue.elements['link'].attributes['href'].to_s.match(".*/(.*)")[1]
         | 
| 340 | 
            +
                          x = {}
         | 
| 341 | 
            +
                          x[:path] = path
         | 
| 342 | 
            +
                          x[:name] = itemvalue.elements['amee:name'].text
         | 
| 343 | 
            +
                          x[:value] = itemvalue.elements['amee:value'].text unless itemvalue.elements['amee:value'].text == "N/A"
         | 
| 344 | 
            +
                          x[:value] ||= "0"
         | 
| 345 | 
            +
                          x[:unit] = itemvalue.elements['amee:unit'].text rescue nil
         | 
| 346 | 
            +
                          x[:per_unit] = itemvalue.elements['amee:perUnit'].text rescue nil
         | 
| 347 | 
            +
                          item[:values][path.to_sym] = x
         | 
| 348 | 
            +
                        end
         | 
| 349 | 
            +
                      end
         | 
| 350 | 
            +
                      data[:items] << item
         | 
| 351 | 
            +
                    end
         | 
| 352 | 
            +
                    # Create object
         | 
| 353 | 
            +
                    Category.new(data)
         | 
| 354 | 
            +
                  rescue
         | 
| 355 | 
            +
                    raise AMEE::BadData.new("Couldn't load ProfileCategory from V2 Atom data. Check that your URL is correct.")
         | 
| 356 | 
            +
                  end
         | 
| 357 | 
            +
             | 
| 177 358 | 
             
                  def self.get_history(connection, path, num_months, end_date = Date.today, items_per_page = 10)
         | 
| 178 359 | 
             
                    month = end_date.month
         | 
| 179 360 | 
             
                    year = end_date.year
         | 
| @@ -201,9 +382,15 @@ module AMEE | |
| 201 382 |  | 
| 202 383 | 
             
                  def self.parse(connection, response)
         | 
| 203 384 | 
             
                    # Parse data from response
         | 
| 204 | 
            -
                    if response. | 
| 385 | 
            +
                    if response.is_v2_json?
         | 
| 386 | 
            +
                      cat = Category.from_v2_json(response)
         | 
| 387 | 
            +
                    elsif response.is_json?
         | 
| 205 388 | 
             
                      cat = Category.from_json(response)
         | 
| 206 | 
            -
                     | 
| 389 | 
            +
                    elsif response.is_v2_atom?
         | 
| 390 | 
            +
                      cat = Category.from_v2_atom(response)
         | 
| 391 | 
            +
                    elsif response.is_v2_xml?
         | 
| 392 | 
            +
                      cat = Category.from_v2_xml(response)
         | 
| 393 | 
            +
                    elsif response.is_xml?
         | 
| 207 394 | 
             
                      cat = Category.from_xml(response)
         | 
| 208 395 | 
             
                    end
         | 
| 209 396 | 
             
                    # Store connection in object for future use
         | 
| @@ -213,10 +400,25 @@ module AMEE | |
| 213 400 | 
             
                  end
         | 
| 214 401 |  | 
| 215 402 |  | 
| 216 | 
            -
                  def self.get(connection, path,  | 
| 403 | 
            +
                  def self.get(connection, path, options = {})
         | 
| 404 | 
            +
                    unless options.is_a?(Hash)
         | 
| 405 | 
            +
                      raise AMEE::ArgumentError.new("Third argument must be a hash of options!")
         | 
| 406 | 
            +
                    end
         | 
| 407 | 
            +
                    # Convert to AMEE options
         | 
| 408 | 
            +
                    if options[:start_date] && connection.version < 2
         | 
| 409 | 
            +
                      options[:profileDate] = options[:start_date].amee1_month 
         | 
| 410 | 
            +
                    elsif options[:start_date] && connection.version >= 2
         | 
| 411 | 
            +
                      options[:startDate] = options[:start_date].amee2schema
         | 
| 412 | 
            +
                    end
         | 
| 413 | 
            +
                    options.delete(:start_date)
         | 
| 414 | 
            +
                    if options[:end_date] && connection.version >= 2
         | 
| 415 | 
            +
                      options[:endDate] = options[:end_date].amee2schema
         | 
| 416 | 
            +
                    end
         | 
| 417 | 
            +
                    options.delete(:end_date)
         | 
| 418 | 
            +
                    if options[:duration] && connection.version >= 2
         | 
| 419 | 
            +
                      options[:duration] = "PT#{options[:duration] * 86400}S"
         | 
| 420 | 
            +
                    end
         | 
| 217 421 | 
             
                    # Load data from path
         | 
| 218 | 
            -
                    options = {:profileDate => for_date.strftime("%Y%m"), :itemsPerPage => items_per_page}
         | 
| 219 | 
            -
                    options[:recurse] = true if recurse == true
         | 
| 220 422 | 
             
                    response = connection.get(path, options)
         | 
| 221 423 | 
             
                    return Category.parse(connection, response)
         | 
| 222 424 | 
             
                  rescue
         | 
| @@ -230,7 +432,12 @@ module AMEE | |
| 230 432 | 
             
                  def item(options)
         | 
| 231 433 | 
             
                    # Search fields - from most specific to least specific
         | 
| 232 434 | 
             
                    item = items.find{ |x| x[:uid] == options[:uid] || x[:name] == options[:name] || x[:dataItemUid] == options[:dataItemUid] || x[:dataItemLabel] == options[:dataItemLabel] }
         | 
| 233 | 
            -
                     | 
| 435 | 
            +
                    # Pass through some options
         | 
| 436 | 
            +
                    new_opts = {}
         | 
| 437 | 
            +
                    new_opts[:returnUnit] = options[:returnUnit] if options[:returnUnit]
         | 
| 438 | 
            +
                    new_opts[:returnPerUnit] = options[:returnPerUnit] if options[:returnPerUnit]
         | 
| 439 | 
            +
                    new_opts[:format] = options[:format] if options[:format]
         | 
| 440 | 
            +
                    item ? AMEE::Profile::Item.get(connection, "#{full_path}/#{item[:path]}", new_opts) : nil
         | 
| 234 441 | 
             
                  end
         | 
| 235 442 |  | 
| 236 443 | 
             
                end
         | 
    
        data/lib/amee/profile_item.rb
    CHANGED
    
    | @@ -4,19 +4,33 @@ module AMEE | |
| 4 4 |  | 
| 5 5 | 
             
                  def initialize(data = {})
         | 
| 6 6 | 
             
                    @values = data ? data[:values] : []
         | 
| 7 | 
            -
                    @ | 
| 8 | 
            -
                    @ | 
| 7 | 
            +
                    @total_amount = data[:total_amount]
         | 
| 8 | 
            +
                    @total_amount_unit = data[:total_amount_unit]
         | 
| 9 | 
            +
                    @start_date = data[:start_date] || data[:valid_from]
         | 
| 10 | 
            +
                    @end_date = data[:end_date] || (data[:end] == true ? @start_date : nil )
         | 
| 9 11 | 
             
                    @data_item_uid = data[:data_item_uid]
         | 
| 10 | 
            -
                    @end = data[:end]
         | 
| 11 12 | 
             
                    super
         | 
| 12 13 | 
             
                  end
         | 
| 13 14 |  | 
| 14 15 | 
             
                  attr_reader :values
         | 
| 15 | 
            -
                  attr_reader : | 
| 16 | 
            -
                  attr_reader : | 
| 17 | 
            -
                  attr_reader : | 
| 16 | 
            +
                  attr_reader :total_amount
         | 
| 17 | 
            +
                  attr_reader :total_amount_unit
         | 
| 18 | 
            +
                  attr_reader :start_date
         | 
| 19 | 
            +
                  attr_reader :end_date
         | 
| 18 20 | 
             
                  attr_reader :data_item_uid
         | 
| 19 21 |  | 
| 22 | 
            +
                  # V1 compatibility
         | 
| 23 | 
            +
                  def valid_from
         | 
| 24 | 
            +
                    start_date
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                  def end
         | 
| 27 | 
            +
                    end_date.nil? ? false : start_date == end_date
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def duration
         | 
| 31 | 
            +
                    end_date.nil? ? nil : (end_date - start_date).to_f
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 20 34 | 
             
                  def self.from_json(json)
         | 
| 21 35 | 
             
                    # Parse json
         | 
| 22 36 | 
             
                    doc = JSON.parse(json)
         | 
| @@ -26,7 +40,8 @@ module AMEE | |
| 26 40 | 
             
                    data[:uid] = doc['profileItem']['uid']
         | 
| 27 41 | 
             
                    data[:name] = doc['profileItem']['name']
         | 
| 28 42 | 
             
                    data[:path] = doc['path']
         | 
| 29 | 
            -
                    data[: | 
| 43 | 
            +
                    data[:total_amount] = doc['profileItem']['amountPerMonth']
         | 
| 44 | 
            +
                    data[:total_amount_unit] = "kg/month"
         | 
| 30 45 | 
             
                    data[:valid_from] = DateTime.strptime(doc['profileItem']['validFrom'], "%Y%m%d")
         | 
| 31 46 | 
             
                    data[:end] = doc['profileItem']['end'] == "false" ? false : true
         | 
| 32 47 | 
             
                    data[:values] = []
         | 
| @@ -46,6 +61,38 @@ module AMEE | |
| 46 61 | 
             
                    raise AMEE::BadData.new("Couldn't load ProfileItem from JSON data. Check that your URL is correct.")
         | 
| 47 62 | 
             
                  end
         | 
| 48 63 |  | 
| 64 | 
            +
                  def self.from_v2_json(json)
         | 
| 65 | 
            +
                    # Parse json
         | 
| 66 | 
            +
                    doc = JSON.parse(json)
         | 
| 67 | 
            +
                    data = {}
         | 
| 68 | 
            +
                    data[:profile_uid] = doc['profile']['uid']
         | 
| 69 | 
            +
                    data[:data_item_uid] = doc['profileItem']['dataItem']['uid']
         | 
| 70 | 
            +
                    data[:uid] = doc['profileItem']['uid']
         | 
| 71 | 
            +
                    data[:name] = doc['profileItem']['name']
         | 
| 72 | 
            +
                    data[:path] = doc['path']
         | 
| 73 | 
            +
                    data[:total_amount] = doc['profileItem']['amount']['value'].to_f
         | 
| 74 | 
            +
                    data[:total_amount_unit] = doc['profileItem']['amount']['unit']
         | 
| 75 | 
            +
                    data[:start_date] = DateTime.parse(doc['profileItem']['startDate'])
         | 
| 76 | 
            +
                    data[:end_date] = DateTime.parse(doc['profileItem']['endDate']) rescue nil
         | 
| 77 | 
            +
                    data[:values] = []
         | 
| 78 | 
            +
                    doc['profileItem']['itemValues'].each do |item|
         | 
| 79 | 
            +
                      value_data = {}
         | 
| 80 | 
            +
                      item.each_pair do |key,value|
         | 
| 81 | 
            +
                        case key
         | 
| 82 | 
            +
                          when 'name', 'path', 'uid', 'value', 'unit'
         | 
| 83 | 
            +
                            value_data[key.downcase.to_sym] = value
         | 
| 84 | 
            +
                          when 'perUnit'
         | 
| 85 | 
            +
                            value_data[:per_unit] = value
         | 
| 86 | 
            +
                        end
         | 
| 87 | 
            +
                      end
         | 
| 88 | 
            +
                      data[:values] << value_data
         | 
| 89 | 
            +
                    end
         | 
| 90 | 
            +
                    # Create object
         | 
| 91 | 
            +
                    Item.new(data)
         | 
| 92 | 
            +
                  rescue
         | 
| 93 | 
            +
                    raise AMEE::BadData.new("Couldn't load ProfileItem from V2 JSON data. Check that your URL is correct.")
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
             | 
| 49 96 | 
             
                  def self.from_xml(xml)
         | 
| 50 97 | 
             
                    # Parse XML
         | 
| 51 98 | 
             
                    doc = REXML::Document.new(xml)
         | 
| @@ -55,7 +102,8 @@ module AMEE | |
| 55 102 | 
             
                    data[:uid] = REXML::XPath.first(doc, "/Resources/ProfileItemResource/ProfileItem/@uid").to_s
         | 
| 56 103 | 
             
                    data[:name] = REXML::XPath.first(doc, '/Resources/ProfileItemResource/ProfileItem/Name').text
         | 
| 57 104 | 
             
                    data[:path] = REXML::XPath.first(doc, '/Resources/ProfileItemResource/Path').text || ""
         | 
| 58 | 
            -
                    data[: | 
| 105 | 
            +
                    data[:total_amount] = REXML::XPath.first(doc, '/Resources/ProfileItemResource/ProfileItem/AmountPerMonth').text.to_f rescue nil
         | 
| 106 | 
            +
                    data[:total_amount_unit] = "kg/month"
         | 
| 59 107 | 
             
                    data[:valid_from] = DateTime.strptime(REXML::XPath.first(doc, "/Resources/ProfileItemResource/ProfileItem/ValidFrom").text, "%Y%m%d")
         | 
| 60 108 | 
             
                    data[:end] = REXML::XPath.first(doc, '/Resources/ProfileItemResource/ProfileItem/End').text == "false" ? false : true
         | 
| 61 109 | 
             
                    data[:values] = []
         | 
| @@ -78,32 +126,139 @@ module AMEE | |
| 78 126 | 
             
                    raise AMEE::BadData.new("Couldn't load ProfileItem from XML data. Check that your URL is correct.")
         | 
| 79 127 | 
             
                  end
         | 
| 80 128 |  | 
| 129 | 
            +
                  def self.from_v2_xml(xml)
         | 
| 130 | 
            +
                    # Parse XML
         | 
| 131 | 
            +
                    doc = REXML::Document.new(xml)
         | 
| 132 | 
            +
                    data = {}
         | 
| 133 | 
            +
                    data[:profile_uid] = REXML::XPath.first(doc, "/Resources/ProfileItemResource/Profile/@uid").to_s
         | 
| 134 | 
            +
                    data[:data_item_uid] = REXML::XPath.first(doc, "/Resources/ProfileItemResource/DataItem/@uid").to_s
         | 
| 135 | 
            +
                    data[:uid] = REXML::XPath.first(doc, "/Resources/ProfileItemResource/ProfileItem/@uid").to_s
         | 
| 136 | 
            +
                    data[:name] = REXML::XPath.first(doc, '/Resources/ProfileItemResource/ProfileItem/Name').text
         | 
| 137 | 
            +
                    data[:path] = REXML::XPath.first(doc, '/Resources/ProfileItemResource/Path').text || ""
         | 
| 138 | 
            +
                    data[:total_amount] = REXML::XPath.first(doc, '/Resources/ProfileItemResource/ProfileItem/Amount').text.to_f rescue nil
         | 
| 139 | 
            +
                    data[:total_amount_unit] = REXML::XPath.first(doc, '/Resources/ProfileItemResource/ProfileItem/Amount/@unit').to_s rescue nil
         | 
| 140 | 
            +
                    data[:start_date] = DateTime.parse(REXML::XPath.first(doc, "/Resources/ProfileItemResource/ProfileItem/StartDate").text)
         | 
| 141 | 
            +
                    data[:end_date] = DateTime.parse(REXML::XPath.first(doc, "/Resources/ProfileItemResource/ProfileItem/EndDate").text) rescue nil
         | 
| 142 | 
            +
                    data[:values] = []
         | 
| 143 | 
            +
                    REXML::XPath.each(doc, '/Resources/ProfileItemResource/ProfileItem/ItemValues/ItemValue') do |item|
         | 
| 144 | 
            +
                      value_data = {}
         | 
| 145 | 
            +
                      item.elements.each do |element|
         | 
| 146 | 
            +
                        key = element.name
         | 
| 147 | 
            +
                        value = element.text
         | 
| 148 | 
            +
                        case key
         | 
| 149 | 
            +
                          when 'Name', 'Path', 'Value', 'Unit'
         | 
| 150 | 
            +
                            value_data[key.downcase.to_sym] = value
         | 
| 151 | 
            +
                          when 'PerUnit'
         | 
| 152 | 
            +
                            value_data[:per_unit] = value
         | 
| 153 | 
            +
                        end
         | 
| 154 | 
            +
                      end
         | 
| 155 | 
            +
                      value_data[:uid] = item.attributes['uid'].to_s
         | 
| 156 | 
            +
                      data[:values] << value_data
         | 
| 157 | 
            +
                    end
         | 
| 158 | 
            +
                    # Create object
         | 
| 159 | 
            +
                    Item.new(data)
         | 
| 160 | 
            +
                  rescue
         | 
| 161 | 
            +
                    raise AMEE::BadData.new("Couldn't load ProfileItem from V2 XML data. Check that your URL is correct.")
         | 
| 162 | 
            +
                  end
         | 
| 163 | 
            +
             | 
| 164 | 
            +
                  def self.from_v2_atom(response)
         | 
| 165 | 
            +
                    # Parse XML
         | 
| 166 | 
            +
                    doc = REXML::Document.new(response)
         | 
| 167 | 
            +
                    data = {}
         | 
| 168 | 
            +
                    data[:profile_uid] = REXML::XPath.first(doc, "/entry/@xml:base").to_s.match("/profiles/(.*?)/")[1]
         | 
| 169 | 
            +
                    #data[:data_item_uid] = REXML::XPath.first(doc, "/Resources/ProfileItemResource/DataItem/@uid").to_s
         | 
| 170 | 
            +
                    data[:uid] = REXML::XPath.first(doc, "/entry/id").text.match("urn:item:(.*)")[1]
         | 
| 171 | 
            +
                    data[:name] = REXML::XPath.first(doc, '/entry/title').text
         | 
| 172 | 
            +
                    data[:path] = REXML::XPath.first(doc, "/entry/@xml:base").to_s.match("/profiles/.*?(/.*)")[1]
         | 
| 173 | 
            +
                    data[:total_amount] = REXML::XPath.first(doc, '/entry/amee:amount').text.to_f rescue nil
         | 
| 174 | 
            +
                    data[:total_amount_unit] = REXML::XPath.first(doc, '/entry/amee:amount/@unit').to_s rescue nil
         | 
| 175 | 
            +
                    data[:start_date] = DateTime.parse(REXML::XPath.first(doc, "/entry/amee:startDate").text)
         | 
| 176 | 
            +
                    data[:end_date] = DateTime.parse(REXML::XPath.first(doc, "/entry/amee:endDate").text) rescue nil
         | 
| 177 | 
            +
                    data[:values] = []
         | 
| 178 | 
            +
                    REXML::XPath.each(doc, '/entry/amee:itemValue') do |item|
         | 
| 179 | 
            +
                      value_data = {}
         | 
| 180 | 
            +
                      value_data[:name] = item.elements['amee:name'].text
         | 
| 181 | 
            +
                      value_data[:value] = item.elements['amee:value'].text unless item.elements['amee:value'].text == "N/A"
         | 
| 182 | 
            +
                      value_data[:path] = item.elements['link'].attributes['href'].to_s
         | 
| 183 | 
            +
                      value_data[:unit] = item.elements['amee:unit'].text rescue nil
         | 
| 184 | 
            +
                      value_data[:per_unit] = item.elements['amee:perUnit'].text rescue nil
         | 
| 185 | 
            +
                      data[:values] << value_data
         | 
| 186 | 
            +
                    end
         | 
| 187 | 
            +
                    # Create object
         | 
| 188 | 
            +
                    Item.new(data)
         | 
| 189 | 
            +
                  rescue
         | 
| 190 | 
            +
                    raise AMEE::BadData.new("Couldn't load ProfileItem from V2 ATOM data. Check that your URL is correct.")
         | 
| 191 | 
            +
                  end
         | 
| 192 | 
            +
             | 
| 81 193 | 
             
                  def self.parse(connection, response)
         | 
| 82 194 | 
             
                    # Parse data from response
         | 
| 83 | 
            -
                    if response. | 
| 84 | 
            -
                       | 
| 195 | 
            +
                    if response.is_v2_json?
         | 
| 196 | 
            +
                      item = Item.from_v2_json(response)
         | 
| 197 | 
            +
                    elsif response.is_json?
         | 
| 198 | 
            +
                      item = Item.from_json(response)
         | 
| 199 | 
            +
                    elsif response.is_v2_atom?
         | 
| 200 | 
            +
                      item = Item.from_v2_atom(response)
         | 
| 201 | 
            +
                    elsif response.is_v2_xml?
         | 
| 202 | 
            +
                      item = Item.from_v2_xml(response)
         | 
| 85 203 | 
             
                    else
         | 
| 86 | 
            -
                       | 
| 204 | 
            +
                      item = Item.from_xml(response)
         | 
| 87 205 | 
             
                    end
         | 
| 88 206 | 
             
                    # Store connection in object for future use
         | 
| 89 | 
            -
                     | 
| 207 | 
            +
                    item.connection = connection
         | 
| 90 208 | 
             
                    # Done
         | 
| 91 | 
            -
                    return  | 
| 209 | 
            +
                    return item
         | 
| 92 210 | 
             
                  end
         | 
| 93 211 |  | 
| 94 | 
            -
             | 
| 212 | 
            +
                 def self.get(connection, path, options = {})
         | 
| 213 | 
            +
                    unless options.is_a?(Hash)
         | 
| 214 | 
            +
                      raise AMEE::ArgumentError.new("Third argument must be a hash of options!")
         | 
| 215 | 
            +
                    end
         | 
| 216 | 
            +
                    # Convert to AMEE options
         | 
| 217 | 
            +
                    if options[:start_date] && category.connection.version < 2
         | 
| 218 | 
            +
                      options[:profileDate] = options[:start_date].amee1_month
         | 
| 219 | 
            +
                    elsif options[:start_date] && category.connection.version >= 2
         | 
| 220 | 
            +
                      options[:startDate] = options[:start_date].amee2schema
         | 
| 221 | 
            +
                    end
         | 
| 222 | 
            +
                    options.delete(:start_date)
         | 
| 223 | 
            +
                    if options[:end_date] && category.connection.version >= 2
         | 
| 224 | 
            +
                      options[:endDate] = options[:end_date].amee2schema
         | 
| 225 | 
            +
                    end
         | 
| 226 | 
            +
                    options.delete(:end_date)
         | 
| 227 | 
            +
                    if options[:duration] && category.connection.version >= 2
         | 
| 228 | 
            +
                      options[:duration] = "PT#{options[:duration] * 86400}S"
         | 
| 229 | 
            +
                    end
         | 
| 95 230 | 
             
                    # Load data from path
         | 
| 96 | 
            -
                    response = connection.get(path,  | 
| 231 | 
            +
                    response = connection.get(path, options)
         | 
| 97 232 | 
             
                    return Item.parse(connection, response)
         | 
| 98 233 | 
             
                  rescue
         | 
| 99 234 | 
             
                    raise AMEE::BadData.new("Couldn't load ProfileItem. Check that your URL is correct.")
         | 
| 100 235 | 
             
                  end
         | 
| 101 236 |  | 
| 102 | 
            -
                  def self.create( | 
| 237 | 
            +
                  def self.create(category, data_item_uid, options = {})
         | 
| 238 | 
            +
                    # Store format if set
         | 
| 239 | 
            +
                    format = options[:format]
         | 
| 240 | 
            +
                    unless options.is_a?(Hash)
         | 
| 241 | 
            +
                      raise AMEE::ArgumentError.new("Third argument must be a hash of options!")
         | 
| 242 | 
            +
                    end
         | 
| 243 | 
            +
                    # Set dates
         | 
| 244 | 
            +
                    if options[:start_date] && category.connection.version < 2
         | 
| 245 | 
            +
                      options[:profileDate] = options[:start_date].amee1_month
         | 
| 246 | 
            +
                    elsif options[:start_date] && category.connection.version >= 2
         | 
| 247 | 
            +
                      options[:startDate] = options[:start_date].amee2schema
         | 
| 248 | 
            +
                    end
         | 
| 249 | 
            +
                    options.delete(:start_date)
         | 
| 250 | 
            +
                    if options[:end_date] && category.connection.version >= 2
         | 
| 251 | 
            +
                      options[:endDate] = options[:end_date].amee2schema
         | 
| 252 | 
            +
                    end        
         | 
| 253 | 
            +
                    options.delete(:end_date)
         | 
| 254 | 
            +
                    if options[:duration] && category.connection.version >= 2
         | 
| 255 | 
            +
                      options[:duration] = "PT#{options[:duration] * 86400}S"
         | 
| 256 | 
            +
                    end
         | 
| 103 257 | 
             
                    # Send data to path
         | 
| 104 258 | 
             
                    options.merge! :dataItemUid => data_item_uid
         | 
| 105 | 
            -
                    response =  | 
| 106 | 
            -
                    category = Category.parse( | 
| 259 | 
            +
                    response = category.connection.post(category.full_path, options)
         | 
| 260 | 
            +
                    category = Category.parse(category.connection, response)
         | 
| 261 | 
            +
                    options.merge!(:format => format) if format
         | 
| 107 262 | 
             
                    return category.item(options)
         | 
| 108 263 | 
             
                  rescue
         | 
| 109 264 | 
             
                    raise AMEE::BadData.new("Couldn't create ProfileItem. Check that your information is correct.")
         | 
| @@ -112,8 +267,8 @@ module AMEE | |
| 112 267 | 
             
                  def self.update(connection, path, options = {})
         | 
| 113 268 | 
             
                    response = connection.put(path, options)
         | 
| 114 269 | 
             
                    return Item.parse(connection, response)
         | 
| 115 | 
            -
                   | 
| 116 | 
            -
             | 
| 270 | 
            +
                  rescue
         | 
| 271 | 
            +
                    raise AMEE::BadData.new("Couldn't update ProfileItem. Check that your information is correct.")
         | 
| 117 272 | 
             
                  end
         | 
| 118 273 |  | 
| 119 274 | 
             
                  def update(options = {})
         | 
    
        data/lib/amee/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: Floppy-amee
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 2.0.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors: 
         | 
| 7 7 | 
             
            - James Smith
         | 
| @@ -9,7 +9,7 @@ autorequire: | |
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 11 |  | 
| 12 | 
            -
            date: 2009-02- | 
| 12 | 
            +
            date: 2009-02-13 00:00:00 -08:00
         | 
| 13 13 | 
             
            default_executable: 
         | 
| 14 14 | 
             
            dependencies: []
         | 
| 15 15 |  |