# RoutingKey.java

    /*
    ** Module   : RoutingKey.java
    ** Abstract : contains routing information
    **
    ** Copyright (c) 2005-2017, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- -T- --JPRM-- ----------------Description-----------------
    ** 001 SIY 20050120 ADD   @19506 Created initial version.
    ** 002 SIY 20050211 ADD   @19773 Added copy-constructor and replacement for
    **                               the standard object reading/writing methods.
    ** 003 SIY 20050315 CHG   @20390 Organized imports and other minor cleanups.
    ** 004 SIY 20050329 CHG   @20549 Fixed comments, added constant for shutdown()
    **                               entry point.
    ** 005 NVS 20050418 CHG   @20766 Added new public method getSpecial for
    **                               creating special routing keys.
    ** 006 NVS 20060210 CHG   @24509 Added another special system routing key:
    **                               INTERRUPT_SESSION.
    ** 007 GES 20060801 CHG   @28289 Converted to Externalizable to improve
    **                               efficiency because Serializable has unneeded
    **                               processing (for versioning...) that is
    **                               executed on "inflation".
    ** 008 ECF 20071112 CHG   @35888 Refactored net package. Renamed
    **                               TERMINATE_SESSION to TERMINATE_REMOTE.
    **                               Changed ID-related method names to match
    **                               coding standards.
    ** 009 ES  20240619              Added another special system routing key:
    **                               SERVER_INTERRUPT.
    */
    /*
    ** This program is free software: you can redistribute it and/or modify
    ** it under the terms of the GNU Affero General Public License as
    ** published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
    **
    ** You may find a copy of the GNU Affero GPL version 3 at the following
    ** location: https://www.gnu.org/licenses/agpl-3.0.en.html
    **
    ** Additional terms under GNU Affero GPL version 3 section 7:
    **
    **   Under Section 7 of the GNU Affero GPL version 3, the following additional
    **   terms apply to the works covered under the License.  These additional terms
    **   are non-permissive additional terms allowed under Section 7 of the GNU
    **   Affero GPL version 3 and may not be removed by you.
    **
    **   0. Attribution Requirement.
    **
    **     You must preserve all legal notices or author attributions in the covered
    **     work or Appropriate Legal Notices displayed by works containing the covered
    **     work.  You may not remove from the covered work any author or developer
    **     credit already included within the covered work.
    **
    **   1. No License To Use Trademarks.
    **
    **     This license does not grant any license or rights to use the trademarks
    **     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
    **     of Golden Code Development Corporation. You are not authorized to use the
    **     name Golden Code, FWD, or the names of any author or contributor, for
    **     publicity purposes without written authorization.
    **
    **   2. No Misrepresentation of Affiliation.
    **
    **     You may not represent yourself as Golden Code Development Corporation or FWD.
    **
    **     You may not represent yourself for publicity purposes as associated with
    **     Golden Code Development Corporation, FWD, or any author or contributor to
    **     the covered work, without written authorization.
    **
    **   3. No Misrepresentation of Source or Origin.
    **
    **     You may not represent the covered work as solely your work.  All modified
    **     versions of the covered work must be marked in a reasonable way to make it
    **     clear that the modified work is not originating from Golden Code Development
    **     Corporation or FWD.  All modified versions must contain the notices of
    **     attribution required in this license.
    */

    package com.goldencode.p2j.net;

    import java.io.*;

    /**
     * RoutingKey holds all information related message routing, both external
     * routing (source and destination node addresses) and internal routing
     * (exported entry point IDs).
     *
     * @author SIY
     */
    public final class RoutingKey
    implements Externalizable
    {
       /** getRoutingKey() special entry point */
       public static final int GET_ROUTING_KEY = -1;

       /** authenticateRemote() special entry point */
       public static final int AUTHENTICATE_REMOTE = -2;

       /** terminateRemote() special entry point */
       public static final int TERMINATE_REMOTE = -3;

       /** shutdown() special entry point */
       public static final int SHUTDOWN_PACKAGE = -4;

       /** interruptSession() special entry point */
       public static final int INTERRUPT_SESSION = -5;

       /** serverInterrupt() special entry point */
       public static final int SERVER_INTERRUPT = -6;

       /** Security context ID */
       private int contextID;

       /** Destination node address */
       private int destination;

       /** Method group ID */
       private int groupID;

       /** Method in the group ID */
       private int methodID;

       /** Source node address */
       private int source;

       /**
        * Construct a default <code>RoutingKey</code> instance. By convention it
        * points to the getRoutingKey() special entry point (exported by
        * <code>Dispatcher</code>).
        */
       public RoutingKey()
       {
          this(GET_ROUTING_KEY);
       }

       /**
        * Construct a <code>RoutingKey</code> instance for special entry point.
        *
        * @param    special
        *           This is an ID which will be assigned to groupID and methodID.
        */
       RoutingKey(int special)
       {
          this(special, special, 0, 0, 0);
       }

       /**
        * Construct an instance with specified groupID and methodID. This
        * constructor is used by <code>Dispatcher</code> for generation of valid
        * RoutingKey instances for exported entry points created by the
        * application (unlike special entry points which are created
        * artificially).
        *
        * @param    groupID
        *           Method group ID.
        * @param    methodID
        *           Method ID.
        */
       RoutingKey(int groupID, int methodID)
       {
          this(groupID, methodID, 0, 0, 0);
       }

       /**
        * Construct a key from other routing key.
        *
        * @param    other
        *           Instance which is used as a source.
        */
       RoutingKey(RoutingKey other)
       {
          if (other != null)
          {
             source      = other.source;
             destination = other.destination;
             groupID     = other.groupID;
             methodID    = other.methodID;
             contextID   = other.contextID;
          }
       }

       /**
        * Construct a complete instance. Used internally by other constructors.
        *
        * @param    group
        *           Method group ID.
        * @param    method
        *           Method ID.
        * @param    context
        *           Security context ID.
        * @param    src
        *           Source node address.
        * @param    dst
        *           Destination node address.
        */
       private RoutingKey(int group, int method, int context, int src, int dst)
       {
          source      = src;
          destination = dst;
          groupID     = group;
          methodID    = method;
          contextID   = context;
       }

       /**
        * Creates a special routing key from "system" group.
        *
        * @param    special
        *           This is an ID which will be assigned to groupID and methodID.
        *           Must be one of the following:
        *           <ul>
        *              <li>GET_ROUTING_KEY - equivalent of the default
        *                  constructor;
        *              <li>SHUTDOWN_PACKAGE
        *           </ul>
        *
        * @return   The newly created instance of RoutingKey or <code>null</code>
        *           if the parameter is invalid.
        */
       public static RoutingKey getSpecial(int special)
       {
          if (special != GET_ROUTING_KEY && special != SHUTDOWN_PACKAGE)
             return null;

          return new RoutingKey(special, special, 0, 0, 0);
       }

       /**
        * Compare two instances.
        *
        * @param    obj
        *           An object to compare with.
        *
        * @return   <code>true</code> if the two keys are identical.
        */
       public boolean equals(Object obj)
       {
          if (this == obj)
             return true;

          if (obj instanceof RoutingKey)
          {
             RoutingKey key = (RoutingKey) obj;

             if (getGroupID() != key.getGroupID())
                return false;

             if (getMethodID() != key.getMethodID())
                return false;

             return true;
          }

          return false;
       }

       /**
        * Provide access to the destination node address.
        *
        * @return   The destination node address.
        */
       public int getDestinationAddress()
       {
          return destination;
       }

       /**
        * Provide access to the source node address.
        *
        * @return   The source node address.
        */
       public int getSourceAddress()
       {
          return source;
       }

       /**
        * Generate a hash code for use by HashMap.
        *
        * @return   The hash code.
        */
       public int hashCode()
       {
          return ((groupID << 16) | methodID);
       }

       /**
        * Assign new destination node address.
        *
        * @param    dst
        *           The destination node address.
        */
       public void setDestinationAddress(int dst)
       {
          destination = dst;
       }

       /**
        * Assign new source node address.
        *
        * @param    src
        *           The source node address.
        */
       public void setSourceAddress(int src)
       {
          source = src;
       }

       /**
        * Replacement for the default object reading method. It is meant to be
        * be called by containing objects rather than by the J2SE infrastructure
        * but the standard signature and name are used.
        *
        * @param    in
        *           Input source from which fields will be restored.
        *
        * @throws   IOException
        *           In case of I/O errors.
        * @throws   ClassNotFoundException
        *           If the payload can't be instantiated.
        */
       public void readExternal(ObjectInput in)
       throws IOException,
              ClassNotFoundException
       {
          source      = in.readInt();
          destination = in.readInt();
          groupID     = in.readInt();
          methodID    = in.readInt();
          contextID   = in.readInt();
       }

       /**
        * Replacement for the default object writing method. It is meant to be
        * be called by containing objects rather than by the J2SE infrastructure
        * but the standard signature and name are used.
        *
        * @param    out
        *           The output destination to which fields will be saved.
        *
        * @throws   IOException
        *           In case of I/O errors.
        */
       public void writeExternal(ObjectOutput out)
       throws IOException
       {
          out.writeInt(source);
          out.writeInt(destination);
          out.writeInt(groupID);
          out.writeInt(methodID);
          out.writeInt(contextID);
       }

       /**
        * Provide access to the security context ID.
        *
        * @return   The security context ID.
        */
       int getContextID()
       {
          return contextID;
       }

       /**
        * Provide access to the method's group ID.
        *
        * @return   The group ID.
        */
       int getGroupID()
       {
          return groupID;
       }

       /**
        * Provide access to the method ID.
        *
        * @return   The method ID.
        */
       int getMethodID()
       {
          return methodID;
       }

       /**
        * Assign new security context ID
        *
        * @param    contextID
        *           New security context ID.
        */
       void setContextID(int contextID)
       {
          this.contextID = contextID;
       }

       /**
        * Swap source and destination addresses. Convenient method when request
        * message instance is used to prepare an reply message.
        */
       void swapAddresses()
       {
          int tmp = source;

          source = destination;
          destination = tmp;
       }
    }