/*
* 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.bus;
import static org.hawkular.inventory.api.Action.contentHashChanged;
import static org.hawkular.inventory.api.Action.identityHashChanged;
import static org.hawkular.inventory.api.Action.syncHashChanged;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import org.hawkular.inventory.api.Action;
import org.hawkular.inventory.api.Interest;
import org.hawkular.inventory.api.Inventory;
import org.hawkular.inventory.api.model.AbstractElement;
import org.hawkular.inventory.api.model.DataEntity;
import org.hawkular.inventory.api.model.Environment;
import org.hawkular.inventory.api.model.Feed;
import org.hawkular.inventory.api.model.MetadataPack;
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.api.model.ResourceType;
import org.hawkular.inventory.api.model.Tenant;
import rx.Subscription;
/**
* @author Lukas Krejci
* @since 0.0.1
*/
public final class BusIntegration {
private final Inventory inventory;
private MessageSender messageSender;
private QueryListener queryListener;
private final Set<Subscription> subscriptions = new HashSet<>();
private Configuration configuration;
private InitialContext namingContext;
public BusIntegration(Inventory inventory) {
this.inventory = inventory;
}
public void configure(Configuration configuration) {
this.configuration = configuration;
}
public void start() throws NamingException, JMSException {
if (namingContext != null) {
return;
}
namingContext = new InitialContext();
ConnectionFactory connectionFactory = (ConnectionFactory) namingContext.lookup(
configuration.getConnectionFactoryJndiName());
this.messageSender = new MessageSender(connectionFactory, configuration.getInventoryChangesTopicName());
install();
this.queryListener = new QueryListener(inventory, connectionFactory, configuration.getQueryQueueName());
}
public void stop() throws NamingException, IOException {
uninstall();
namingContext.close();
namingContext = null;
queryListener.close();
queryListener = null;
}
private void install() {
install(inventory, subscriptions, Tenant.class, messageSender, contentHashChanged());
install(inventory, subscriptions, MetadataPack.class, messageSender);
install(inventory, subscriptions, ResourceType.class, messageSender, syncHashChanged(), identityHashChanged(),
contentHashChanged());
install(inventory, subscriptions, MetricType.class, messageSender, syncHashChanged(), identityHashChanged(),
contentHashChanged());
install(inventory, subscriptions, Environment.class, messageSender, Action.copied(), contentHashChanged());
install(inventory, subscriptions, Feed.class, messageSender, Action.registered(), syncHashChanged(),
identityHashChanged(), contentHashChanged());
install(inventory, subscriptions, Resource.class, messageSender, syncHashChanged(), identityHashChanged(),
contentHashChanged());
install(inventory, subscriptions, Metric.class, messageSender, syncHashChanged(), identityHashChanged(),
contentHashChanged());
install(inventory, subscriptions, Relationship.class, messageSender);
install(inventory, subscriptions, DataEntity.class, messageSender, syncHashChanged(), identityHashChanged(),
contentHashChanged());
}
private void uninstall() {
subscriptions.forEach(Subscription::unsubscribe);
}
@SafeVarargs
private static <U extends AbstractElement.Update, T extends AbstractElement<?, U>>
void install(Inventory inventory, Set<Subscription> subscriptions, Class<T> entityClass,
MessageSender sender, Action<?, T>... additionalActions) {
installAction(inventory, subscriptions, entityClass, sender, Action.created());
installAction(inventory, subscriptions, entityClass, sender, Action.updated());
installAction(inventory, subscriptions, entityClass, sender, Action.deleted());
for (Action<?, T> a : additionalActions) {
installAction(inventory, subscriptions, entityClass, sender, a);
}
}
private static <C, T extends AbstractElement> void installAction(Inventory inventory, Set<Subscription>
subscriptions, Class<T> entityClass, MessageSender sender, Action<C, T> action) {
Interest<C, T> interest = Interest.in(entityClass).being(action);
Subscription s = inventory.observable(interest).subscribe((c) -> {
// todo: ugly
Tenant t;
if (c instanceof AbstractElement) {
if (c instanceof Relationship) {
t = new Tenant(((Relationship) c).getSource().getRoot(), null);
} else {
t = new Tenant(((AbstractElement) c).getPath().getRoot(), null);
}
} else if (c instanceof Action.EnvironmentCopy) {
t = new Tenant(((Action.EnvironmentCopy) c).getSource().getPath().getRoot(), null);
} else if (c instanceof Action.Update) {
t = new Tenant(((AbstractElement) ((Action.Update) c).getOriginalEntity()).getPath().getRoot(),
null);
} else {
throw new IllegalArgumentException("Unknown event type: " + c.getClass().getName());
}
sender.send(interest, t, c);
});
subscriptions.add(s);
}
}