All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.freedomotic.core.Autodiscovery Maven / Gradle / Ivy

/**
 *
 * Copyright (c) 2009-2014 Freedomotic team http://freedomotic.com
 *
 * This file is part of Freedomotic
 *
 * This Program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2, or (at your option) any later version.
 *
 * This Program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * Freedomotic; see the file COPYING. If not, see
 * .
 */
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.freedomotic.core;

import com.freedomotic.api.Client;
import com.freedomotic.bus.BusConsumer;
import com.freedomotic.bus.BusMessagesListener;
import com.freedomotic.bus.BusService;
import com.freedomotic.exceptions.RepositoryException;
import com.freedomotic.model.object.Behavior;
import com.freedomotic.plugins.ClientStorage;
import com.freedomotic.plugins.ObjectPluginPlaceholder;
import com.freedomotic.things.ThingRepository;
import com.freedomotic.reactions.Command;
import com.freedomotic.reactions.CommandPersistence;
import com.freedomotic.reactions.TriggerPersistence;
import com.freedomotic.things.EnvObjectLogic;
import com.google.inject.Inject;
import java.io.File;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jms.JMSException;
import javax.jms.ObjectMessage;

/**
 *
 * @author enrico
 */
public final class Autodiscovery implements BusConsumer {

    private static final String MESSAGING_CHANNEL = "app.objects.create";

    private static BusMessagesListener listener;
    private static final Logger LOG = Logger.getLogger(Autodiscovery.class.getName());

    // Dependencies
    private final ClientStorage clientStorage;
    private final BusService busService;
    private final ThingRepository thingsRepository;

    @Inject
    Autodiscovery(ClientStorage clientStorage, ThingRepository thingsRepository, BusService busService) {
        this.clientStorage = clientStorage;
        this.thingsRepository = thingsRepository;
        this.busService = busService;
        register();
    }

    static String getMessagingChannel() {
        return MESSAGING_CHANNEL;
    }

    /**
     * Register one or more channels to listen to
     */
    private void register() {
        listener = new BusMessagesListener(this, busService);
        listener.consumeCommandFrom(getMessagingChannel());
    }

    @Override
    public void onMessage(ObjectMessage message) {
        try {
            Object jmsObject = message.getObject();

            if (jmsObject instanceof Command) {
                Command command = (Command) jmsObject;
                String name = command.getProperty("object.name");
                String protocol = command.getProperty("object.protocol");
                String address = command.getProperty("object.address");
                String clazz = command.getProperty("object.class");

                if (thingsRepository.findByAddress(protocol, address).isEmpty()) {
                    join(clazz, name, protocol, address);
                }
            }
        } catch (JMSException ex) {
            Logger.getLogger(Autodiscovery.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     *
     * @param clazz
     * @param name
     * @param protocol
     * @param address
     * @return
     */
    protected EnvObjectLogic join(String clazz, String name, String protocol, String address) {
        EnvObjectLogic loaded = null;
        ObjectPluginPlaceholder objectPlugin = (ObjectPluginPlaceholder) clientStorage.get(clazz);

        if (objectPlugin == null) {
            LOG.log(Level.WARNING, "Autodiscovery error: doesn''t exist an object class called {0}", clazz);
            return null;
        }
        
        LOG.log(Level.WARNING, "Autodiscovery request for an object called ''{0}'' of type ''{1}''", new Object[]{name, clazz});

        File templateFile = objectPlugin.getTemplate();
        try {
            loaded = thingsRepository.load(templateFile);
        } catch (RepositoryException ex) {
            LOG.log(Level.SEVERE, null, ex);
        }
        //changing the name and other properties invalidates related trigger and commands
        //call init() again after this changes
        if ((name != null) && !name.isEmpty()) {
            loaded.getPojo().setName(name);
        } else {
            loaded.getPojo().setName(protocol);
        }

        loaded = thingsRepository.copy(loaded);
        loaded.getPojo().setProtocol(protocol);
        loaded.getPojo().setPhisicalAddress(address);
        // Remove the 'virtual' tag and any other actAs configuration. 
        //TODO: it would be better to remove the actAs property and manage all with tags
        loaded.getPojo().setActAs("");
        loaded.setRandomLocation();

        //set the PREFERRED MAPPING of the protocol plugin (if any is defined in its manifest)
        Client addon = clientStorage.getClientByProtocol(protocol);

        if (addon != null) {
            for (int i = 0; i < addon.getConfiguration().getTuples().size(); i++) {
                Map tuple = addon.getConfiguration().getTuples().getTuple(i);
                String regex = (String) tuple.get("object.class");

                if ((regex != null) && clazz.matches(regex)) {
                    //map object behaviors to hardware triggers
                    for (Behavior behavior : loaded.getPojo().getBehaviors()) {
                        String triggerName = (String) tuple.get(behavior.getName());
                        if (triggerName != null) {
                            loaded.addTriggerMapping(TriggerPersistence.getTrigger(triggerName),
                                    behavior.getName());
                        }
                    }

                    for (String action : loaded.getPojo().getActions().stringPropertyNames()) {
                        String commandName = (String) tuple.get(action);

                        if (commandName != null) {
                            loaded.setAction(action,
                                    CommandPersistence.getHardwareCommand(commandName));
                        }
                    }
                }
            }
        }
        LOG.log(Level.INFO, "Autodiscovery adds a thing called ''{0}'' of type ''{1}''", 
                new Object[]{loaded.getPojo().getName(), clazz});
        return loaded;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy