/*
* 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.incorporates;
import static org.hawkular.inventory.api.filters.With.id;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.hawkular.inventory.api.EntityAlreadyExistsException;
import org.hawkular.inventory.api.EntityNotFoundException;
import org.hawkular.inventory.api.MetadataPacks;
import org.hawkular.inventory.api.MetricTypes;
import org.hawkular.inventory.api.Query;
import org.hawkular.inventory.api.ResourceTypes;
import org.hawkular.inventory.api.filters.Filter;
import org.hawkular.inventory.api.model.Entity;
import org.hawkular.inventory.api.model.IdentityHash;
import org.hawkular.inventory.api.model.MetadataPack;
import org.hawkular.inventory.api.model.MetricType;
import org.hawkular.inventory.api.model.Relationship;
import org.hawkular.inventory.api.model.ResourceType;
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.7.0
*/
public final class BaseMetadataPacks {
private BaseMetadataPacks() {
}
public static class ReadWrite<BE> extends Mutator<BE, MetadataPack, MetadataPack.Blueprint, MetadataPack.Update,
String> implements MetadataPacks.ReadWrite {
public ReadWrite(TraversalContext<BE, MetadataPack> context) {
super(context);
}
@SuppressWarnings("unchecked")
@Override
protected String getProposedId(Transaction<BE> tx, MetadataPack.Blueprint blueprint) {
Iterator<? extends Entity<? extends Entity.Blueprint, ?>> members = blueprint.getMembers().stream()
.map((p) -> {
SegmentType type = p.getSegment().getElementType();
Class<?> cls = Entity.entityTypeFromSegmentType(type);
try {
BE e = tx.find(context.discriminator(), p);
return (Entity<? extends Entity.Blueprint, ?>) tx.convert(context.discriminator(), e, cls);
} catch (ElementNotFoundException ex) {
throw new EntityNotFoundException(cls, Query.filters(Query.to(p)));
}
}).iterator();
return IdentityHash.of(members, context.inventory.keepTransaction(tx));
}
@Override
protected EntityAndPendingNotifications<BE, MetadataPack>
wireUpNewEntity(Discriminator discriminator, BE entity, MetadataPack.Blueprint blueprint,
CanonicalPath parentPath, BE parent,
Transaction<BE> tx) {
Set<Notification<?, ?>> newRels = new HashSet<>();
blueprint.getMembers().forEach((p) -> {
try {
BE member = tx.find(discriminator, p);
BE rel = tx.relate(discriminator, entity, member, incorporates.name(), null);
Relationship r = tx.convert(discriminator, rel, Relationship.class);
newRels.add(new Notification<>(r, r, created()));
} catch (ElementNotFoundException e) {
throw new EntityNotFoundException(p.getSegment().getElementType().getSimpleName(),
Query.filters(Query.to(p)));
}
});
MetadataPack entityObject = tx.convert(discriminator, entity, MetadataPack.class);
return new EntityAndPendingNotifications<>(entity, entityObject, newRels);
}
@Override public MetadataPacks.Multiple getAll(Filter[][] filters) {
return new Multiple<>(context.proceed().whereAll(filters).get());
}
@Override public MetadataPacks.Single get(String id) throws EntityNotFoundException {
return new Single<>(context.proceed().where(id(id)).get());
}
@Override public MetadataPacks.Single create(MetadataPack.Blueprint blueprint, boolean cache)
throws EntityAlreadyExistsException {
blueprint.getMembers().forEach(p -> {
if (p.ids().getFeedId() != null) {
throw new IllegalArgumentException("Only global types can be part of a metadata pack. No " +
"feed-local types are allowed but '" + p + "' encountered.");
}
});
return new Single<>(context.toCreatedEntity(doCreate(blueprint), cache));
}
}
public static class ReadContained<BE> extends Traversal<BE, MetadataPack> implements MetadataPacks.ReadContained {
public ReadContained(TraversalContext<BE, MetadataPack> context) {
super(context);
}
@Override public MetadataPacks.Multiple getAll(Filter[][] filters) {
return new Multiple<>(context.proceed().whereAll(filters).get());
}
@Override public MetadataPacks.Single get(String id) throws EntityNotFoundException {
return new Single<>(context.proceed().where(id(id)).get());
}
}
public static class Read<BE> extends Traversal<BE, MetadataPack> implements MetadataPacks.Read {
public Read(TraversalContext<BE, MetadataPack> context) {
super(context);
}
@Override public MetadataPacks.Multiple getAll(Filter[][] filters) {
return new Multiple<>(context.proceed().whereAll(filters).get());
}
@Override public MetadataPacks.Single get(Path path) throws EntityNotFoundException {
return new Single<>(context.proceedTo(path));
}
}
public static class Single<BE> extends SingleEntityFetcher<BE, MetadataPack, MetadataPack.Update>
implements MetadataPacks.Single {
public Single(TraversalContext<BE, MetadataPack> context) {
super(context);
}
@Override public ResourceTypes.Read resourceTypes() {
return new BaseResourceTypes.Read<>(context.proceedTo(incorporates, ResourceType.class).get());
}
@Override public MetricTypes.Read metricTypes() {
return new BaseMetricTypes.Read<>(context.proceedTo(incorporates, MetricType.class).get());
}
}
public static class Multiple<BE> extends MultipleEntityFetcher<BE, MetadataPack, MetadataPack.Update>
implements MetadataPacks.Multiple {
public Multiple(TraversalContext<BE, MetadataPack> context) {
super(context);
}
@Override public ResourceTypes.Read resourceTypes() {
return new BaseResourceTypes.Read<>(context.proceedTo(incorporates, ResourceType.class).get());
}
@Override public MetricTypes.Read metricTypes() {
return new BaseMetricTypes.Read<>(context.proceedTo(incorporates, MetricType.class).get());
}
}
}