// $Id: StructureData.java,v 1.8 2004/11/07 03:00:48 caron Exp $
/*
 * Copyright 1997-2004 Unidata Program Center/University Corporation for
 * Atmospheric Research, P.O. Box 3000, Boulder, CO 80307,
 * support@unidata.ucar.edu.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at
 * your option) any later version.
 *
 * This library 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 Lesser
 * General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, strlenwrite to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */
package ucar.nc2;

import ucar.ma2.*;
import java.util.*;

/**
 * A container for a Structure's data. Analogous to an Array for a Variable.
 */

public class StructureData {
  protected Structure structure;
  protected ArrayList members = new ArrayList(); // Members

  /**
   * Constructor.
   * @param structure data is for this structure.
   */
  public StructureData(Structure structure) {
    this.structure = structure;
  }

  /**
   * Add a member Variable and its Array.
   * @param v member variable
   * @param arr data aray
   */
  public void addMember( Variable v, Array arr) {
    members.add( new Member( v, arr));
  }

  /**
   * Get the Structure the data is for.
   */
  public Structure getStructure() { return structure; }

  /**
   * Get the name; matches the Structure it is for.
   */
  public String	getName() { return structure.getName(); }

  /**
   * Get the list of members as StructureData.Member objects.
   * @return List of StructureData.Member
   */
  public java.util.List getMembers() { return members; }


  /** Get the names of the member variable contained directly in this Structure.
   * @return List of type String.
   */
  public java.util.List getMemberNames() {
    ArrayList memberNames = new ArrayList();  // Strings
    for (int i = 0; i < members.size(); i++) {
      Member m =  (Member) members.get(i);
      memberNames.add( m.getV().getName());
    }
    return memberNames;
  }

  /** Find the member by its short name.
   * @return StructureData.Member
   */
  public Member findMember(String memberName) {
    if (memberName == null) return null;
    for (int i=0; i<members.size(); i++) {
      Member m = (Member) members.get(i);
      if (m.v.getShortName().equals(memberName))
        return m;
    }
    return null;
  }

  /**
   * Find the Array member with the specified name, or null if not found.
   */
  public Array findMemberArray(String memberName) {
    Member m = findMember(memberName);
    if (m == null) return null;
    return m.data;
  }

   /**
   * Find a member, possibly nested in multiple structures. If any arrays, take first element.
   * @param fullName eg "name1.name2.name" (note no groups).
   * @return Member or null if not found.
   */
  public Member findNestedMember( String fullName) {
    StructureData sdata = this;
    Member nested = null;
    StringTokenizer stoke = new StringTokenizer(fullName, ".");
    while (stoke.hasMoreTokens()) {
      String name = stoke.nextToken();
      nested = sdata.findMember( name);
      if (nested.v.getDataType() == DataType.STRUCTURE)
        sdata = (StructureData) nested.data.getObject( nested.data.getIndex());
    }
    return nested;
  }

  /////////////////////////////////////////////////////////////////////////////////////////////////////
  // scaler access
  private Index scalarIndex = new Index0D( new int[0]);

  /** Get byte value, from rank 0 member array.
   * @param memberName name of member Variable.
   * @throws IllegalArgumentException if name is not legal member name.
   */
  public boolean getScalarBoolean(String memberName) {
    Array data = findMemberArray(memberName);
    if (data == null) throw new IllegalArgumentException("illegal member name ="+memberName);
    return data.getBoolean(scalarIndex);
  }

  /** Get byte value, from rank 0 member array.
   * @param memberName name of member Variable.
   * @throws IllegalArgumentException if name is not legal member name.
   */
  public byte getScalarByte(String memberName) {
    Array data = findMemberArray(memberName);
    if (data == null) throw new IllegalArgumentException("illegal member name ="+memberName);
    return data.getByte(scalarIndex);
  }

  /** Get double value, from rank 0 member array.
   * @param memberName name of member Variable.
   * @throws IllegalArgumentException if name is not legal member name.
   */
  public double getScalarDouble(String memberName) {
    Array data = findMemberArray(memberName);
    if (data == null) throw new IllegalArgumentException("illegal member name ="+memberName);
    return data.getDouble(scalarIndex);
  }

  /** Get float value, from rank 0 member array.
   * @param memberName name of member Variable.
   * @throws IllegalArgumentException if name is not legal member name.
   */
  public float getScalarFloat(String memberName) {
    Array data = findMemberArray(memberName);
    if (data == null) throw new IllegalArgumentException("illegal member name ="+memberName);
    return data.getFloat(scalarIndex);
  }

  /** Get int value, from rank 0 member array.
   * @param memberName name of a member Variable.
   * @throws IllegalArgumentException if name is not legal member name.
   */
  public int getScalarInt(String memberName) {
    Array data = findMemberArray(memberName);
    if (data == null) throw new IllegalArgumentException("illegal member name ="+memberName);
    return data.getInt(scalarIndex);
  }

  /** Get long value, from rank 0 member array.
   * @param memberName name of member Variable.
   * @throws IllegalArgumentException if name is not legal member name.
   */
  public long getScalarLong(String memberName) {
    Array data = findMemberArray(memberName);
    if (data == null) throw new IllegalArgumentException("illegal member name ="+memberName);
    return data.getLong(scalarIndex);
  }

  /** Get short value, from rank 0 member array.
   * @param memberName name of member Variable.
   * @throws IllegalArgumentException if name is not legal member name.
   */
  public short getScalarShort(String memberName) {
    Array data = findMemberArray(memberName);
    if (data == null) throw new IllegalArgumentException("illegal member name ="+memberName);
    return data.getShort(scalarIndex);
  }

  /** Get structureData value, from rank 0 member array.
   * @param memberName name of member Variable.
   * @throws IllegalArgumentException if name is not legal member name.
   */
  public StructureData getScalarStructure(String memberName) {
    ArrayObject.D0 a = (ArrayObject.D0) findMemberArray(memberName);
    if (a == null) throw new IllegalArgumentException("illegal member name ="+memberName);
    Object data = a.get();
    assert (data instanceof StructureData) : data.getClass().getName();
    return (StructureData) data;
  }

  /** Get String value, from rank 0 String or rank 1 char member array.
   * @param memberName name of member Variable.
   * @throws IllegalArgumentException if name is not legal member name.
   */
  public String getScalarString(String memberName) {
    Array a = findMemberArray(memberName);
    if (a == null) throw new IllegalArgumentException("illegal member name ="+memberName);
    if (a instanceof ArrayChar.D1)
      return ((ArrayChar.D1) a).getString();

    assert (a instanceof ArrayObject.D0);
    Object data = ((ArrayObject.D0)a).get();
    assert (data instanceof String) : data.getClass().getName();
    return (String) data;
  }

  /////////////////////////////////////////////////

  /**
   * Encapsolates a member variable and its data array.
   */
  static public class Member {
    private Variable v; /** pointer to the member variable */
    private Array data; /** the in-memory data array */

    protected Member() { }

    protected Member(Variable v, Array data) {
      this.v = v;
      this.data = data;
    }

    /** Get the associated Variable */
    public Variable getV() {
      return v;
    }

    /** Get the data. */
    public Array getData() {
      return data;
    }
  }

}

/* Change History:
   $Log: StructureData.java,v $
   Revision 1.8  2004/11/07 03:00:48  caron
   *** empty log message ***

   Revision 1.7  2004/10/06 19:03:44  caron
   clean up javadoc
   change useV3 -> useRecordsAsStructure
   remove id, title, from NetcdfFile constructors
   add "in memory" NetcdfFile

   Revision 1.6  2004/09/22 13:46:36  caron
   *** empty log message ***

   Revision 1.5  2004/08/26 17:55:10  caron
   no message

   Revision 1.4  2004/08/16 20:53:46  caron
   2.2 alpha (2)

   Revision 1.3  2004/07/12 23:40:18  caron
   2.2 alpha 1.0 checkin

   Revision 1.2  2004/07/06 19:28:11  caron
   pre-alpha checkin

   Revision 1.1.1.1  2003/12/04 21:05:27  caron
   checkin 2.2

 */