/* CodeSet_sctx.java --
   Copyright (C) 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath 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, or (at your option)
any later version.

GNU Classpath 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 GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.CORBA.GIOP;

import gnu.CORBA.CDR.AbstractCdrInput;
import gnu.CORBA.CDR.AbstractCdrOutput;
import gnu.CORBA.IOR;
import java.io.IOException;

/**
 * The code set service context. This context must be included in all
 * messages that use wide characters.
 *
 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
 */
public class CodeSetServiceContext
  extends ServiceContext
{
  /**
   * The context code sets id.
   */
  public static final int ID = 1;

  /**
   * The standard component to include in the messages.
   */
  public static final CodeSetServiceContext STANDARD = new CodeSetServiceContext();

  /**
   * The encoding, used to transfer the narrow (1 byte) character data.
   * The default value is taken from {@link CharSets_OSF#NATIVE_CHARACTER}.
   */
  public int char_data = CharSets_OSF.NATIVE_CHARACTER;

  /**
   * The encoding, used to transfer the wide character data.
   * The default value is taken from
   * {@link CharSets_OSF#NATIVE_WIDE_CHARACTER}.
   */
  public int wide_char_data = CharSets_OSF.NATIVE_WIDE_CHARACTER;

  /**
   * Find and return the code set service context in the give
   * contexts array. Returns {@link #STANDARD} if no code set
   * context is present.
   *
   * @param contexts the array of contexts, can be null.
   */
  public static CodeSetServiceContext find(ServiceContext[] contexts)
  {
    if (contexts != null)
      for (int i = 0; i < contexts.length; i++)
        {
          if (contexts [ i ] instanceof CodeSetServiceContext)
            return (CodeSetServiceContext) contexts [ i ];
        }
    return STANDARD;
  }

  /**
   * Select the suitable encoding that is defined in the provided profile.
   *
   * TODO character encoding. Now the encoding can be set, but it is ignored.
   * If you take this task, scan 'TODO character encoding' for
   * relevant places.
   */
  public static CodeSetServiceContext negotiate(IOR.CodeSets_profile profile)
  {
    if (profile.negotiated != null)
      return profile.negotiated;

    CodeSetServiceContext use = new CodeSetServiceContext();

    use.char_data =
      negotiate(profile.narrow, STANDARD.char_data, CharSets_OSF.ISO8859_1);

    use.wide_char_data =
      negotiate(profile.wide, STANDARD.wide_char_data, CharSets_OSF.UTF16);

    profile.negotiated = use;

    return use;
  }

  /**
   * Read the context from the given stream. Does not read the
   * code sets id.
   */
  public void readContext(AbstractCdrInput input)
  {
    AbstractCdrInput encap = input.read_encapsulation();

    char_data = encap.read_ulong();
    wide_char_data = encap.read_ulong();
  }

  /**
   * Return a string representation.
   */
  public String toString()
  {
    return " Encoding: narrow " + name(char_data) + ", wide " +
           name(wide_char_data) + ". ";
  }

  /**
   * Write the context to the given stream, including the code
   * sets id.
   */
  public void write(AbstractCdrOutput output)
  {
    output.write_ulong(ID);

    AbstractCdrOutput enout = output.createEncapsulation();

    enout.write_long(char_data);
    enout.write_ulong(wide_char_data);

    try
      {
        enout.close();
      }
    catch (IOException ex)
      {
        InternalError t = new InternalError();
        t.initCause(ex);
        throw t;
      }
  }

  /**
   * Negotiate about the character encoding. Prefer our native encoding,
   * if no, prefer IORs native encoding, if no, find any encoding,
   * supported by both sides, if no, return the specified final decission.
   *
   * @param profile the component profile in IOR.
   * @param our_native our native encoding
   * @param final_decission the encoding that must be returned if no
   * compromise is found.
   *
   * @return the resulted encoding.
   */
  protected static int negotiate(IOR.CodeSets_profile.CodeSet_component profile,
                                 int our_native, int final_decission
                                )
  {
    // If our and IORs native sets match, use the native set.
    if (profile.native_set == our_native)
      return our_native;

    // If the native sets do not match, but the IOR says it
    // supports our native set, use our native set.
    if (profile.conversion != null)
      for (int i = 0; i < profile.conversion.length; i++)
        {
          if (our_native == profile.conversion [ i ])
            return our_native;
        }

    // At this point, we suggest to use the IORs native set.
    int[] allSupported = CharSets_OSF.getSupportedCharSets();

    for (int s = 0; s < allSupported.length; s++)
      if (allSupported [ s ] == profile.native_set)
        return profile.native_set;

    // Any compromise left?
    if (profile.conversion != null)
      for (int s = 0; s < allSupported.length; s++)
        for (int i = 0; i < profile.conversion.length; i++)
          if (allSupported [ s ] == profile.conversion [ i ])
            return allSupported [ s ];

    // Return the CORBA default char encoding.
    return final_decission;
  }

  /**
   * Conveniency method, used in toString()
   */
  private String name(int set)
  {
    return "0x" + Integer.toHexString(set) + " (" + CharSets_OSF.getName(set) +
           ") ";
  }
}
