/*
* BeanCruncher.java
* Copyright (c) 2005 by University of Hamburg. All Rights Reserved.
* Departament of Informatics.
* Distributed Systems and Information Systems.
*
* Created by walczak on Dec 2, 2005.
* Last revision $Revision: 4252 $ by:
* $Author: walczak $ on $Date: 2006-05-30 11:05:06 +0200 (Di, 30 Mai 2006) $.
*/
package nuggets;
import java.util.HashMap;
import java.util.Map;
import nuggets.util.IdHashMap;
/**
* BeanCruncher - transforms beans into parts and attributes. To be used on one
* communication line. Uses references to minimize the number of items send over
* the wire or to disk.
*/
public class BeanCruncher implements ICruncher
{
private IWriter codec;
/** the default package */
private String ontology;
final private IdHashMap ids = new IdHashMap();
private Map idstodo = new HashMap();
static final int MAX_VALUE_LENGTH = 256;
/**
* Constructor for BeanCruncher.
*
* @param codec
*/
public BeanCruncher(IWriter codec)
{
this.codec = codec;
}
// ----------- ICruncher interface ----------
/**
* @param obj
* @return the id of this object or 0
*/
public int declare(Object obj, ClassLoader classloader)
{
if(obj != null)
return persist_recursive(obj, classloader);
return 0;
}
/**
* @param attr
* @param id
* @see nuggets.ICruncher#put(java.lang.String, int)
*/
public void put(String attr, int id)
{
codec.putRef(attr, Integer.toHexString(id));
}
/**
* @param value
* @see nuggets.ICruncher#add(Object)
*/
public void add(Object value)
{
codec.addToken(Integer.toHexString(getID(value)));
}
/**
* @param attr
* @param value
* @see nuggets.ICruncher#put(java.lang.String, java.lang.String)
*/
public void put(String attr, String value)
{
if(value == null)
{
codec.put(attr, "0");
}
else if(value.length() > MAX_VALUE_LENGTH)
{
put(attr, getID(value));
// codec.put(attr, Integer.toHexString(getID(value)));
}
else
{
codec.put(attr, value);
}
}
/**
* @param value
* @see nuggets.ICruncher#addToken(java.lang.String)
*/
public void addToken(String value)
{
codec.addToken(value);
}
/**
* @param ba
* @see nuggets.ICruncher#setData(byte[])
*/
public void setData(byte[] ba)
{
codec.write(ba);
}
/**
* @param text
* @see nuggets.ICruncher#setText(java.lang.String)
*/
public void setText(String text)
{
codec.write(text);
}
/**
* @param chars
* @param start
* @param len
* @see nuggets.ICruncher#setText(java.lang.String)
*/
public void setText(char[] chars, int start, int len)
{
codec.write(chars, start, len);
}
// -----------------------------------------
/**
* Root marshall call point
*
* @param root
*/
public void persist(Object root, ClassLoader classloader)
{
clear();
if (root!=null) setOntology(root.getClass());
codec.start(ontology);
persist_recursive(root, classloader);
Object[] todo = idstodo.keySet().toArray();
for(int i=0; i<todo.length; i++)
{
int key = ((Integer)idstodo.get(todo[i])).intValue();
persist_recursive(key, todo[i], classloader);
}
codec.end();
}
/**
* This clears the object ids an the scrap
*/
public void clear()
{
ontology=null;
ids.clear();
idstodo.clear();
seq = 1;
}
/**
* @param o
* @return the id of this object
*/
protected int persist_recursive(Object o, ClassLoader classloader)
{
int id=ids.get(o);
if(id==0)
{
ids.put(o, id=seq++);
idstodo.remove(o);
Class clazz = o.getClass();
// find delegate
IDelegate m = PersistenceHelper.getDelegate(clazz, classloader);
try
{
m.persist(o, this, classloader);
codec.end(getTag(clazz));
}
catch(Exception e)
{
throw new PersistenceException(e);
}
}
return id;
}
/**
* @param o
* @return the id of this object
*/
protected void persist_recursive(int id, Object o, ClassLoader classloader)
{
ids.put(o, id);
idstodo.remove(o);
Class clazz = o.getClass();
// find delegate
IDelegate m = PersistenceHelper.getDelegate(clazz, classloader);
try
{
m.persist(o, this, classloader);
codec.end(getTag(clazz));
}
catch(Exception e)
{
throw new PersistenceException(e);
}
}
/**
* @param o
*/
public void startConcept(Object o)
{
codec.start(getTag(o.getClass()), Integer.toHexString(getID(o)));
}
/**
* @param clazz
* @return the tag for this class
*/
protected String getTag(Class clazz)
{
if(clazz.isArray()) return "array";
String cn = clazz.getName();
if(cn.startsWith(ontology + '.')) return cn.substring(ontology.length() + 1);
return cn;
}
/** <code>seq</code>: */
protected int seq;
/**
* @param o
* @return the id for this object
*/
protected int getID(Object o)
{
if(o == null) return 0;
int id = ids.get(o);
if(id == 0)
{
id = seq++;
// ids.put(o, id = seq++);
idstodo.put(o, new Integer(id));
}
return id;
}
/**
* @param clazz
*/
private void setOntology(Class clazz)
{
if (clazz.isPrimitive() || clazz.isArray()) return;
String clazz_name=clazz.getName();
String tpck="";
int i=clazz_name.lastIndexOf('.');
if (i>0) {
tpck=clazz_name.substring(0, i);
}
if (ontology == null || ontology.length()>tpck.length()) {
ontology=tpck;
}
}
}