/******************************************************************
 * File:        Message.java
 * Created by:  Dave Reynolds
 * Created on:  6 May 2013
 * 
 * (c) Copyright 2013, Epimorphics Limited
 *
 *  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 com.epimorphics.registry.message;

import java.util.List;

import com.epimorphics.registry.commands.CommandStatusUpdate;
import com.epimorphics.registry.core.Command;
import com.epimorphics.registry.core.RegisterItem;
import org.apache.jena.rdf.model.Model;
import org.apache.jena.rdf.model.RDFNode;
import org.apache.jena.rdf.model.Resource;
import org.apache.jena.vocabulary.RDF;

/**
 * Format for notification messages. These are used to allow for processing or
 * logging to be trigger by registration/change events. A variety of
 * message infrastructures may be used including MQ style.
 * <p>
 * For a status update the message will be the new status.
 * </p><p>
 * For an update the target will be the resource updated and the payload will be
 * the post-update description of the resource (i.e. after any patch processing).
 * </p><p>
 * For a registration the target will be the item registered.
 * </p>
 * @author <a href="mailto:dave@epimorphics.com">Dave Reynolds</a>
 */
public class Message {

    String target;
    String entity;
    String operation;
    String[] types;
    Object message;
    
    /**
     * Create a empty message
     */
    public Message() {
    }

    
    public void setTarget(String target) {
        this.target = target;
    }


    public void setOperation(String operation) {
        this.operation = operation;
    }


    public void setTypes(String[] types) {
        this.types = types;
    }


    public void setMessage(Object message) {
        this.message = message;
    }


    /**
     * Create a message corresponding to a command.
     * If the command is a StatusUpdate then the message body will be set to the new status.
     */
    public Message(Command command) {
        target = command.getTarget();
        operation = command.getOperation().name();
        types = new String[0];
        if (command instanceof CommandStatusUpdate) {
            message = ((CommandStatusUpdate)command).getRequestedStatus();
        }
    }
    
    /**
     * Create a message corresponding to a command with a model payload.
     */
    public Message(Command command, Model model) {
        this(command);
        message = model;
    }
    
    /**
     * Create a message corresponding to the registration of an item
     */
    public Message(Command command, RegisterItem item) {
        this(command);
        Resource itemroot = item.getRoot();
        target = itemroot.getURI();
        message = itemroot.getModel();
        Resource entity = item.getEntity();
        if (entity != null) {
            setTypes(entity);
        }
    }

    /**
     * Record the types of the created/updated entity.
     */
    public void setTypes(Resource entity) {
        List<RDFNode> tys = entity.getModel().listObjectsOfProperty(entity, RDF.type).toList();
        types = new String[ tys.size() ];
        for (int i = 0; i < types.length; i++) {
            RDFNode ty = tys.get(i);
            if (ty.isURIResource()) {
                types[i] = ty.asResource().getURI();
            }
        }
    }

    /**
     * Return the URI of the target of the command
     */
    public String getTarget() {
        return target;
    }

    /**
     * Return the operation which triggered the message.
     */
    public String getOperation() {
        return operation;
    }

    /**
     * Test if the entity registered or updated had the given type
     */
    public boolean hasType(String type) {
        for (String t : types) {
            if (t.equals(type)) return true;
        }
        return false;
    }

    /**
     * If the message is a model then return otherwise return null.
     */
    public Model getMessageAsModel() {
        if (message instanceof Model) {
            return (Model) message;
        }
        return null;
    }

    /**
     * If the message is a String then return otherwise return null.
     */
    public String getMessageAsString() {
        if (message instanceof String) {
            return (String) message;
        }
        return null;
    }
    

}

@@ -2834,24 +2834,137 @@
      %7D%0A    %7D
+%0A%0A    public Message(Command command, String target) %7B%0A        this(command);%0A        this.target = target;%0A    %7D
 %0A    %0A    /*

ADD Message constructor for command with alternative target