/*********************************************************************************
* TotalCross Software Development Kit *
* Copyright (C) 2003 Fabian Kroeher *
* Copyright (C) 2003-2012 SuperWaba Ltda. *
* All Rights Reserved *
* *
* This library and virtual machine 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. *
* *
* This file is covered by the GNU LESSER GENERAL PUBLIC LICENSE VERSION 3.0 *
* A copy of this license is located in file license.txt at the root of this *
* SDK or can be downloaded here: *
* http://www.gnu.org/licenses/lgpl-3.0.txt *
* *
*********************************************************************************/
package totalcross.pim.ce.builtin;
import totalcross.util.*;
/**
* superclass of all the classes that represent data structures on the PocketPC device
* @author Fabian Kroeher
*
*/
public abstract class IObject
{
private Hashtable fields;
private int capacity;
/**
* creates a new IObject
* @param capacity of the Hashtable where the fields are stored
* @param nativeString the String which has been obtained from the native lib call
*/
protected IObject(int capacity, StringExt nativeString)
{
fields = new Hashtable(capacity);
this.capacity = capacity;
parseNativeString(nativeString);
}
/**
* this method reads out the nativeString until it reaches the next dataset Separator (defined in Constant);
* please note that the part that has been read out is deleted from the nativeString (thus, by calling this
* method the nativeString gets shorter and shorter every time)
* @param nativeString the StringExt to parse
*/
protected void parseNativeString(StringExt nativeString)
{
int fieldCounter = 0;
// go through the native String an extract the values
StringBuffer tmp = new StringBuffer("");
whileLoop:
while (nativeString.length() > 0)
{
// check if there is a separator next
if (nativeString.startsWith(Constant.d1Sep))
{
//System.out.println("found d1Sep, tmp is " + tmp);
// found a separator - create new Field, flush tmp and delete the separator from the native String
setValue(field(fieldCounter++), tmp.toString());
tmp.setLength(0);
nativeString.delete(0, Constant.d1Sep.length());
}
else
if (nativeString.startsWith(Constant.datasetSep))
{
//System.out.println("found dataset sep, tmp is " + tmp);
// found a dataset Separator, delete it from the String and break the loop
setValue(field(fieldCounter++), tmp.toString());
nativeString.delete(0, Constant.datasetSep.length());
break whileLoop;
}
else
{
// nothing special, take the first char from the native String and append it to tmp
tmp.append(nativeString.charAt(0));
nativeString.delete(0, 1);
}
}
if (tmp.length() > 0) // guich: if still has data, add it (case of the id returned by newTask, which has no separators)
setValue(field(fieldCounter++), tmp.toString());
}
/**
* resets all the fields of the IObject except for the id
*/
public void reset()
{
// get the id and the key under which id is saved
Hashtable newFields = new Hashtable(capacity);
String idKey = field(0);
String idVal = getValue(idKey);
newFields.put(idKey, idVal);
// overwrite fields with the new, empty (except for the id) Hashtable
fields = newFields;
}
/**
* gets the value which is stored under field name from the internal Hashtable fields
* @param fieldName the field name
* @return the value of the fieldname, null if field name is not found
*/
private Object get(String fieldName)
{
return fields.get(fieldName);
}
/**
* returns the value which is stored under field name from the internal Hashtable fields as a String,
* no matter which datatype the value has.
* @param fieldName the field name
* @return the value of the field name, "" if the field is not found
*/
public String getValue(String fieldName)
{
String retVal = null;
if (fieldName.startsWith("(String)"))
retVal = this.getString(fieldName);
else
{
Object o=null;
if (fieldName.startsWith("(IDate)"))
o = this.getIDate(fieldName);
else
if (fieldName.startsWith("(IRecipients)"))
o = this.getIRecipients(fieldName);
else
if (fieldName.startsWith("(IRecurrencePattern)"))
o = this.getIRecurrencePattern(fieldName);
if (o != null)
retVal = o.toString();
}
if (retVal == null) retVal = "";
return retVal;
}
/**
* returns the value of a given field name as a String, ClassCast Exceptions are catched
* @param fieldName the field name
* @return the value as a String, null if field is not found or ClassCast Exception occurs
*/
protected String getString(String fieldName)
{
String retVal = null;
try
{
retVal = (String)get(fieldName);
}
catch(ClassCastException cce)
{
}
return retVal;
}
/**
* returns the value of a given field name as a String, ClassCast Exceptions are catched
* @param fieldName the field name
* @return the value as a IDate, null if field is not found or ClassCast Exception occurs
*/
protected IDate getIDate(String fieldName)
{
IDate retVal = null;
try
{
retVal = (IDate)get(fieldName);
}
catch(ClassCastException cce)
{
}
return retVal;
}
/**
* returns the value of a given field name as a String, ClassCast Exceptions are catched
* @param fieldName the field name
* @return the value as a IRecipients, null if field is not found or ClassCast Exception occurs
*/
public IRecipients getIRecipients(String fieldName)
{
IRecipients retVal = null;
try
{
retVal = (IRecipients)get(fieldName);
}
catch(ClassCastException cce)
{
}
return retVal;
}
/**
* returns the value of a given field name as a String, ClassCast Exceptions are catched
* @param fieldName the field name
* @return the value as a IRecurrencePattern, null if field is not found or ClassCast Exception occurs
*/
public IRecurrencePattern getIRecurrencePattern(String fieldName)
{
IRecurrencePattern retVal = null;
try
{
retVal = (IRecurrencePattern)get(fieldName);
}
catch(ClassCastException cce)
{
}
return retVal;
}
/**
* sets a field with name key to the value value; Objects according to their given data type #
* (within the key) will be created when necessary
* @param key the field name
* @param value the value as String representation
*/
public void setValue(String key, String value)
{
if (key.startsWith("(String)"))
fields.put(key, value);
else
if (key.startsWith("(IDate)"))
fields.put(key, new IDate(value));
else
if (key.startsWith("(IRecipients)"))
fields.put(key, new IRecipients(value));
else
if (key.startsWith("(IRecurrencePattern)"))
fields.put(key, new IRecurrencePattern(value));
}
/**
* refreshes the data fields of the IObject from the PPC device
* this method has to be implemented according to the
* native library call that matches his datatype
*/
abstract public void refresh();
/**
* saves the data fields of the IObject to the PPC device
* this method has to be implemented according to the
* native library call that matches his datatype
*/
abstract public void save();
/**
* deletes this IObject on the PPC device
* this method has to be implemented according to the
* native library call that matches his datatype
*/
abstract public void delete();
/**
* this method must return the
* field name (from the corresponding i*Field Vectors of class Constant) of the given position
* @param position of the fieldname
* @return the name of the field
*/
abstract public String field(int position);
/**
* this method must return the
* size of the corresponding i*Field Vector of the class Constant
* @return the size of the fields
*/
abstract public int fields();
/**
* provides a simple String representation of this IObject mainly for debugging purposes
* @return a String representation of this object
*/
public String toString()
{
int n = fields();
StringBuffer retVal = new StringBuffer(n*10);
for (int i = 0; i < n; i++)
{
String f = field(i);
retVal.append(f).append(':').append(getString(f)).append('\n');
}
return retVal.toString();
}
}