Package com.nokia.dempsy.config

Source Code of com.nokia.dempsy.config.ClusterDefinition

/*
* Copyright 2012 the original author or authors.
*
* 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.nokia.dempsy.config;

import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

import com.nokia.dempsy.Adaptor;
import com.nokia.dempsy.DempsyException;
import com.nokia.dempsy.KeySource;
import com.nokia.dempsy.annotations.Evictable;
import com.nokia.dempsy.annotations.MessageHandler;
import com.nokia.dempsy.annotations.MessageProcessor;
import com.nokia.dempsy.annotations.Start;
import com.nokia.dempsy.internal.util.SafeString;

/**
* <p>A {@link ClusterDefinition} is part of an {@link ApplicationDefinition}. For a full
* description of the {@link ClusterDefinition} please see the {@link ApplicationDefinition}
* documentation.</p>
*
* <p>Note: for ease of use when configuring by hand (not using a dependency injection framework
* like Spring or Guice) all "setters" (all 'mutators' in general) return the {@link ClusterDefinition}
* itself for the purpose of chaining.</p>
*/
public class ClusterDefinition
{
   private ClusterId clusterId;
   private String clusterName;

   private Object messageProcessorPrototype;
   private Adaptor adaptor;
   private ClusterId[] destinations = {};
   private Object strategy = null;
   private Object serializer = null;
   private Object statsCollectorFactory = null;
   private Object dempsyExecutor = null;
   private Object outputExecuter = null;
   private boolean adaptorIsDaemon = false;
   private KeySource<?> keySource = null;
   private long evictionFrequency = 600;
   private TimeUnit evictionTimeUnit = TimeUnit.SECONDS;
  
   private ApplicationDefinition parent;
  
   /**
    * Create a ClusterDefinition from a cluster name. A {@link ClusterDefinition} is to be embedded in
    * an {@link ApplicationDefinition} so it only needs to cluster name and not the entire {@link ClusterId}.
    */
   public ClusterDefinition(String clusterName) { this.clusterName = clusterName; }

   /**
    * <p>Create a ClusterDefinition from a cluster name. A {@link ClusterDefinition} is to be embedded in
    * an {@link ApplicationDefinition} so it only needs to cluster name and not the entire {@link ClusterId}.</p>
    *
    * <p>This Cluster will represent an {@link Adaptor} cluster. Use this constructor from a dependency injection
    * framework supporting constructor injection.</p>
    *
    * @see #setAdaptor
    */
   public ClusterDefinition(String clusterName, Adaptor adaptor) { this.clusterName = clusterName; setAdaptor(adaptor); }

   /**
    * <p>Create a ClusterDefinition from a cluster name. A {@link ClusterDefinition} is to be embedded in
    * an {@link ApplicationDefinition} so it only needs to cluster name and not the entire {@link ClusterId}.</p>
    *
    * <p>This Cluster will represent a {@link MessageProcessor} cluster. Use this constructor from a dependency injection
    * framework supporting constructor injection.</p>
    *
    * @see #setMessageProcessorPrototype
    */
   public ClusterDefinition(String clusterName, Object prototype) throws DempsyException
   {
      this.clusterName = clusterName;
      setMessageProcessorPrototype(prototype);
   }

   /**
    * Get the full clusterId of this cluster.
    */
   public ClusterId getClusterId() { return clusterId; }
  
   /**
    * If this {@link ClusterDefinition} identifies specific destination for outgoing
    * messages, this will return the list of ids of those destination clusters.
    */
   public ClusterId[] getDestinations() { return destinations; }
  
   /**
    * Set the list of explicit destination that outgoing messages should be limited to.
    */
   public ClusterDefinition setDestinations(ClusterId... destinations)
   {
      this.destinations = destinations;
      return this;
   }
  
   /**
    * Returns true if there are any explicitly defined destinations.
    * @see #setDestinations
    */
   public boolean hasExplicitDestinations() { return this.destinations != null && this.destinations.length > 0; }
  
