/*
* 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 java.util.Collections.emptyList;
import static org.hawkular.inventory.api.Relationships.WellKnown.contains;
import static org.hawkular.inventory.api.Relationships.WellKnown.incorporates;
import static org.hawkular.inventory.api.Relationships.WellKnown.isParentOf;
import static org.hawkular.inventory.api.filters.Related.by;
import static org.hawkular.inventory.api.filters.With.id;
import static org.hawkular.inventory.api.filters.With.type;
import org.hawkular.inventory.api.EntityAlreadyExistsException;
import org.hawkular.inventory.api.EntityNotFoundException;
import org.hawkular.inventory.api.Environments;
import org.hawkular.inventory.api.Feeds;
import org.hawkular.inventory.api.Metrics;
import org.hawkular.inventory.api.Resources;
import org.hawkular.inventory.api.filters.Filter;
import org.hawkular.inventory.api.filters.RecurseFilter;
import org.hawkular.inventory.api.model.Environment;
import org.hawkular.inventory.api.model.Feed;
import org.hawkular.inventory.api.model.Metric;
import org.hawkular.inventory.api.model.Resource;
import org.hawkular.inventory.base.spi.Discriminator;
import org.hawkular.inventory.paths.CanonicalPath;
import org.hawkular.inventory.paths.Path;
/**
* @author Lukas Krejci
* @since 0.1.0
*/
public final class BaseEnvironments {
private BaseEnvironments() {
}
private static <BE>
BaseResources.Read<BE> proceedToResources(TraversalContext<BE, Environment> context,
Environments.ResourceParents... parents) {
return new BaseResources.Read<>(context.proceedWithParents(Resource.class,
Environments.ResourceParents.class, Environments.ResourceParents.ENVIRONMENT, parents,
(p, extender) -> {
switch (p) {
case ENVIRONMENT:
extender.path().with(by(contains), type(Resource.class));
break;
case FEED:
extender.path()
.with(by(incorporates), type(Feed.class), by(contains), type(Resource.class));
break;
case RESOURCE:
//go to root resources, wherever they are
extender.path().with(new Filter[][]{
{by(contains), type(Resource.class)},
{by(incorporates), type(Feed.class), by(contains), type(Resource.class)}});
//and then go to the child resources
extender.path().with(RecurseFilter.builder().addChain(by(isParentOf), type(Resource
.class)).build());
break;
default:
throw new AssertionError("Unhandled type of resource parent under environment.");
}
}));
}
private static <BE>
BaseMetrics.Read<BE> proceedToMetrics(TraversalContext<BE, Environment> context,
Environments.MetricParents... parents) {
return new BaseMetrics.Read<>(context.proceedWithParents(Metric.class,
Environments.MetricParents.class, Environments.MetricParents.ENVIRONMENT, parents, (p, extender) -> {
switch (p) {
case ENVIRONMENT:
extender.path().with(by(contains), type(Metric.class));
break;
case FEED:
extender.path().with(by(incorporates), type(Feed.class), by(contains), type(Metric.class));
break;
case RESOURCE:
//out by all possible paths from env to a resource
extender.path().with(new Filter[][]{
{by(contains), type(Resource.class)},
{by(incorporates), type(Feed.class), by(contains), type(Resource.class)}});
//out to direct metrics and also metrics of child resources
extender.path().with(new Filter[][]{
{by(contains), type(Metric.class)},
{RecurseFilter.builder().addChain(by(contains), type(Resource.class)).build(),
by(contains), type(Metric.class)}});
break;
default:
throw new AssertionError("Unhandled type of metric parent under environment.");
}
}));
}
public static class ReadWrite<BE>
extends Mutator<BE, Environment, Environment.Blueprint, Environment.Update, String>
implements Environments.ReadWrite {
public ReadWrite(TraversalContext<BE, Environment> context) {
super(context);
}
@Override
protected String getProposedId(Transaction<BE> tx, Environment.Blueprint blueprint) {
return blueprint.getId();
}
@Override
protected EntityAndPendingNotifications<BE, Environment>
wireUpNewEntity(Discriminator discriminator, BE entity, Environment.Blueprint blueprint,
CanonicalPath parentPath, BE parent,
Transaction<BE> tx) {
return new EntityAndPendingNotifications<>(entity, new Environment(blueprint.getName(),
parentPath.extend(Environment.SEGMENT_TYPE, tx.extractId(entity)).get(),
null, blueprint.getProperties()), emptyList());
}
@Override
public void copy(String sourceEnvironmentId, String targetEnvironmentId) {
//TODO implement
throw new UnsupportedOperationException();
}
@Override
public Environments.Multiple getAll(Filter[][] filters) {
return new Multiple<>(context.proceed().whereAll(filters).get());
}
@Override
public Environments.Single get(String id) throws EntityNotFoundException {
return new Single<>(context.proceed().where(id(id)).get());
}
@Override
public Environments.Single create(Environment.Blueprint blueprint, boolean cache) throws EntityAlreadyExistsException {
return new Single<>(context.toCreatedEntity(doCreate(blueprint), cache));
}
}
public static class ReadContained<BE> extends Traversal<BE, Environment> implements Environments.ReadContained {
public ReadContained(TraversalContext<BE, Environment> context) {
super(context);
}
@Override
public Environments.Multiple getAll(Filter[][] filters) {
return new Multiple<>(context.proceed().whereAll(filters).get());
}
@Override
public Environments.Single get(String id) throws EntityNotFoundException {
return new Single<>(context.proceed().where(id(id)).get());
}
}
public static class Read<BE> extends Traversal<BE, Environment> implements Environments.Read {
public Read(TraversalContext<BE, Environment> context) {
super(context);
}
@Override
public Environments.Multiple getAll(Filter[][] filters) {
return new Multiple<>(context.proceed().whereAll(filters).get());
}
@Override
public Environments.Single get(Path id) throws EntityNotFoundException {
return new Single<>(context.proceedTo(id));
}
}
public static class Single<BE> extends SingleEntityFetcher<BE, Environment, Environment.Update>
implements Environments.Single {
public Single(TraversalContext<BE, Environment> context) {
super(context);
}
@Override
public Feeds.ReadAssociate feeds() {
return new BaseFeeds.ReadAssociate<>(context.proceedTo(incorporates, Feed.class).get());
}
@Override
public Resources.ReadWrite resources() {
return new BaseResources.ReadWrite<>(context.proceedTo(contains, Resource.class).get());
}
@Override
public Metrics.ReadWrite metrics() {
return new BaseMetrics.ReadWrite<>(context.proceedTo(contains, Metric.class).get());
}
@Override
public Metrics.Read metricsUnder(Environments.MetricParents... parents) {
return proceedToMetrics(context, parents);
}
@Override
public Resources.Read resourcesUnder(Environments.ResourceParents... parents) {
return proceedToResources(context, parents);
}
}
public static class Multiple<BE> extends MultipleEntityFetcher<BE, Environment, Environment.Update>
implements Environments.Multiple {
public Multiple(TraversalContext<BE, Environment> context) {
super(context);
}
@Override
public Feeds.Read feeds() {
return new BaseFeeds.Read<>(context.proceedTo(incorporates, Feed.class).get());
}
@Override
public Resources.ReadContained resources() {
return new BaseResources.ReadContained<>(context.proceedTo(contains, Resource.class).get());
}
@Override
public Metrics.ReadContained metrics() {
return new BaseMetrics.ReadContained<>(context.proceedTo(contains, Metric.class).get());
}
@Override
public Metrics.Read metricsUnder(Environments.MetricParents... parents) {
return proceedToMetrics(context, parents);
}
@Override
public Resources.Read resourcesUnder(Environments.ResourceParents... parents) {
return proceedToResources(context, parents);
}
}
}