Package nexj.core.meta.integration

Source Code of nexj.core.meta.integration.Channel

// Copyright 2010 NexJ Systems Inc. This software is licensed under the terms of the Eclipse Public License 1.0
package nexj.core.meta.integration;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.resource.NotSupportedException;
import javax.resource.ResourceException;

import nexj.core.meta.Component;
import nexj.core.meta.MetadataException;
import nexj.core.meta.MetadataLookupException;
import nexj.core.meta.NamedMetadataObject;
import nexj.core.meta.integration.service.Binding;
import nexj.core.meta.integration.service.Interface;
import nexj.core.meta.integration.service.Service;
import nexj.core.util.HashTab;
import nexj.core.util.Lookup;

/**
* Communication channel metadata.
* A communication channel has a client adapter for sending
* outgoing messages, implementing the Sender interface,
* and a server adapter receiving incoming messages and
* optionally invoking a service implementation.
*/
public abstract class Channel extends NamedMetadataObject
{
   // constants
  
   /**
    * Multiple services declaring the same message in the interface are not supported.
    */
   public final static byte COMBINE_NONE = 0;
  
   /**
    * Only the first one among the services with a duplicate message is invoked.
    */
   public final static byte COMBINE_FIRST = 1;
  
   /**
    * All the services with a duplicate message are invoked.
    */
   public final static byte COMBINE_ALL = 2;
  
   // attributes

   /**
    * The sendable flag.
    */
   protected boolean m_bSendable;

   /**
    * The receivable flag.
    */
   protected boolean m_bReceivable;

   /**
    * The duplicate message combination mode, one of the COMBINE_* constants.
    */
   protected byte m_nCombinationMode;

   // associations

   /**
    * The channel type.
    */
   protected ChannelType m_type;

   /**
    * The sender adapter component.
    */
   protected Component m_sender;

   /**
    * The receiver adapter component.
    */
   protected Component m_receiver;

   /**
    * The message table.
    */
   protected MessageTable m_messageTable;
  
   /**
    * The message to service list map: List[Message].
    */
   protected Lookup m_messageMap;

   /**
    * The service binding collection.
    */
   protected List m_bindingList = new ArrayList(2); // of type Binding

   // constructors
  
   /**
    * Constructs the channel.
    * @param sName The channel name.
    */
   public Channel(String sName)
   {
      super(sName);
   }

   // operations
  
   /**
    * Sets the channel type.
    * @param type The channel type to set.
    */
   public void setType(ChannelType type)
   {
      verifyNotReadOnly();
      m_type = type;
   }

   /**
    * @return The channel type.
    */
   public ChannelType getType()
   {
      return m_type;
   }

   /**
    * @return True if the channel can participate in distributed transactions.
    */
   public abstract boolean isTransactional();
  
   /**
    * @return True if the channel is synchronous,
    * i.e. if send-receive can be done within the same transaction.
    */
   public abstract boolean isSynchronous();
  
   /**
    * Sets the sendable flag.
    * @param bSendable The sendable flag to set.
    */
   public void setSendable(boolean bSendable)
   {
      verifyNotReadOnly();
      m_bSendable = bSendable;
   }

   /**
    * @return The sendable flag.
    */
   public boolean isSendable()
   {
      return m_bSendable;
   }
  
   /**
    * Sets the receivable flag.
    * @param bReceivable The receivable flag to set.
    */
   public void setReceivable(boolean bReceivable)
   {
      verifyNotReadOnly();
      m_bReceivable = bReceivable;
   }

   /**
    * @return The receivable flag.
    */
   public boolean isReceivable()
   {
      return m_bReceivable;
   }

   /**
    * @return True if the channel is configured as a sender, a receiver or both.
    */
   public boolean isEnabled()
   {
      return m_bSendable || m_bReceivable;
   }
  
   /**
    * Sets the sender adapter component.
    * @param sender The sender adapter component to set.
    */
   public void setSender(Component sender)
   {
      verifyNotReadOnly();
      m_sender = sender;
   }

   /**
    * @return The sender adapter component.
    */
   public Component getSender()
   {
      return m_sender;
   }

   /**
    * Sets the receiver adapter component.
    * @param receiver The receiver adapter component to set.
    */
   public void setReceiver(Component receiver)
   {
      verifyNotReadOnly();
      m_receiver = receiver;
   }

   /**
    * @return The receiver adapter component.
    */
   public Component getReceiver()
   {
      return m_receiver;
   }

   /**
    * Sets the duplicate message combination mode.
    * @param nCombinationMode The duplicate message combination mode to set,
    * one of the COMBINE_* constants.
    */
   public void setCombinationMode(byte nCombinationMode)
   {
      verifyNotReadOnly();
      m_nCombinationMode = nCombinationMode;
   }

   /**
    * @return The duplicate message combination mode, one of the COMBINE_* constants.
    */
   public byte getCombinationMode()
   {
      return m_nCombinationMode;
   }
  
   /**
    * @return The message table.
    */
   public MessageTable getMessageTable()
   {
      return m_messageTable;
   }
  
   /**
    * Adds a new service binding to the channel.
    * @param binding The service binding to add.
    */
   public void addBinding(Binding binding) throws MetadataException
   {
      verifyNotReadOnly();
     
      Service service = binding.getService();
      Interface iface = service.getInterface();
     
      for (int i = m_bindingList.size() - 1; i >= 0; --i)
      {
         Binding prevbnd = (Binding)m_bindingList.get(i);
         Service prevsvc = prevbnd.getService();
        
         if (prevsvc == service && m_nCombinationMode != COMBINE_ALL)
         {
            throw new MetadataException("err.meta.integration.bindingDup",
               new Object[]{service.getFullName(), getName()});
         }

         if (i == 0)
         {
            if (prevsvc.getInterface() != null)
            {
               if (iface != null)
               {
                  if (iface.getFormat() != prevsvc.getInterface().getFormat())
                  {
                     throw new MetadataException("err.meta.integration.binding.formatMismatch",
                        new Object[]{service.getFullName(), getName()});
                  }
               }
               else if (m_nCombinationMode != COMBINE_ALL)
               {
                  throw new MetadataException("err.meta.integration.binding.genericService",
                     new Object[]{service.getFullName(), getName()});
               }
            }
            else if (iface != null || m_nCombinationMode != COMBINE_ALL)
            {
               throw new MetadataException("err.meta.integration.binding.genericService",
                  new Object[]{service.getFullName(), getName()});
            }
         }
      }

      if (iface != null)
      {
         MessageTable table = iface.getRequestTable();

         if (m_messageTable == null)
         {
            m_messageTable = new MessageTable();
            m_messageTable.setFormat(iface.getFormat());
            m_messageMap = new HashTab(table.getMessageCount());
         }

         for (int i = 0, n = table.getMessageCount(); i != n; ++i)
         {
            Message message = table.getMessage(i);
            List list = (List)m_messageMap.get(message);

            if (list == null)
            {
               list = new ArrayList(1);
               m_messageMap.put(message, list);
               list.add(binding);
            }
            else
            {
               switch (m_nCombinationMode)
               {
                  case COMBINE_NONE:
                     throw new MetadataException("err.meta.integration.binding.messageDup",
                        new Object[]{message.getName(), service.getFullName(),
                           ((Binding)list.get(0)).getService().getFullName(), getName()});
                    
                  case COMBINE_ALL:
                     list.add(binding);
                     break;
               }
            }

            if (m_messageTable.findMessage(message.getName()) == null)
            {
               m_messageTable.addMessage(message);
            }
         }
      }

      m_bindingList.add(binding);
      binding.setChannel(this);
   }

   /**
    * Gets a service binding by ordinal number.
    * @param nOrdinal The service binding ordinal number (0-based).
    * @return The service binding object.
    */
   public Binding getBinding(int nOrdinal)
   {
      return (Binding)m_bindingList.get(nOrdinal);
   }

   /**
    * @return The service binding count.
    */
   public int getBindingCount()
   {
      return m_bindingList.size();
   }

   /**
    * @return An iterator for the contained service binding objects.
    */
   public Iterator getBindingIterator()
   {
      return m_bindingList.iterator();
   }
  
   /**
    * Gets a service binding iterator for a given message.
    * @param message The message.
    * @return The service binding iterator.
    * @throws MetadataLookupException if no service bindings are available for this message.
    */
   public Iterator getBindingIterator(Message message) throws MetadataLookupException
   {
      if (m_messageMap != null)
      {
         List list = (List)m_messageMap.get(message);
        
         if (list != null)
         {
            return list.iterator();
         }
      }

      throw new MetadataLookupException("err.meta.integration.bindingLookup",
         message.getName(), getName());
   }

   /**
    * @param channel A channel whose attributes will be copied over to this channel.
    * @throws ResourceException if the associated consumer pool fails to startup again
    *    or the operation is not supported.
    */
   public void update(Channel channel) throws ResourceException
   {
      throw new NotSupportedException();
   }

   /**
    * @see nexj.core.meta.MetadataObject#makeReadOnly()
    */
   public void makeReadOnly()
   {
      super.makeReadOnly();

      if (m_messageTable != null)
      {
         m_messageTable.makeReadOnly();
      }

      ((ArrayList)m_bindingList).trimToSize();

      for (int i = m_bindingList.size() - 1; i >= 0; i--)
      {
         ((Binding)m_bindingList.get(i)).makeReadOnly();
      }
   }
}
TOP

Related Classes of nexj.core.meta.integration.Channel

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.