   public ClusterDefinition setRoutingStrategy(Object strategy) { this.strategy = strategy; return this; }
   public Object getRoutingStrategy() { return strategy == null ? parent.getRoutingStrategy() : strategy; }
  
   /**
    * returns OutputExecuter
    * @return OutputExecuter
    */
   public Object getOutputExecuter() {
      return outputExecuter;
   }
  
   /**
    * returns ClusterDefinition
    * @param output
    * @return
    */
   public ClusterDefinition setOutputExecuter(Object outputExecuter) {
      this.outputExecuter = outputExecuter;
      return this;
   }

   protected ClusterDefinition setParentApplicationDefinition(ApplicationDefinition applicationDef) throws DempsyException
   {
      if (clusterName == null)
         throw new DempsyException("You must set the 'clusterName' when configuring a dempsy cluster for the application: " + String.valueOf(applicationDef));
      clusterId = new ClusterId(applicationDef.getApplicationName(),clusterName);
      parent = applicationDef;
      return this;
   }
  
   public ApplicationDefinition getParentApplicationDefinition() { return parent; }
  
   public Object getSerializer() { return serializer == null ? parent.getSerializer() : serializer; }
   public ClusterDefinition setSerializer(Object serializer) { this.serializer = serializer; return this; }

   public Object getStatsCollectorFactory() {return statsCollectorFactory == null ? parent.getStatsCollectorFactory() : statsCollectorFactory;}
   public ClusterDefinition setStatsCollectorFactory(Object statsCollectorFactory)
   {
      this.statsCollectorFactory = statsCollectorFactory;
      return this;
   }
  
   public Object getExecutor() { return dempsyExecutor == null ? parent.getExecutor() : dempsyExecutor; }
   public ClusterDefinition setExecutor(Object dempsyExecutor)
   {
      this.dempsyExecutor = dempsyExecutor;
      return this;
   }
  
   public ClusterDefinition setMessageProcessorPrototype(Object messageProcessor) throws DempsyException
   {
      this.messageProcessorPrototype = messageProcessor;
      return this;
   }
   public Object getMessageProcessorPrototype() { return messageProcessorPrototype; }
  
   public boolean isRouteAdaptorType(){ return (this.getAdaptor() != null); }
   public Adaptor getAdaptor() { return adaptor; }
   public ClusterDefinition setAdaptor(Adaptor adaptor) { this.adaptor = adaptor; return this; }
   public boolean isAdaptorDaemon() { return adaptorIsDaemon; }
   public ClusterDefinition setAdaptorDaemon(boolean isAdaptorDaemon) { this.adaptorIsDaemon = isAdaptorDaemon; return this; }
   public KeySource<?> getKeySource(){ return keySource; }
   public ClusterDefinition setKeySource(KeySource<?> keySource){ this.keySource = keySource; return this; }

  public long getEvictionFrequency() {
    return evictionFrequency;
  }

  public ClusterDefinition setEvictionFrequency(long evictionFrequency) {
    this.evictionFrequency = evictionFrequency; return this;
  }
 
  public TimeUnit getEvictionTimeUnit() {
    return evictionTimeUnit;
  }

  public ClusterDefinition setEvictionTimeUnit(TimeUnit timeUnit) {
    this.evictionTimeUnit = timeUnit; return this;
  }
  
   @Override
   public String toString()
   {
      StringBuilder sb = new StringBuilder("(");
      sb.append(clusterId == null ? "(unknown cluster id)" : String.valueOf(clusterId));
      Object obj = messageProcessorPrototype == null ? adaptor : messageProcessorPrototype;
      boolean hasBoth = adaptor != null && messageProcessorPrototype != null;
      sb.append(":").append(obj == null ? "(ERROR: no processor or adaptor)" : obj.getClass().getSimpleName());
      if (hasBoth) // if validate has been called then this can't be true
         sb.append(",").append(adaptor.getClass().getSimpleName()).append("<-ERROR");
      if (hasExplicitDestinations())
         sb.append("|destinations:").append(String.valueOf(destinations));
      sb.append(")");
      return sb.toString();
   }
  
