/* * This program 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 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Array.java * Copyright (C) 2009 University of Waikato, Hamilton, New Zealand * */ package weka.core.pmml; import org.w3c.dom.Element; import java.io.Serializable; import java.io.StreamTokenizer; import java.io.StringReader; import java.util.ArrayList; /** * Class for encapsulating a PMML Array element. * * @author Mark Hall (mhall{[at]}pentaho{[dot]}com) * @version $Revision: 5563 $ */ public class Array implements Serializable { /** * Utility method to check if an XML element is an array. * * @param arrayE the XML element to check * @return returns true if the XML element is an array */ public static boolean isArray(Element arrayE) { String name = arrayE.getTagName(); if (name.equals("Array") || name.equals("NUM-ARRAY") || name.equals("INT-ARRAY") || name.equals("REAL-ARRAY") || name.equals("STRING-ARRAY") || isSparseArray(arrayE)) { return true; } return false; } /** * Utility method to check if an XML element is a sparse array. * * @param arrayE the XML element to check. * @return true if the XML element is a sparse array. */ private static boolean isSparseArray(Element arrayE) { String name = arrayE.getTagName(); if (name.equals("INT-SparseArray") || name.equals("REAL-SparseArray")) { return true; } return false; } /** * Static factory method for creating non-sparse or sparse * array types as needed. * * @param arrayE the XML element encapsulating the array * @return an appropriate Array type * @throws Exception if there is a problem when constructing the array */ public static Array create(Element arrayE) throws Exception { if (!isArray(arrayE)) { throw new Exception("[Array] the supplied element does not contain an array!"); } if (isSparseArray(arrayE)) { // TODO: implement sparse array subclass :-) } return new Array(arrayE); } public static enum ArrayType { NUM("NUM-ARRAY"), INT("INT-ARRAY"), REAL("REAL-ARRAY"), STRING("STRING-ARRAY"); private final String m_stringVal; ArrayType(String name) { m_stringVal = name; } public String toString() { return m_stringVal; } } /** The values of the array */ protected ArrayList<String> m_values = new ArrayList<String>(); /** The type of the array */ protected ArrayType m_type = ArrayType.NUM; protected Array(Element arrayE) throws Exception { String arrayS = arrayE.getTagName(); // get the type of the array if (arrayS.equals("Array")) { String type = arrayE.getAttribute("type"); if (type.equals("int")) { m_type = ArrayType.INT; } else if (type.equals("real")) { m_type = ArrayType.REAL; } else if (type.equals("string")) { m_type = ArrayType.STRING; } } else { for (ArrayType a : ArrayType.values()) { if (a.toString().equals(arrayS)) { m_type = a; break; } } } // now read the values String contents = arrayE.getChildNodes().item(0).getNodeValue(); StringReader sr = new StringReader(contents); StreamTokenizer st = new StreamTokenizer(sr); st.resetSyntax(); st.whitespaceChars(0, ' '); st.wordChars(' '+1,'\u00FF'); st.whitespaceChars(' ',' '); st.quoteChar('"'); st.quoteChar('\''); //m_Tokenizer.eolIsSignificant(true); st.nextToken(); while (st.ttype != StreamTokenizer.TT_EOF && st.ttype != StreamTokenizer.TT_EOL) { m_values.add(st.sval); st.nextToken(); } } /** * Get the type of this array. * * @return the type of the array. */ public ArrayType getType() { return m_type; } /** * Is this array a SparseArray? * * @return true if this array is sparse. */ public boolean isSparse() { return false; } /** * Get the number of values in this array. * * @return the number of values in this array. */ public int numValues() { return m_values.size(); } /** * Returns true if the array contains this string value. * * @param value the value to check for. * @return true if the array contains this string value */ public boolean contains(String value) { return m_values.contains(value); } /** * Returns true if the array contains this integer value. * * @param value the value to check for * @return true if the array contains this integer value */ public boolean contains(int value) { return contains(new Integer(value).toString()); } /** * Returns true if the array contains this real value. * * @param value the value to check for * @return true if the array contains this real value */ public boolean contains(double value) { return contains(new Double(value).toString()); } /** * Returns true if the array contains this real value. * * @param value the value to check for * @return true if the array contains this real value */ public boolean contains(float value) { return contains(new Float(value).toString()); } private void checkInRange(int index) throws Exception { if (index >= m_values.size() || index < 0) { throw new IllegalArgumentException("[Array] index out of range " + index); } } /** * Gets the value at index from the array. * * @param index the index of the value to get. * @return the value at index in the array as as String. * @throws Exception if index is out of bounds. */ public String value(int index) throws Exception { checkInRange(index); return m_values.get(index); } /** * Gets the value at index from the array as a String. Calls * value(). * * @param index the index of the value to get. * @return the value at index in the array as a String. * @throws Exception if index is out of bounds. */ public String valueString(int index) throws Exception { return value(index); } /** * Gets the value at index from the array as a double. * * @param index the index of the value to get. * @return the value at index in the array as a double. * @throws Exception if index is out of bounds. */ public double valueDouble(int index) throws Exception { if (m_type == ArrayType.STRING) { throw new Exception("[Array] Array does not contain numbers!"); } return Double.parseDouble(value(index)); } /** * Gets the value at index from the array as a float. * * @param index the index of the value to get. * @return the value at index in the array as a float. * @throws Exception if index is out of bounds. */ public float valueFloat(int index) throws Exception { if (m_type == ArrayType.STRING) { throw new Exception("[Array] Array does not contain numbers!"); } return Float.parseFloat(value(index)); } /** * Gets the value at index from the array as an int. * * @param index the index of the value to get. * @return the value at index in the array as an int. * @throws Exception if index is out of bounds. */ public int valueInt(int index) throws Exception { if (m_type == ArrayType.INT) { throw new Exception("[Array] Array does not contain integers!"); } return Integer.parseInt(value(index)); } /** * Gets the value at indexOfIndex from the array. Does the * same as value() if this array is not sparse. * * @param indexOfIndex the index of the index of the value to get. * @return a value from the array as a String. * @throws Exception if indexOfIndex is out of bounds. */ public String valueSparse(int indexOfIndex) throws Exception { return value(indexOfIndex); } /** * Gets the value at indexOfIndex from the array. Does the * same as value() if this array is not sparse. * * @param indexOfIndex the index of the index of the value to get. * @return a value from the array as a String. * @throws Exception if indexOfIndex is out of bounds. */ public String valueSparseString(int indexOfIndex) throws Exception { return valueSparse(indexOfIndex); } /** * Gets the value at indexOfIndex from the array. Does the * same as value() if this array is not sparse. * * @param indexOfIndex the index of the index of the value to get. * @return a value from the array as a double. * @throws Exception if indexOfIndex is out of bounds. */ public double valueSparseDouble(int indexOfIndex) throws Exception { return valueDouble(indexOfIndex); } /** * Gets the value at indexOfIndex from the array. Does the * same as value() if this array is not sparse. * * @param indexOfIndex the index of the index of the value to get. * @return a value from the array as a float. * @throws Exception if indexOfIndex is out of bounds. */ public float valueSparseFloat(int indexOfIndex) throws Exception { return valueFloat(indexOfIndex); } /** * Gets the value at indexOfIndex from the array. Does the * same as value() if this array is not sparse. * * @param indexOfIndex the index of the index of the value to get. * @return a value from the array as an int. * @throws Exception if indexOfIndex is out of bounds. */ public int valueSparseInt(int indexOfIndex) throws Exception { return valueInt(indexOfIndex); } public String toString() { StringBuffer text = new StringBuffer(); text.append("["); for (int i = 0; i < m_values.size(); i++) { text.append(m_values.get(i)); if (i < m_values.size() - 1) { text.append(","); } } text.append("]"); return text.toString(); } }