All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.microsoft.azure.sdk.iot.device.twin.TwinMetadata Maven / Gradle / Ivy

The newest version!
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

package com.microsoft.azure.sdk.iot.device.twin;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;

import java.util.Date;
import java.util.Map;

/**
 * Representation of a single Twin metadata for the {@link TwinCollection}.
 *
 * 

The metadata is a set of pairs lastUpdated/lastUpdatedVersion for each * property and sub-property in the Twin. It is optionally provided by * the service and the clients can only ready it. * *

This class store the Date and Version for each entity in the {@link TwinCollection}. * *

For instance, the following is a valid TwinCollection with its metadata. *

 * {@code
 *  "$metadata":{
 *      "$lastUpdated":"2017-09-21T02:07:44.238Z",
 *      "$lastUpdatedVersion":4,
 *      "MaxSpeed":{
 *          "$lastUpdated":"2017-09-21T02:07:44.238Z",
 *          "$lastUpdatedVersion":3,
 *          "$lastUpdatedBy": "newconfig",
 *          "$lastUpdatedByDigest": "637570574076206429",
 *          "Value":{
 *              "$lastUpdated":"2017-09-21T02:07:44.238Z",
 *              "$lastUpdatedVersion":5
 *          },
 *          "NewValue":{
 *              "$lastUpdated":"2017-09-21T02:07:44.238Z",
 *              "$lastUpdatedVersion":5
 *          }
 *      }
 *  }
 * }
 * 
* * @see Understand and use device twins in IoT Hub * @see Device Twin Api */ // Unchecked casts of Maps to Map are safe as long as service is returning valid twin json payloads. Since all json keys are Strings, all maps must be Map @SuppressWarnings("unchecked") public class TwinMetadata { // the entity last updated date and time in the TwinCollection public static final String LAST_UPDATE_TAG = "$lastUpdated"; private Date lastUpdated; // the entity last updated version in the TwinCollection public static final String LAST_UPDATE_VERSION_TAG = "$lastUpdatedVersion"; private final Integer lastUpdatedVersion; // the entity last updated by in the TwinCollection. Value is a configuration applied on the Twin. public static final String LAST_UPDATED_BY = "$lastUpdatedBy"; private String lastUpdatedBy; // the entity last updated by digest in the TwinCollection which represents service internal version for the applied configuration. public static final String LAST_UPDATED_BY_DIGEST = "$lastUpdatedByDigest"; private String lastUpdatedByDigest; /** * CONSTRUCTOR * *

