/* * Copyright 2015-2016 Red Hat, Inc. and/or its affiliates * and other contributors as indicated by the @author tags. * * 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 org.hawkular.inventory.api.model; import java.util.Collections; import java.util.Map; import java.util.Objects; import java.util.Set; import org.hawkular.inventory.paths.CanonicalPath; import org.hawkular.inventory.paths.SegmentType; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import io.swagger.annotations.ApiModel; /** * Metric type defines metadata of metrics of the same type. Metric types are owned by * {@link ResourceType resource type}s in the same way as {@link Metric metric}s are owned by {@link Resource resource}s * (i.e. multiple resource types can "own" a single metric type). * * @author Heiko W. Rupp * @author Lukas Krejci */ @ApiModel(description = "Metric type defines the unit and data type of a metric. It also specifies the default " + " collection interval as a guideline for the feed on how often to collect the metric values.", parent = SyncedEntity.class) public final class MetricType extends SyncedEntity<MetricType.Blueprint, MetricType.Update> { public static final SegmentType SEGMENT_TYPE = SegmentType.mt; private final MetricUnit unit; private final MetricDataType metricDataType; private final Long collectionInterval; /** * Jackson support */ @SuppressWarnings("unused") private MetricType() { unit = null; metricDataType = null; collectionInterval = null; } public MetricType(CanonicalPath path, String identityHash, String contentHash, String syncHash) { this(path, identityHash, contentHash, syncHash, MetricUnit.NONE, MetricDataType.GAUGE, null, null); } public MetricType(CanonicalPath path, String identityHash, String contentHash, String syncHash, MetricUnit unit, MetricDataType metricDataType) { this(path, identityHash, contentHash, syncHash, unit, metricDataType, null, null); } public MetricType(CanonicalPath path, String identityHash, String contentHash, String syncHash, MetricUnit unit, MetricDataType metricDataType, Long collectionInterval) { this(path, identityHash, contentHash, syncHash, unit, metricDataType, null, collectionInterval); } public MetricType(String name, CanonicalPath path, String identityHash, String contentHash, java.lang.String syncHash, MetricUnit unit, MetricDataType metricDataType) { this(name, path, identityHash, contentHash, syncHash, unit, metricDataType, null, null); } public MetricType(CanonicalPath path, String identityHash, String contentHash, String syncHash, MetricUnit unit, MetricDataType metricDataType, Map<String, Object> properties, Long collectionInterval) { super(null, path, identityHash, contentHash, syncHash, properties); if (metricDataType == null) { throw new IllegalArgumentException("metricDataType == null"); } this.unit = unit; this.metricDataType = metricDataType; this.collectionInterval = collectionInterval; } public MetricType(String name, CanonicalPath path, String identityHash, java.lang.String contentHash, java.lang.String syncHash, MetricUnit unit, MetricDataType metricDataType, Map<String, Object> properties, Long collectionInterval) { super(name, path, identityHash, contentHash, syncHash, properties); this.metricDataType = metricDataType; this.unit = unit; this.collectionInterval = collectionInterval; } public MetricUnit getUnit() { return unit; } public MetricDataType getMetricDataType() { return metricDataType; } /** * This will disappear in due time. * * @deprecated use {@link #getMetricDataType()} insteads * @return the metric data type */ @Deprecated @JsonSerialize(using = ToStringSerializer.class) public MetricDataType getType() { return getMetricDataType(); } public Long getCollectionInterval() { return collectionInterval; } @Override public Updater<Update, MetricType> update() { return new Updater<>((u) -> new MetricType(u.getName(), getPath(), getIdentityHash(), getContentHash(), getSyncHash(), valueOrDefault(u.unit, this.unit), metricDataType, u.getProperties(), valueOrDefault(u.getCollectionInterval(), collectionInterval)), this, Update.builder()); } @Override public <R, P> R accept(ElementVisitor<R, P> visitor, P parameter) { return visitor.visitMetricType(this, parameter); } @Override protected void appendToString(StringBuilder toStringBuilder) { super.appendToString(toStringBuilder); toStringBuilder.append(", unit=").append(unit); } /** * Data required to create a new metric type. * * <p>Note that tenantId, etc., are not needed here because they are provided by the context in which the * {@link org.hawkular.inventory.api.WriteInterface#create(org.hawkular.inventory.api.model.Blueprint)} method is * called. */ @ApiModel("MetricTypeBlueprint") public static final class Blueprint extends Entity.Blueprint { private final MetricUnit unit; private final MetricDataType metricDataType; private final Long collectionInterval; public static Builder builder(MetricDataType type) { return new Builder(type); } /** * JAXB support */ @SuppressWarnings("unused") private Blueprint() { unit = null; metricDataType = null; collectionInterval = null; } public Blueprint(String id, MetricUnit unit, MetricDataType metricDataType, Long collectionInterval) { this(id, unit, metricDataType, Collections.emptyMap(), collectionInterval); } public Blueprint(String id, MetricUnit unit, MetricDataType metricDataType, Map<String, Object> properties, Long collectionInterval) { super(id, properties); this.unit = unit == null ? MetricUnit.NONE : unit; this.metricDataType = metricDataType; this.collectionInterval = collectionInterval; } public Blueprint(String id, MetricUnit unit, MetricDataType metricDataType, Long collectionInterval, Map<String, Object> properties, Map<String, Set<CanonicalPath>> outgoing, Map<String, Set<CanonicalPath>> incoming) { super(id, properties, outgoing, incoming); this.metricDataType = metricDataType; this.unit = unit; this.collectionInterval = collectionInterval; } public Blueprint(String id, String name, MetricUnit unit, MetricDataType metricDataType, Map<String, Object> properties, Long collectionInterval, Map<String, Set<CanonicalPath>> outgoing, Map<String, Set<CanonicalPath>> incoming) { super(id, name, properties, outgoing, incoming); this.metricDataType = metricDataType; this.unit = unit; this.collectionInterval = collectionInterval; } public MetricUnit getUnit() { //this is so that we throw a meaningful exception when processing blueprints created by deserialization //from user data. if (unit == null) { throw new IllegalStateException("Unit of metric type cannot be null."); } return unit; } public MetricDataType getMetricDataType() { //this is so that we throw a meaningful exception when processing blueprints created by deserialization //from user data. if (metricDataType == null) { throw new IllegalStateException("Data type of metric type cannot be null."); } return metricDataType; } /** * @deprecated use {@link #getMetricDataType()} */ @Deprecated @JsonSerialize(using = ToStringSerializer.class) public MetricDataType getType() { return getMetricDataType(); } public Long getCollectionInterval() { return collectionInterval; } @Override public <R, P> R accept(ElementBlueprintVisitor<R, P> visitor, P parameter) { return visitor.visitMetricType(this, parameter); } public static final class Builder extends Entity.Blueprint.Builder<Blueprint, Builder> { private MetricUnit unit; private MetricDataType metricDataType; private Long collectionInterval; public Builder(MetricDataType metricDataType) { this.metricDataType = metricDataType; } public Builder withUnit(MetricUnit unit) { this.unit = unit; return this; } /** * @deprecated don't use this. Use the constructor instead. */ @Deprecated public Builder withType(MetricDataType type) { this.metricDataType = type; return this; } public Builder withInterval(Long interval) { this.collectionInterval = interval; return this; } @Override public Blueprint build() { return new Blueprint(id, name, unit, metricDataType, properties, collectionInterval, outgoing, incoming); } } } @ApiModel("MetricTypeUpdate") public static final class Update extends Entity.Update { private final MetricUnit unit; private final Long collectionInterval; public static Builder builder() { return new Builder(); } //Jackson support @SuppressWarnings("unused") private Update() { this(null, null, null); } public Update(Map<String, Object> properties, MetricUnit unit, Long collectionInterval) { super(null, properties); this.unit = unit; this.collectionInterval = collectionInterval; } public Update(String name, Map<String, Object> properties, MetricUnit unit, Long collectionInterval) { super(name, properties); this.unit = unit; this.collectionInterval = collectionInterval; } public MetricUnit getUnit() { return unit; } public Long getCollectionInterval() { return collectionInterval; } @Override public <R, P> R accept(ElementUpdateVisitor<R, P> visitor, P parameter) { return visitor.visitMetricType(this, parameter); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof Update)) return false; if (!super.equals(o)) return false; Update update = (Update) o; if (unit != update.unit) return false; return collectionInterval != null ? collectionInterval.equals(update.collectionInterval) : update.collectionInterval == null; } @Override public int hashCode() { int result = super.hashCode(); result = 31 * result + (unit != null ? unit.hashCode() : 0); result = 31 * result + (collectionInterval != null ? collectionInterval.hashCode() : 0); return result; } public static final class Builder extends Entity.Update.Builder<MetricType, Update, Builder> { private MetricUnit unit; private Long collectionInterval; public Builder withUnit(MetricUnit unit) { this.unit = unit; return this; } public Builder withInterval(Long interval) { this.collectionInterval = interval; return this; } @Override public Update build() { return new Update(name, properties, unit, collectionInterval); } @Override public Builder withDifference(MetricType original, MetricType updated) { if (!Objects.equals(original.getUnit(), updated.getUnit())) { withUnit(updated.getUnit()); } if (!Objects.equals(original.getCollectionInterval(), updated.getCollectionInterval())) { withInterval(updated.getCollectionInterval()); } return super.withDifference(original, updated); } } } }