/* * 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.filters.With.type; import org.hawkular.inventory.api.EntityNotFoundException; import org.hawkular.inventory.api.Query; import org.hawkular.inventory.api.RelationAlreadyExistsException; import org.hawkular.inventory.api.RelationNotFoundException; import org.hawkular.inventory.api.Relationships; import org.hawkular.inventory.api.model.Entity; import org.hawkular.inventory.api.model.Relationship; import org.hawkular.inventory.paths.Path; import org.hawkular.inventory.paths.SegmentType; /** * A base class for implementations of {@code *ReadAssociate} implementations. * * @author Lukas Krejci * @since 0.1.0 */ class Associator<BE, E extends Entity<?, ?>> extends Traversal<BE, E> { private final Relationships.WellKnown relationship; private final SegmentType sourceEntityType; protected Associator(TraversalContext<BE, E> context, Relationships.WellKnown relationship, SegmentType sourceEntityType) { super(context); this.relationship = relationship; this.sourceEntityType = sourceEntityType; } public Relationship associate(Path id) throws EntityNotFoundException, RelationAlreadyExistsException { checkPathLegal(id); return associate(context, sourceEntityType, relationship, id); } static <BE> Relationship associate(TraversalContext<BE, ?> context, SegmentType sourceEntityType, Relationships.WellKnown relationship, Path id) { return inTx(context, tx -> { BE target = Util.find(context.discriminator(), tx, context.sourcePath, id); Query sourceQuery = context.sourcePath.extend().filter().with(type(sourceEntityType)).get(); BE source = tx.querySingle(context.discriminator(), sourceQuery); EntityAndPendingNotifications<BE, Relationship> rel = Util.createAssociation(context.discriminator(), tx, source, relationship.name(), target, null); tx.getPreCommit().addNotifications(rel); return rel.getEntity(); }); } public Relationship disassociate(Path id) throws EntityNotFoundException { checkPathLegal(id); return disassociate(context, sourceEntityType, relationship, id); } static <BE> Relationship disassociate(TraversalContext<BE, ?> context, SegmentType sourceEntityType, Relationships.WellKnown relationship, Path id) { return inTx(context, tx -> { BE target = Util.find(context.discriminator(), tx, context.sourcePath, id); Query sourceQuery = context.sourcePath.extend().filter().with(type(sourceEntityType)).get(); EntityAndPendingNotifications<BE, Relationship> rel = Util.deleteAssociation(context.discriminator(), tx, sourceQuery, sourceEntityType, relationship.name(), target); tx.getPreCommit().addNotifications(rel); return rel.getEntity(); }); } public Relationship associationWith(Path path) throws RelationNotFoundException { return associationWith(context, sourceEntityType, relationship, path); } static <BE> Relationship associationWith(TraversalContext<BE, ?> context, SegmentType sourceEntityType, Relationships.WellKnown relationship, Path path) throws RelationNotFoundException { return inTx(context, tx -> { Query sourceQuery = context.sourcePath.extend().filter().with(type(sourceEntityType)).get(); Query targetQuery = Util.queryTo(context.sourcePath, path); SegmentType targetType = path.getSegment().getElementType(); return Util.getAssociation(context.discriminator(), tx, sourceQuery, sourceEntityType, targetQuery, targetType, relationship.name()); }); } protected void checkPathLegal(Path targetPath) { if (!context.entityClass.getSimpleName().equals(targetPath.getSegment().getElementType().getSimpleName())) { throw new IllegalArgumentException("Current position in the inventory traversal expects entities of type " + context.entityClass.getSimpleName() + " which is incompatible with the provided path: " + targetPath); } } /** * @return the type of the source entity of the association on this position in the inventory traversal */ @SuppressWarnings("unchecked") protected Class<? extends Entity<?, ?>> getSourceType() { return (Class<? extends Entity<?, ?>>) context.previous.entityClass; } }