Java tutorial
/** * Copyright 2016, RadiantBlue Technologies, Inc. * * Licensed 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. **/ package model.job.metadata; import java.lang.reflect.InvocationTargetException; import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import javax.validation.constraints.NotNull; import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; //import org.springframework.data.elasticsearch.annotations.Field; //import org.springframework.data.elasticsearch.annotations.FieldType; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import exception.InvalidInputException; import io.swagger.annotations.ApiModelProperty; import model.resource.NumericKeyValue; import model.resource.TextKeyValue; import model.security.SecurityClassification; /** * Common Meta-data fields used to describe Data or Resources (e.g. Services, etc.) within the Piazza * system. This object should be generic enough to be used to attach common * metadata fields to any object stored in the Piazza system. * * @author mlynum & Patrick.Doody * */ @JsonIgnoreProperties(ignoreUnknown = true) public class ResourceMetadata implements Serializable { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "Human-readable name of the resource") public String name; @ApiModelProperty(value = "Human-readable description of the resource") public String description; @ApiModelProperty(value = "In case of ComplexData, Format defines the allowed input representation") public String format; @ApiModelProperty(value = "Quality level of the resource (Production, Development)") public String qos; private final static Logger LOGGER = LoggerFactory.getLogger(ResourceMetadata.class); // Values indicating the status of the resource public enum STATUS_TYPE { ONLINE, OFFLINE, DEGRADED, FAILED } @ApiModelProperty(value = "Status of the resource") private STATUS_TYPE statusType; @ApiModelProperty(allowableValues = "status_type", value = "Describes the status of the resource(ONLINE, FAILED (The resoure has failed), DEGRADED (The resource is not performing well), OFFLINE (the resource has been turned off)") public String availability; @ApiModelProperty(value = "Keywords describing the resource") public String tags; @ApiModelProperty(value = "Classification of the resource", required = true) @NotNull public SecurityClassification classType; @ApiModelProperty(value = "The date the service will be terminated") @JsonIgnore public DateTime expiresOn; @ApiModelProperty(value = "Indication on whether a client certificate required to access thie resource. Could be a user certificate or computer certificate") public Boolean clientCertRequired; @ApiModelProperty(value = "Indication on whether credentials are required to access this resource") public Boolean credentialsRequired; @ApiModelProperty(value = "Indication on whether preauthorization is required before using the resource? (e.g. do users need to sign a user agreement, etc.)") public Boolean preAuthRequired; @ApiModelProperty(value = "A list of networks names where this resource is available") public String networkAvailable; @ApiModelProperty(value = "Name, e-mail and phone number of point of contact (String concatenated together)") public String contacts; @ApiModelProperty(value = "Human readable reason on the status of the resource") public String reason; @ApiModelProperty(value = "The current version of the resource") public String version; @ApiModelProperty(value = "Username of the individual submitting the resource") public String createdBy; @ApiModelProperty(value = "The date and time of data submission to Piazza") public String createdOn; @ApiModelProperty(value = "Provided by the system. If available, the Id of the Job that resulted in the creation of this resource.", required = false) public String createdByJobId; @ApiModelProperty(value = "A generic Map of String:String (key:value) pairs with additional metadata") private Map<String, String> metadata; /* * Need the ability to accommodate arbitrary key/value pairs */ @ApiModelProperty(value = "Allows for the optional specification of user-defined key-value pairs of numeric values", required = false) //@Field(type = FieldType.Nested) private List<NumericKeyValue> numericKeyValueList; @ApiModelProperty(value = "Allows for the optional specification ofu ser-defined key-value pairs for string values", required = false) //@Field(type = FieldType.Nested) private List<TextKeyValue> textKeyValueList; public List<NumericKeyValue> getNumericKeyValueList() { return numericKeyValueList; } public void setNumericKeyValueList(List<NumericKeyValue> numericKeyValueList) { this.numericKeyValueList = numericKeyValueList; } public List<TextKeyValue> getTextKeyValueList() { return textKeyValueList; } public void setTextKeyValueList(List<TextKeyValue> textKeyValueList) { this.textKeyValueList = textKeyValueList; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getFormat() { return format; } public void setFormat(String format) { this.format = format; } public String getQos() { return qos; } public void setQos(String qos) { this.qos = qos; } public String getAvailability() { return availability; } public void setAvailability(String availability) { this.availability = availability; } public String getTags() { return tags; } public void setTags(String tags) { this.tags = tags; } public SecurityClassification getClassType() { return classType; } public void setClassType(SecurityClassification classType) { this.classType = classType; } public Boolean getClientCertRequired() { return clientCertRequired; } public void setClientCertRequired(Boolean clientCertRequired) { this.clientCertRequired = clientCertRequired; } public Boolean getCredentialsRequired() { return credentialsRequired; } public void setCredentialsRequired(Boolean credentialsRequired) { this.credentialsRequired = credentialsRequired; } public Boolean getPreAuthRequired() { return preAuthRequired; } public void setPreAuthRequired(Boolean preAuthRequired) { this.preAuthRequired = preAuthRequired; } public String getNetworkAvailable() { return networkAvailable; } public void setNetworkAvailable(String networkAvailable) { this.networkAvailable = networkAvailable; } public String getContacts() { return contacts; } public void setContacts(String contacts) { this.contacts = contacts; } public String getReason() { return reason; } public void setReason(String reason) { this.reason = reason; } public String getVersion() { return version; } public STATUS_TYPE getStatusType() { return statusType; } public void setStatusType(STATUS_TYPE statusType) { this.statusType = statusType; } public void setVersion(String version) { this.version = version; } public DateTime getExpiresOn() { return expiresOn; } public void setExpiresOn(DateTime expiresOn) { this.expiresOn = expiresOn; } public String getCreatedBy() { return createdBy; } public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } public String getCreatedOn() { return createdOn; } public void setCreatedOn(String createdOn) { this.createdOn = createdOn; } public Map<String, String> getMetadata() { return metadata; } public void setMetadata(Map<String, String> metadata) { this.metadata = metadata; } /** * Merges the properties of another ResourceMetadata into this one. * * <p> * If the other ResourceMetadata specifies properties, then those properties * take precedence. If the other ResourceMetadata contains a null value for * a property that exists in this object, then this object's property is * unchanged unless the overwriteNull flag is set to true. * </p> * * @param other * The ResourceMetadata properties to merge * @param overwriteNull * True if null values in the other ResourceMetadata should * overwrite values in this object. False if not. * @throws InvalidInputException */ public void merge(ResourceMetadata other, boolean overwriteNull) throws InvalidInputException { final List<String> protectedNames = Arrays.asList("setCreatedBy", "setCreatedOn", "setCreatedByJobId"); for (Method fromMethod : this.getClass().getMethods()) { if (fromMethod.getDeclaringClass().equals(this.getClass()) && fromMethod.getName().startsWith("get")) { mergeMethod(other, overwriteNull, fromMethod, protectedNames); } } } private void mergeMethod(final ResourceMetadata other, boolean overwriteNull, final Method fromMethod, final List<String> protectedNames) throws InvalidInputException { String fromName = fromMethod.getName(); String toName = fromName.replace("get", "set"); String invalidInputFieldName = toName.replace("set", ""); // Block updates to specific ResourceMetadata fields // if values are different, then throw exception if (protectedNames.contains(toName)) { Object currentValue; Object newValue; try { currentValue = fromMethod.invoke(this, (Object[]) null); newValue = fromMethod.invoke(other, (Object[]) null); } catch (Exception e) { LOGGER.error("Could not update System Managed Field. Skipping", e); throw new InvalidInputException( String.format("Could not update system managed field %s", invalidInputFieldName)); } if (currentValue != null && newValue != null && !currentValue.equals(newValue)) { throw new InvalidInputException( String.format("Could not update system managed field %s", invalidInputFieldName)); } //simply return if value is the same, no one is hacking return; } // merge value if field is not protected try { Method toMethod = this.getClass().getMethod(toName, fromMethod.getReturnType()); Object value = fromMethod.invoke(other, (Object[]) null); if ((value != null) || (overwriteNull == true)) { toMethod.invoke(this, value); } } catch (Exception exception) { LOGGER.error("Error merging the properties of ResourceMetadatas", exception); } } public String getCreatedByJobId() { return createdByJobId; } public void setCreatedByJobId(String createdByJobId) { this.createdByJobId = createdByJobId; } }