   public void validate() throws DempsyException
   {
      if (parent == null)
         throw new DempsyException("The parent ApplicationDefinition isn't set for the Cluster " +
               SafeString.valueOf(clusterName) + ". You need to initialize the parent ApplicationDefinition prior to validating");
      if (clusterName == null)
         throw new DempsyException("You must set the 'clusterName' when configuring a dempsy cluster for the application.");
      if (messageProcessorPrototype == null && adaptor == null)
         throw new DempsyException("A dempsy cluster must contain either an 'adaptor' or a message processor prototype. " +
               clusterId + " doesn't appear to be configure with either.");
      if (messageProcessorPrototype != null && adaptor != null)
         throw new DempsyException("A dempsy cluster must contain either an 'adaptor' or a message processor prototype but not both. " +
               clusterId + " appears to be configured with both.");

     
      if (messageProcessorPrototype != null)
      {
         if(!messageProcessorPrototype.getClass().isAnnotationPresent(MessageProcessor.class))
            throw new DempsyException("Attempting to set an instance of \"" +
                  SafeString.valueOfClass(messageProcessorPrototype) + "\" within the " +
                  ClusterDefinition.class.getSimpleName() + " for \"" + SafeString.valueOf(clusterId) +
                  "\" but it isn't identified as a MessageProcessor. Please annotate the class.");

         Method[] methods = messageProcessorPrototype.getClass().getMethods();
        
         boolean foundAtLeastOneMethod = false;
         for(Method method: methods)
         {
            if(method.isAnnotationPresent(MessageHandler.class))
            {
               foundAtLeastOneMethod = true;
               break;
            }
         }
        
         if (!foundAtLeastOneMethod)
            throw new DempsyException("No method on the message processor of type \"" +
                  SafeString.valueOfClass(messageProcessorPrototype) + "\" is identified as a MessageHandler. Please annotate the appropriate method using @MessageHandler.");

         int startMethods = 0;
         for(Method method: methods)
         {
            if (method.isAnnotationPresent(Start.class))
            {
               startMethods++;
            }
         }
         if (startMethods > 1)
            throw new DempsyException("Multiple methods on the message processor of type\""
                  + SafeString.valueOf(messageProcessorPrototype) + "\" is identified as a Start method. Please annotate at most one method using @Start.");
     
         Method[] evictableMethods = messageProcessorPrototype.getClass().getMethods();
        
         boolean foundEvictableMethod = false;
         Method evictableMethod = null;
         for(Method method: evictableMethods)
         {
            if(method.isAnnotationPresent(Evictable.class))
            {
               if(foundEvictableMethod)
               {
                  throw new DempsyException("More than one method on the message processor of type \"" +
                        SafeString.valueOfClass(messageProcessorPrototype) + "\" is identified as a Evictable. Please annotate the appropriate method using @Evictable.");
               }
               foundEvictableMethod = true;
               evictableMethod = method;
            }
         }
         if(evictableMethod != null)
         {
            if(evictableMethod.getReturnType() == null || !evictableMethod.getReturnType().isAssignableFrom(boolean.class))
               throw new DempsyException("Evictable method \""+ SafeString.valueOf(evictableMethod) + "\" on the message processor of type \"" +
                     SafeString.valueOfClass(messageProcessorPrototype) + "\" should return boolean value. Please annotate the appropriate method using @Evictable.");
         }
      }
      if(adaptor != null && keySource != null)
      {
         throw new DempsyException("A dempsy cluster can not pre-instantation an adaptor.");
      }
   }
}
TOP

Related Classes of com.nokia.dempsy.config.ClusterDefinition

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.