/* * 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.base; import static org.hawkular.inventory.api.Action.created; import static org.hawkular.inventory.api.Relationships.WellKnown.defines; import static org.hawkular.inventory.api.Relationships.WellKnown.incorporates; import static org.hawkular.inventory.api.filters.With.id; import java.util.ArrayList; import java.util.List; import org.hawkular.inventory.api.EntityAlreadyExistsException; import org.hawkular.inventory.api.EntityNotFoundException; import org.hawkular.inventory.api.Metrics; import org.hawkular.inventory.api.filters.Filter; import org.hawkular.inventory.api.model.Metric; import org.hawkular.inventory.api.model.MetricType; import org.hawkular.inventory.api.model.Relationship; import org.hawkular.inventory.api.model.Resource; import org.hawkular.inventory.base.spi.Discriminator; import org.hawkular.inventory.base.spi.ElementNotFoundException; import org.hawkular.inventory.paths.CanonicalPath; import org.hawkular.inventory.paths.Path; import org.hawkular.inventory.paths.SegmentType; /** * @author Lukas Krejci * @since 0.1.0 */ public final class BaseMetrics { private BaseMetrics() { } public static class ReadWrite<BE> extends Mutator<BE, Metric, Metric.Blueprint, Metric.Update, String> implements Metrics.ReadWrite { public ReadWrite(TraversalContext<BE, Metric> context) { super(context); } @Override protected String getProposedId(Transaction<BE> tx, Metric.Blueprint blueprint) { return blueprint.getId(); } @Override protected EntityAndPendingNotifications<BE, Metric> wireUpNewEntity(Discriminator discriminator, BE entity, Metric.Blueprint blueprint, CanonicalPath parentPath, BE parent, Transaction<BE> tx) { BE metricTypeObject; try { CanonicalPath tenant = CanonicalPath.of().tenant(parentPath.ids().getTenantId()).get(); CanonicalPath metricTypePath = Util.canonicalize(blueprint.getMetricTypePath(), tenant, parentPath, MetricType.SEGMENT_TYPE); metricTypeObject = tx.find(discriminator, metricTypePath); } catch (ElementNotFoundException e) { throw new IllegalArgumentException("A metric type with path '" + blueprint.getMetricTypePath() + "' not found relative to '" + parentPath + "'."); } //specifically do NOT check relationship rules, here because defines cannot be created "manually". //here we "know what we are doing" and need to create the defines relationship to capture the //contract of the metric. BE r = tx.relate(discriminator, metricTypeObject, entity, defines.name(), null); CanonicalPath entityPath = tx.extractCanonicalPath(entity); MetricType metricType = tx.convert(discriminator, metricTypeObject, MetricType.class); Metric ret = new Metric(blueprint.getName(), parentPath.extend(Metric.SEGMENT_TYPE, tx.extractId(entity)).get(), null, null, null, metricType, blueprint.getCollectionInterval(), blueprint.getProperties()); Relationship rel = new Relationship(tx.extractId(r), defines.name(), parentPath, entityPath); List<Notification<?, ?>> notifs = new ArrayList<>(); notifs.add(new Notification<>(rel, rel, created())); if (Resource.class.equals(tx.extractType(parent))) { r = tx.relate(discriminator, parent, entity, incorporates.name(), null); rel = new Relationship(tx.extractId(r), incorporates.name(), parentPath, entityPath); notifs.add(new Notification<>(rel, rel, created())); } return new EntityAndPendingNotifications<>(entity, ret, notifs); } @Override public Metrics.Multiple getAll(Filter[][] filters) { return new Multiple<>(context.proceed().whereAll(filters).get()); } @Override public Metrics.Single get(String id) throws EntityNotFoundException { return new Single<>(context.proceed().where(id(id)).get()); } @Override public Metrics.Single create(Metric.Blueprint blueprint, boolean cache) throws EntityAlreadyExistsException { return new Single<>(context.toCreatedEntity(doCreate(blueprint), cache)); } } public static class ReadContained<BE> extends Traversal<BE, Metric> implements Metrics.ReadContained { public ReadContained(TraversalContext<BE, Metric> context) { super(context); } @Override public Metrics.Multiple getAll(Filter[][] filters) { return new Multiple<>(context.proceed().whereAll(filters).get()); } @Override public Metrics.Single get(String id) throws EntityNotFoundException { return new Single<>(context.proceed().where(id(id)).get()); } } public static class Read<BE> extends Traversal<BE, Metric> implements Metrics.Read { public Read(TraversalContext<BE, Metric> context) { super(context); } @Override public Metrics.Multiple getAll(Filter[][] filters) { return new Multiple<>(context.proceed().whereAll(filters).get()); } @Override public Metrics.Single get(Path id) throws EntityNotFoundException { return new Single<>(context.proceedTo(id)); } } public static class ReadAssociate<BE> extends Associator<BE, Metric> implements Metrics.ReadAssociate { public ReadAssociate(TraversalContext<BE, Metric> context) { super(context, incorporates, SegmentType.r); } @Override public Metrics.Multiple getAll(Filter[][] filters) { return new Multiple<>(context.proceed().whereAll(filters).get()); } @Override public Metrics.Single get(Path id) throws EntityNotFoundException { return new Single<>(context.proceedTo(id)); } } public static class Single<BE> extends SingleSyncedFetcher<BE, Metric, Metric.Blueprint, Metric.Update> implements Metrics.Single { public Single(TraversalContext<BE, Metric> context) { super(context); } } public static class Multiple<BE> extends MultipleEntityFetcher<BE, Metric, Metric.Update> implements Metrics.Multiple { public Multiple(TraversalContext<BE, Metric> context) { super(context); } } }