This private constructor will receive and store the metadata parameters. * * @param lastUpdated the {@code String} with the date and time UTC of the last update on the entity. It can be {@code null}, empty or invalid. * @param lastUpdatedVersion the {@code Integer} with the version of the last update on the entity. It can be {@code null}. * @throws IllegalArgumentException If no valid parameter was provide and the class will be empty, or if the DateTime is invalid. */ TwinMetadata(String lastUpdated, Integer lastUpdatedVersion, String lastUpdatedBy, String lastUpdatedByDigest) { if (!Tools.isNullOrEmpty(lastUpdated)) { this.lastUpdated = ParserUtility.getDateTimeUtc(lastUpdated); } if (lastUpdatedBy != null) { this.lastUpdatedBy = lastUpdatedBy; } if (lastUpdatedByDigest != null) { this.lastUpdatedByDigest = lastUpdatedByDigest; } this.lastUpdatedVersion = lastUpdatedVersion; if ((this.lastUpdatedVersion == null) && (this.lastUpdated == null)) { throw new IllegalArgumentException("no valid data to create a TwinMetadata."); } } /** * CONSTRUCTOR (copy) * *

This private constructor will create a new instance of the TwinMetadata coping the information from the provided one. * * @param metadata the original {@code TwinMetadata} to copy. */ TwinMetadata(TwinMetadata metadata) { if (metadata == null) { throw new IllegalArgumentException("metadata to copy cannot be null"); } this.lastUpdated = metadata.getLastUpdated(); this.lastUpdatedVersion = metadata.getLastUpdatedVersion(); this.lastUpdatedBy = metadata.getLastUpdatedBy(); this.lastUpdatedByDigest = metadata.getLastUpdatedByDigest(); } /** * Metadata extractor * *

This internal method will try to find $lastUpdated and $lastUpdatedVersion at the first * level of the provided Map (Object), and create a new instance of the TwinMetadata with * this information. * *

Once the provide Object can or cannot be a Map, and, if it is a Map, it can or cannot * contains a valid metadata, this method contains the label try, which means that * it can return a valid TwinMetadata or {@code null}. * *

For instance, for the following Map, this method will create a TwinMetadata with * {@code lastUpdated = 2015-09-21T02:07:44.238Z} and {@code lastUpdatedVersion = 3} * *

     * {@code
     * "$lastUpdated":"2015-09-21T02:07:44.238Z",
     * "$lastUpdatedVersion":3,
     * "Value":{
     *     "$lastUpdated":"2016-09-21T02:07:44.238Z",
     *     "$lastUpdatedVersion":5
     * },
     * "NewValue":{
     *     "$lastUpdated":"2017-09-21T02:07:44.238Z",
     *     "$lastUpdatedVersion":5
     * }
     * }
     * 
* * @param metadata the {@code Object} that may contains the metadata. * @return A valid TwinMetadata instance it the provided metadata {@code Object} is a Map with * data and version metadata, or {@code null} for the other cases. * @throws IllegalArgumentException If no valid parameter was provide and the class will be empty, or if the DateTime is invalid. */ static TwinMetadata tryExtractFromMap(Object metadata) { if (!(metadata instanceof Map)) { return null; } String lastUpdated = null; Integer lastUpdatedVersion = null; String lastUpdatedBy = null; String lastUpdatedByDigest = null; for (Map.Entry entry : ((Map) metadata).entrySet()) { String key = entry.getKey(); if (key.equals(LAST_UPDATE_TAG)) { lastUpdated = (String) entry.getValue(); } else if (key.equals(LAST_UPDATE_VERSION_TAG)) { if (!(entry.getValue() instanceof Number)) { throw new IllegalArgumentException("Version in the metadata shall be a number"); } lastUpdatedVersion = ((Number) entry.getValue()).intValue(); } else if (key.equals(TwinMetadata.LAST_UPDATED_BY)) { lastUpdatedBy = entry.getValue().toString(); } else if (key.equals(TwinMetadata.LAST_UPDATED_BY_DIGEST)) { lastUpdatedByDigest = entry.getValue().toString(); } } if ((lastUpdatedVersion != null) || !Tools.isNullOrEmpty(lastUpdated)) { return new TwinMetadata(lastUpdated, lastUpdatedVersion, lastUpdatedBy, lastUpdatedByDigest); } return null; } /** * Getter for lastUpdatedBy. * * @return the {@code String} representing the configuration LastUpdatedBy. */ public String getLastUpdatedBy() { return this.lastUpdatedBy; } /** * Getter for lastUpdatedByDigest. * * @return the {@code String} with the stored lastUpdatedByDigest. */ public String getLastUpdatedByDigest() { return this.lastUpdatedByDigest; } /** * Getter for lastUpdatedVersion. * * @return the {@code Integer} with the stored lastUpdatedVersion. It can be {@code null}. */ public Integer getLastUpdatedVersion() { return this.lastUpdatedVersion; } /** * Getter for lastUpdated. * * @return the {@code Date} with the stored lastUpdated. It can be {@code null}. */ public Date getLastUpdated() { return this.lastUpdated; } /** * Serializer * *

* Creates a {@code JsonElement}, which the content represents * the information in this class in a JSON format. *

* This is useful if the caller will integrate this JSON with JSON from * other classes to generate a consolidated JSON. *

* * @return The {@code JsonElement} with the content of this class. */ JsonElement toJsonElement() { JsonObject jsonObject = new JsonObject(); if (this.lastUpdated != null) { jsonObject.addProperty(LAST_UPDATE_TAG, ParserUtility.dateTimeUtcToString(this.lastUpdated)); } if (this.lastUpdatedVersion != null) { jsonObject.addProperty(LAST_UPDATE_VERSION_TAG, this.lastUpdatedVersion); } if (this.lastUpdatedBy != null) { jsonObject.addProperty(LAST_UPDATED_BY, this.lastUpdatedBy); } if (this.lastUpdatedByDigest != null) { jsonObject.addProperty(LAST_UPDATED_BY_DIGEST, this.lastUpdatedByDigest); } return jsonObject; } /** * Creates a pretty print JSON with the content of this class and subclasses. * * @return The {@code String} with the pretty print JSON. */ @Override public String toString() { return toJsonElement().toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy