/*
 * This file is part of the OpenNMS(R) Application.
 *
 * OpenNMS(R) is Copyright (C) 2008 The OpenNMS Group, Inc.  All rights reserved.
 * OpenNMS(R) is a derivative work, containing both original code, included code and modified
 * code that was published under the GNU General Public License. Copyrights for modified
 * and included code are below.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * Modifications:
 * 
 * Created: December 16, 2008
 *
 * Copyright (C) 2008 The OpenNMS Group, Inc.  All rights reserved.
 *
 * 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 of the License, 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * For more information contact:
 *      OpenNMS Licensing       <license@opennms.org>
 *      http://www.opennms.org/
 *      http://www.opennms.com/
 */
package org.opennms.netmgt.provision;

import java.net.InetAddress;
import java.util.Date;

import org.apache.log4j.Category;
import org.opennms.core.utils.ThreadCategory;
import org.opennms.netmgt.EventConstants;
import org.opennms.netmgt.dao.NodeDao;
import org.opennms.netmgt.model.OnmsNode;
import org.opennms.netmgt.model.events.EventBuilder;
import org.opennms.netmgt.model.events.EventForwarder;
import org.springframework.transaction.annotation.Transactional;


/**
 * A Dynamic DNS provisioning adapter for integration with OpenNMS Provisoning daemon API.
 * 
 * @author <a href="mailto:david@opennms.org">David Hustace</a>
 *
 */
public class DnsProvisioningAdapter implements ProvisioningAdapter {
    
    /*
     * A read-only DAO will be set by the Provisioning Daemon.
     */
    private NodeDao m_nodeDao;
    private EventForwarder m_eventForwarder;
    private static final String MESSAGE_PREFIX = "Dynamic DNS provisioning failed: ";

    /* (non-Javadoc)
     * @see org.opennms.netmgt.provision.ProvisioningAdapter#addNode(org.opennms.netmgt.model.OnmsNode)
     */
    @Transactional
    public void addNode(int nodeId) throws ProvisioningAdapterException {
        OnmsNode node = null;
        try {
            node = m_nodeDao.get(nodeId);
            DnsRecord record = new DnsRecord(node);
            DynamicDnsAdapter.add(record);
        } catch (Exception e) {
            log().error("updateNode: Error handling node added event.", e);
            sendAndThrow(nodeId, e);
        }
    }

    /* (non-Javadoc)
     * @see org.opennms.netmgt.provision.ProvisioningAdapter#updateNode(org.opennms.netmgt.model.OnmsNode)
     */
    @Transactional
    public void updateNode(int nodeId) throws ProvisioningAdapterException {
        try {
            OnmsNode node = m_nodeDao.get(nodeId);
            DnsRecord record = new DnsRecord(node);
            DynamicDnsAdapter.update(record);
        } catch (Exception e) {
            log().error("updateNode: Error handling node added event.", e);
            sendAndThrow(nodeId, e);
        }
    }
    
    /* (non-Javadoc)
     * @see org.opennms.netmgt.provision.ProvisioningAdapter#deleteNode(org.opennms.netmgt.model.OnmsNode)
     */
    @Transactional
    public void deleteNode(int nodeId) throws ProvisioningAdapterException {
        try {
            OnmsNode node = m_nodeDao.get(nodeId);
            DnsRecord record = new DnsRecord(node);
            DynamicDnsAdapter.delete(record);
        } catch (Exception e) {
            log().error("deleteNode: Error handling node deleted event.", e);
            sendAndThrow(nodeId, e);
        }
    }

    private void sendAndThrow(int nodeId, Exception e) {
        m_eventForwarder.sendNow(buildEvent(EventConstants.PROVISIONING_ADAPTER_FAILED, nodeId).addParam("reason", MESSAGE_PREFIX+e.getLocalizedMessage()).getEvent());
        throw new ProvisioningAdapterException(MESSAGE_PREFIX, e);
    }

    private EventBuilder buildEvent(String uei, int nodeId) {
        EventBuilder builder = new EventBuilder(uei, "Provisioner", new Date());
        builder.setNodeid(nodeId);
        return builder;
    }

    public NodeDao getNodeDao() {
        return m_nodeDao;
    }
    public void setNodeDao(NodeDao dao) {
        m_nodeDao = dao;
    }
    
    public void setEventForwarder(EventForwarder eventForwarder) {
        m_eventForwarder = eventForwarder;
    }

    public EventForwarder getEventForwarder() {
        return m_eventForwarder;
    }

    class DnsRecord {
        private InetAddress m_ip;
        private String m_hostname;
        
        DnsRecord(OnmsNode node) {
            m_ip = node.getCriticalInterface().getInetAddress();
            m_hostname = node.getLabel();
        }

        public InetAddress getIp() {
            return m_ip;
        }

        public String getHostname() {
            return m_hostname;
        }
    }
    
    static class DynamicDnsAdapter {
        
        static boolean add(DnsRecord record) {
            log().error("DNS Adapter not Implemented.");
            throw new UnsupportedOperationException("method not yet implemented.");
        }
        
        static boolean update(DnsRecord record) {
            log().error("DNS Adapter not Implemented.");
            throw new UnsupportedOperationException("method not yet implemented.");
        }
        
        static boolean delete(DnsRecord record) {
            log().error("DNS Adapter not Implemented.");
            throw new UnsupportedOperationException("method not yet implemented.");
        }

        static public DnsRecord getRecord(DnsRecord record) {
            log().error("DNS Adapter not Implemented.");
            throw new UnsupportedOperationException("method not yet implemented.");
        }
    }
    
    private static Category log() {
        return ThreadCategory.getInstance(DnsProvisioningAdapter.class);
    }

}

@@ -1509,16 +1509,38 @@
 il.Date;
+%0Aimport java.util.Set;
 %0A%0Aimport
@@ -1694,16 +1694,65 @@
 odeDao;%0A
+import org.opennms.netmgt.model.OnmsIpInterface;%0A
 import o
@@ -2901,38 +2901,35 @@
    log().error(%22
-update
+add
 Node: Error hand
@@ -5135,20 +5135,48 @@
         
-m_ip
+OnmsIpInterface primaryInterface
  = node.
@@ -5182,45 +5182,403 @@
 .get
-CriticalInterface().getInetAddress();
+PrimaryInterface();%0A            %0A            if (primaryInterface == null) %7B%0A                Set%3COnmsIpInterface%3E ipInterfaces = node.getIpInterfaces();%0A                for (OnmsIpInterface onmsIpInterface : ipInterfaces) %7B%0A                    m_ip = onmsIpInterface.getInetAddress();%0A                %7D%0A            %7D else %7B%0A                m_ip = primaryInterface.getInetAddress();%0A            %7D
 %0A   

fix NPE