package org.biomoby.shared.data;

import org.biomoby.registry.meta.Registry;
import org.biomoby.shared.MobyDataType;
import org.biomoby.shared.MobyNamespace;
import org.biomoby.shared.parser.MobyTags;

/**
 * A class representing a MOBY String primitive. 
 *
 * Internally, the value is stored in a StringBuffer.  Because
 * getObject() will return a mutable StringBuffer, you can use
 * its methods to modify the underlying value of this MOBY object.
 */

public class MobyDataString extends MobyDataObject{

    private StringBuffer value;

    /**
     * Construct the object using a DOM fragment.
     *
     * @throws IllegalArgumentException if the element is not a String tag
     */
    public MobyDataString(org.w3c.dom.Element element) throws IllegalArgumentException{
	this(element, null);
    }

    public MobyDataString(org.w3c.dom.Element element, Registry registry) throws IllegalArgumentException{
	this(getName(element), getTextContents(element), registry);
	setId(getId(element));
	addNamespace(getNamespace(element, registry));
    }
    
    /**
     * Constructor to build a MOBY base String object from a CharSequence
     * (i.e. String, StringBuffer, CharBuffer or StringBuilder).
     */
    public MobyDataString(String articleName, CharSequence stringValue){
	this(articleName, stringValue, null);
    }

    public MobyDataString(String articleName, CharSequence stringValue, Registry registry){
	super(articleName, registry);
	setDataType(MobyDataType.getDataType(MobyTags.MOBYSTRING, registry));
	value = stringValue == null ? null : new StringBuffer(stringValue.toString());
    }

    public MobyDataString(CharSequence stringValue){
	this("", stringValue, null);
    }

    public MobyDataString(CharSequence stringValue, Registry registry){
	this("", stringValue, registry);
    }

    public String toString(){
	return value.toString();
    }

    public MobyDataString clone(){
	MobyDataString copy = new MobyDataString(getName(), value, getDataType().getRegistry());
	copy.setDataType(getDataType());
	copy.setId(getId());
	copy.setNamespaces(getNamespaces());
	return copy;
    }

    /**
     * @return a StringBuffer (i.e. the value is editable)
     */
    public Object getObject(){
	return value;
    }

    public String getValue(){
	return value.toString();
    }

    public void setValue(CharSequence str){
	value.setLength(0);
	value.append(str);
    }

    /**
     * This method sanitizes strings of XML escape characters such as the ampersand (&amp;) and the 
     * less-than sign (&lt;).  WARNING: this method will not escape ampersand in the string "&amp;amp;", 
     * or '&amp;#x26;' style character references.  We will assume that is this case you've probably 
     * already written the string as XML. Also note that null strings are treated as empty strings.
     *
     * WARNING: As of yet, we do not deal with the false escaping of strings containg already-escaped 
     * CDATA sections!
     */
    public String toXML(){
	MobyNamespace[] ns = getNamespaces();
	if(xmlMode == MobyDataInstance.SERVICE_XML_MODE){
	    String tmpValue = value.toString();
	    if(tmpValue != null){
		tmpValue = tmpValue.replaceAll("&(?!(amp|#x\\d+);)", "&amp;");
		tmpValue = tmpValue.replaceAll("<", "&lt;");
	    }
	    else{
		tmpValue = "";
	    }
	    
	    return "<" + MobyTags.MOBYSTRING + " "+ getAttrXML() + " xml:space=\"preserve\">" + 
		tmpValue + "</" + MobyTags.MOBYSTRING + ">";
	}
	// Central mode, use default toXML provided by superclasses
	else{
	    return super.toXML();
	}
    }
}
