All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.anotheria.anodoc.data.Document Maven / Gradle / Ivy

package net.anotheria.anodoc.data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import net.anotheria.anodoc.util.context.CallContext;
import net.anotheria.anodoc.util.context.ContextManager;
import net.anotheria.util.xml.XMLAttribute;
import net.anotheria.util.xml.XMLNode;

/**
 * This class represents a basic document, which is a container for properties and therefore a 
 * corresponding modell object to a simple class (with attributes). 
 * @since 1.0
 * @author lrosenberg
 */
public class Document extends DataHolder 
		implements ICompositeDataObject, Cloneable{
	
	/**
	 * svid.
	 */
	private static final long serialVersionUID = -5433016437476873070L;
	
	/**
	 * The internal data storage. The data storage will be parsed by a Storage Service provided with anodoc. The 
	 * Document itself will not be saved, but the data it contains.
	 */
	private Hashtable dataStorage;
	
	/**
	 * Constant used to save type_identifier as internal property name.
	 */
	public static final String PROP_TYPE_IDENTIFIER = "###my_type###";
	
	/**
	 * Constant for property name of the property under which last update timestamp is stored.
	 */
	public static final String PROP_LAST_UPDATE = "###last_update###";
	
	/**
	 * Constant for property name of the property under which Author is stored.
	 */
	public static final String PROP_AUTHOR = "###author###";

	/**
	 * Creates a new Document with given name. 
	 */
	public Document(String id){
		super(id);
		dataStorage = new Hashtable();
		putProperty(new StringProperty(IHelperConstants.IDENTIFIER_KEY, IHelperConstants.IDENTIFIER_DOCUMENT));
	}
	
	/**
	 * Creates a new document as a copy of another document.
	 * @param anotherDocument the document to be copied
	 */
	public Document(Document anotherDocument){
		super("");
		dataStorage = new Hashtable();
		Hashtable srcTable = anotherDocument.dataStorage;
		Enumeration src = srcTable.elements();
		while(src.hasMoreElements()){
			Property p = (Property)src.nextElement();
			try{
				putProperty((Property)p.clone());
			}catch(CloneNotSupportedException e){
				throw new RuntimeException("Clone failed: "+e.getMessage());
			}
		}
		
	}

	/**
     * Returns the DataHolder contained in this Document under the given name.
     * A document can contain properties, documents and lists.
     * @see net.anotheria.anodoc.data.NoSuchDataHolderException
	 * @param name of DataHolder
	 * @return DataHolder
	 */	
	public DataHolder getDataHolder(String name) throws NoSuchDataHolderException{
		DataHolder holder = dataStorage.get(name);
		if (holder==null)
			throw new NoSuchDataHolderException(name);
		return holder;
	} 
	
	/**
	 * Returns the Document contained in this Document under the given name. 
     * @see net.anotheria.anodoc.data.NoSuchDocumentException
	 * @param name of Document
	 * @return Document
	 */
	public Document getDocument(String name) throws NoSuchDocumentException{
		try{
			DataHolder holder = getDataHolder(name);
			if (holder instanceof Document)
				return (Document)holder;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchDocumentException(name);
	}
	
	/**
	 * Returns a list of all contained properties.
	 * @return properties
	 */
	public List getProperties(){
		Collection holders = dataStorage.values();
		List ret = new ArrayList();
		Iterator it = holders.iterator();
		while(it.hasNext()){
			DataHolder h = it.next();
			if (h instanceof Property){
				ret.add((Property)h);
			}
		}
		return ret;
	}
	
	/**
	 * Returns the DocumentList contained in this Document under the given name. 
	 * @param name of DocumentList
	 * @throws net.anotheria.anodoc.data.NoSuchDocumentListException
	 * @return DocumentList
	 */
	@SuppressWarnings("unchecked")
	public  DocumentList getDocumentList(String name){
		try{
			DataHolder holder = getDataHolder(name);
			if (holder instanceof DocumentList)
				return (DocumentList)holder;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchDocumentListException(name);
	}
	
	/**
	 * Returns the Property contained in this Document under the given name.
	 * @param name of property
	 * @return Property
	 */
	public Property getProperty(String name) throws NoSuchPropertyException{
		try{
			DataHolder holder = getDataHolder(name);
			if (holder instanceof Property)
				return (Property)holder;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchPropertyException(name,"Property");
	}
	
	/**
	 * Returns the IntProperty contained in this Document under the given name.
	 * @param name of property
	 * @return IntProperty
	 */
	public IntProperty getIntProperty(String name) throws NoSuchPropertyException{
		try{
			Property aProperty = getProperty(name);
			if (aProperty instanceof IntProperty)
				return (IntProperty) aProperty;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchPropertyException(name, "IntProperty");
	}

	/**
	 * Returns the LongProperty contained in this Document under the given name.
	 * @param name of property
	 * @return LongProperty
	 */
	public LongProperty getLongProperty(String name) throws NoSuchPropertyException{
		try{
			Property aProperty = getProperty(name);
			if (aProperty instanceof LongProperty)
				return (LongProperty) aProperty;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchPropertyException(name,"LongProperty");
	}
	
	/**
	 * Returns the StringProperty contained in this Document under the given name.
	 * @param name of StringProperty
	 * @return StringProperty
	 */
	public StringProperty getStringProperty(String name) throws NoSuchPropertyException{
		try{
			Property aProperty = getProperty(name);
			if (aProperty instanceof StringProperty)
				return (StringProperty) aProperty;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchPropertyException(name, "StringProperty");
	}

	/**
	 * Returns the BooleanProperty contained in this Document under the given name. 
	 * @param name of BooleanProperty
	 * @return BooleanProperty
	 */
	public BooleanProperty getBooleanProperty(String name) throws NoSuchPropertyException{
		try{
			Property aProperty = getProperty(name);
			if (aProperty instanceof BooleanProperty)
				return (BooleanProperty) aProperty;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchPropertyException(name,"BooleanProperty");
	}

	/**
	 * Returns the ListProperty contained in this Document under the given name.
	 * @param name of ListProperty
	 * @return ListProperty
	 */
	public ListProperty getListProperty(String name) throws NoSuchPropertyException{
		try{
			Property aProperty = getProperty(name);
			if (aProperty instanceof ListProperty)
				return (ListProperty) aProperty;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchPropertyException(name, "ListProperty");
	}
	
	/**
	 * Returns the FloatProperty contained in this Document under the given name. 
	 * @param name of FloatProperty
	 * @return FloatProperty
	 */
	public FloatProperty getFloatProperty(String name) throws NoSuchPropertyException{
		try{
			Property aProperty = getProperty(name);
			if (aProperty instanceof FloatProperty)
				return (FloatProperty) aProperty;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchPropertyException(name, "FloatProperty");
	}
	
	/**
	 * Returns the DoubleProperty contained in this Document under the given name. 
	 * @param name of DoubleProperty
	 * @return DoubleProperty
	 */
	public DoubleProperty getDoubleProperty(String name) throws NoSuchPropertyException{
		try{
			Property aProperty = getProperty(name);
			if (aProperty instanceof DoubleProperty)
				return (DoubleProperty) aProperty;
		}catch(NoSuchDataHolderException e){}
		throw new NoSuchPropertyException(name, "DoubleProperty");
	}

	/**
	 * Returns the DocumentList contained in this Document under the given name in any case,
	 * which means that if no DocumentList is contained it a new will be created.  
	 * This function is protected because it implies very much knowledge about the module 
	 * structure and shouldn't be called from outside a document.
	 * @see net.anotheria.anodoc.data.NoSuchDocumentListException
	 * @param name of Document
	 * @return DocumentList
	 */
	protected  DocumentList getDocumentListAnyCase(String name) {
		try{
			return getDocumentList(name);
		}catch(NoSuchDocumentListException e){
			
		}
		DocumentList newList = createDocumentList(name);
		putList(newList);
		return newList;
	}
	
	/**
	 * Returns the Document contained in this Document under the given name in any case,
	 * which means that if no Document is contained it a new will be created. 
	 * This function is protected because it implies very much knowledge about the module 
	 * structure and shouldn't be called from outside a document.
	 * @see net.anotheria.anodoc.data.NoSuchDocumentException
	 * @param name of document
	 * @return Doucument
	 */
	protected Document getDocumentAnyCase(String name) {
		try{
			return getDocument(name);
		}catch(NoSuchDocumentException e){}
		Document newDoc = createDocument(name);
		putDocument(newDoc);
		return newDoc;
	}
	
	protected ListProperty getListPropertyAnyCase(String name){
		 try{
		 	return getListProperty(name);
		 }catch(NoSuchPropertyException e){}
		 ListProperty list = new ListProperty(name);
		 putProperty(list);
		 return list;
	}
	
	/**
	 * Creates a new DocumentList. Overwrite this, if your document
	 * uses special lists.
	 * Called by getDocumentListAnyCase
	 * @param name
	 * @return
	 */
	protected  DocumentList createDocumentList(String name){
		return new DocumentList(name);
	}
	
	/**
	 * Creates a new Document. Overwrite this, if your document
	 * uses special subdocuments (which should almost ever be the case).
	 * Called by getDocumentAnyCase
	 * @param name
	 * @return
	 */
	protected Document createDocument(String name){
		return new Document(name);
	}
	
	protected ListProperty createListProperty(String name){
		return new ListProperty(name);
	}

	protected void removeDataHolder(DataHolder holder){
		dataStorage.remove(holder.getId());
	}
	
	protected void removeDataHolder(String id){
		dataStorage.remove(id);
	}
	
	/**
	 * Puts the given DataHolder (which can be a document, a list or a property)
	 * in the internal storage.
	 */
	protected void addDataHolder(DataHolder holder){
		dataStorage.put(holder.getId(), holder);
	}
	
	/**
	 * Puts the given StringProperty in the internal storage.
	 */
	public void putStringProperty(StringProperty p){
		putProperty(p);
	}
	
	/**
	 * Puts the given IntProperty in the internal storage.
	 */
	public void putIntProperty(IntProperty p){
		putProperty(p);
	}

	/**
	 * Puts the given LongProperty in the internal storage.
	 */
	public void putLongProperty(LongProperty p){
		putProperty(p);
	}

	/**
	 * Puts the given BooleanProperty in the internal storage.
	 */
	public void putBooleanProperty(BooleanProperty p){
		putProperty(p);
	}

	/**
	 * Puts the given ListProperty in the internal storage.
	 */
	public void putListProperty(ListProperty p){
		putProperty(p);
	}
	
	/**
	 * Puts the given FloatProperty in the internal storage.
	 */
	public void putFloatProperty(FloatProperty p){
		putProperty(p);
	}
	
	/**
	 * Puts the given FloatProperty in the internal storage.
	 */
	public void putDoubleProperty(DoubleProperty p){
		putProperty(p);
	}

	/**
	 * Puts the given Property in the internal storage.
	 */
	public void putProperty(Property p){
		addDataHolder(p);
	}
	
	public void removeProperty(Property p){
		removeDataHolder(p);
	}
	
	public void removeProperty(String propertyName){
		removeDataHolder(propertyName);
	}

	/**
	 * Puts the given Document in the internal storage.
	 */
	public void putDocument(Document doc){
		addDataHolder(doc);
	}
	
	/**
	 * Puts the given DocumentList in the internal storage.
	 */
	public void putList(DocumentList list){
		addDataHolder(list);
	}

	/**
	 * Returns the string representation of this document.
	 */
	@Override public String toString(){
		return "DOC "+getId()+" "+dataStorage;
	}
	
	///////////// STORAGE /////////////
	
	
	/**
	 * Returns the keys (names) of the contained documents.
	 * @see net.anotheria.anodoc.data.ICompositeDataObject#getKeys()
	 */
	public Enumeration getKeys() {
		return dataStorage.keys();
	}

	/**
	 * Returns the contained object stored under given key.
	 * @see net.anotheria.anodoc.data.ICompositeDataObject#getObject(String)
	 */
	public Object getObject(String key) {
		return dataStorage.get(key);
	}

	/**
	 * Returns the storage id which should be used by a storage to 
	 * store this document.
	 * @see net.anotheria.anodoc.data.IBasicStoreableObject#getStorageId()
	 */
	public String getStorageId() {
		return IHelperConstants.IDENTIFIER_DOCUMENT+
				IHelperConstants.DELIMITER+
				getId();
	} 
	
	/////////////////// TYPE IDENTIFIER FOR DATENBANK und FACTORY
	/**
	 * Returns the type identifier of this document.
	 */
	public String getTypeIdentifier(){
		return getString(PROP_TYPE_IDENTIFIER);
	}

	/**
	 * Sets the type identifier for this document. The type identifier is 
	 * especially useful for queries and factory-reassembling.
	 * @param anIdentifier
	 */	
	public void setTypeIdentifier(String anIdentifier){
		setString(PROP_TYPE_IDENTIFIER, anIdentifier);
	}
	
	//// WEITERE NUETZLICHE FUNKTION ////
	/**
	 * Returns the string value of the according StringProperty,
	 * or empty string (see getEmptyString) if none set.
	 */
	public String getString(String fieldId) throws NoSuchPropertyException{
		try{
			return getStringProperty(fieldId).getString();
		}catch(NoSuchPropertyException e){
			return getEmptyString();
		}
	}
	
	/**
	 * Returns the long value of the according LongProperty,
	 * or an empty long (see getEmptyLong) if none set.
	 * @return long value
	 */
	public long getLong(String fieldId) throws NoSuchPropertyException{
		try{
			return getLongProperty(fieldId).getlong();
		}catch(NoSuchPropertyException e){
			return getEmptyLong();
		}
	}
	
	/**
	 * Returns the int value of the according IntProperty,
	 * or an empty int (see getEmptyInt) if none set.
	 * @return int value
	 */
	public int getInt(String fieldId) throws NoSuchPropertyException{
		try{
			return getIntProperty(fieldId).getInt();
		}catch(NoSuchPropertyException e){
			return getEmptyInt();
		}
	}

	/**
	 * Returns list of Property by fieldId.
	 * @param fieldId fieldId
	 * @return list of Property or empty list if no Property was found by diven fieldId
	 * @throws NoSuchPropertyException
	 */
	public List getList(String fieldId) throws NoSuchPropertyException{
		try{
			return getListProperty(fieldId).getList();
		}catch(NoSuchPropertyException e){
			return getEmptyList();
		}
	}

	/**
	 * Returns the float value of the according FloatProperty,
	 * or an empty float (see getEmptyFloat) if none set.
	 * @return float value of FloatProperty
	 */
	public float getFloat(String fieldId) throws NoSuchPropertyException{
		try{
			return getFloatProperty(fieldId).getfloat();
		}catch(NoSuchPropertyException e){
			return getEmptyFloat();
		}
	}

	/**
	 * Returns the double value of the according DoubleProperty,
	 * or an empty double (see getEmptyDouble) if none set.
	 * @return double value of DoubleProperty
	 */
	public double getDouble(String fieldId) throws NoSuchPropertyException{
		try{
			return getDoubleProperty(fieldId).getdouble();
		}catch(NoSuchPropertyException e){
			return getEmptyDouble();
		}
	}

	/**
	 * Returns the boolean value of the according BooleanProperty,
	 * or an empty boolean (see getEmptyBoolean) if none set.
	 * @return boolean value
	 */
	public boolean getBoolean(String fieldId) throws NoSuchPropertyException{
		try{
			return getBooleanProperty(fieldId).getboolean();
		}catch(NoSuchPropertyException e){
			return getEmptyBoolean();
		}
	}
	
	public void setList(String fieldId, List value){
		putListProperty(new ListProperty(fieldId, value));
	}

	/**
	 * Sets a StringProperty with name = fieldId and value = value in this document.
	 */
	public void setString(String fieldId, String value){
		putStringProperty(new StringProperty(fieldId, value));
	}
	
	/**
	 * Sets a LongProperty with name = fieldId and value = value in this document.
	 */
	public void setLong(String fieldId, long value){
		putLongProperty(new LongProperty(fieldId, value));
	}
	
	/**
	 * Sets a IntProperty with name = fieldId and value = value in this document.
	 */
	public void setInt(String fieldId, int value){
		putIntProperty(new IntProperty(fieldId, value));
	}
	
	/**
	 * Sets a FloatProperty with name = fieldId and value = value in this document.
	 */
	public void setFloat(String fieldId, float value){
		putFloatProperty(new FloatProperty(fieldId, value));
	}

	/**
	 * Sets a FloatProperty with name = fieldId and value = value in this document.
	 */
	public void setDouble(String fieldId, double value){
		putDoubleProperty(new DoubleProperty(fieldId, value));
	}

	/**
	 * Sets a BooleangProperty with name = fieldId and value = value in this document.
	 */
	public void setBoolean(String fieldId, boolean value){
		putBooleanProperty(new BooleanProperty(fieldId, value));
	}

	/**
	 * Returns the initial value for a string (empty string - ""). Overwrite it if you wish another values. An empty value will always be returned if
	 * you call get'Type' and the corresponding property doesn't exists.
	 *
	 * @return ""
	 */
	public String getEmptyString() {
		return "";
	}

	/**
	 * Returns the initial value for a long (0). Overwrite it if you wish another values. An empty value will always be returned if  
	 * you call get'Type' and the corresponding property doesn't exists.   
	 * @return 0
	 */
	public long getEmptyLong(){
		return 0;
	}
	
	/**
	 * Returns the initial value for a int (0). Overwrite it if you wish another values. An empty value will always be returned if  
	 * you call get'Type' and the corresponding property doesn't exists.   
	 * @return 0
	 */
	public int getEmptyInt(){
		return 0;
	}
	
	/**
	 * Returns the initial value for a float (0.0). Overwrite it if you wish another values. An empty value will always be returned if  
	 * you call get'Type' and the corresponding property doesn't exists.   
	 * @return 0
	 */
	public float getEmptyFloat(){
		return 0;
	}

	/**
	 * Returns the initial value for a double (0.0). Overwrite it if you wish another values. An empty value will always be returned if  
	 * you call get'Type' and the corresponding property doesn't exists.   
	 * @return 0.0
	 */
	public double getEmptyDouble(){
		return 0.0;
	}

	/**
	 * Returns the initial value for a boolean (false). Overwrite it if you wish another values. An empty value will always be returned if  
	 * you call get'Type' and the corresponding property doesn't exists.   
	 * @return false
	 */
	public boolean getEmptyBoolean(){
		return false;
	}
	
	public List getEmptyList(){
		return new ArrayList();
	}
	
	/**
	 * Returns the cumulative size of the contained DataHolders.
	 * @see net.anotheria.anodoc.data.DataHolder#getSizeInBytes()
	 * @return size of the contained DataHolders
	 */
	public long getSizeInBytes() {
		int sum = 0;
		Enumeration values = dataStorage.elements();
		while(values.hasMoreElements()){
			sum += values.nextElement().getSizeInBytes();
		}
		return sum;
	}

	public void renameTo(String newId){
		setId(newId);
	}
	
	@SuppressWarnings("unchecked")
	@Override public Object clone() throws CloneNotSupportedException{
		Object ret = super.clone();
		((Document)ret).dataStorage = (Hashtable)dataStorage.clone();
		return ret;
	}

	@Override public XMLNode toXMLNode(){
		XMLNode root = new XMLNode("document");
		
		root.addAttribute(new XMLAttribute("documentId", getId()));
		for (Iterator it = dataStorage.values().iterator(); it.hasNext();)
			root.addChildNode(it.next().toXMLNode());
		
		return root;
	}
	
	public Object getPropertyValue(String propertyName){
		return getProperty(propertyName).getValue();
	}
	
	public void setLastUpdateNow(){
		setLong(PROP_LAST_UPDATE, System.currentTimeMillis());
	}
	
	public long getLastUpdateTimestamp(){
		return getLong(PROP_LAST_UPDATE); 
	}
	
	public void setCallContextAuthor(){
		CallContext callContext = ContextManager.getCallContext();
		String author = callContext != null? callContext.getCurrentAuthor(): "UNKNOWN";
		setString(PROP_AUTHOR, author);
	}
	
	public String getAuthor(){
		return getString(PROP_AUTHOR); 
	}
	
	protected List copyToStringList(List properties){
		ArrayList ret = new ArrayList(properties.size());
		for (Property p : properties)
			ret.add(((StringProperty)p).getString());
		return ret;
	}
	
	protected List copyFromStringList(List strings){
		ArrayList ret = new ArrayList();
		for (String s : strings)
			ret.add(new StringProperty(s,s));
		return ret;
	}
	
	protected  List copyToIntegerList(List properties){
		ArrayList ret = new ArrayList(properties.size());
		for (Property p : properties)
			ret.add(((IntProperty)p).getInt());
		return ret;
	}
	
	protected List copyFromIntegerList(List integers){
		ArrayList ret = new ArrayList();
		for (int i : integers)
			ret.add(new IntProperty(""+ i,i));
		return ret;
	}
	
	protected  List copyToLongList(List properties){
		ArrayList ret = new ArrayList(properties.size());
		for (Property p : properties)
			ret.add(((LongProperty)p).getLong());
		return ret;
	}
	
	protected List copyFromLongList(List longs){
		ArrayList ret = new ArrayList();
		for (long l: longs)
			ret.add(new LongProperty(""+ l, l));
		return ret;
	}
	
	protected  List copyToBooleanList(List properties){
		ArrayList ret = new ArrayList(properties.size());
		for (Property p : properties)
			ret.add(((BooleanProperty)p).getBoolean());
		return ret;
	}
	
	protected List copyFromBooleanList(List booleans){
		ArrayList ret = new ArrayList();
		for (boolean b: booleans)
			ret.add(new BooleanProperty(""+ b, b));
		return ret;
	}
	
	protected  List copyToDoubleList(List properties){
		ArrayList ret = new ArrayList(properties.size());
		for (Property p : properties)
			ret.add(((DoubleProperty)p).getDouble());
		return ret;
	}
	
	protected List copyFromDoubleList(List doubles){
		ArrayList ret = new ArrayList();
		for (double d: doubles)
			ret.add(new DoubleProperty(""+ d, d));
		return ret;
	}
	
	protected  List copyToFloatList(List properties){
		ArrayList ret = new ArrayList(properties.size());
		for (Property p : properties)
			ret.add(((FloatProperty)p).getFloat());
		return ret;
	}
	
	protected List copyFromFloatList(List floats){
		ArrayList ret = new ArrayList();
		for (float d: floats)
			ret.add(new FloatProperty(""+ d, d));
		return ret;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy