
package org.biomoby.shared.data;

import org.biomoby.shared.MobyPrefixResolver;
import org.biomoby.shared.parser.MobyTags;
import org.w3c.dom.Element;

/**
 * Class to hold data corresponginf to the MOBY PIB.
 */

public class MobyProvisionInfo{
    private String softwareName;
    private String softwareVersion;
    private String softwareComment;
    private String dbName;
    private String dbVersion;
    private String dbComment;
    private String serviceComment;

    /**
     * Creates a blank provision information object.
     */
    public MobyProvisionInfo(){
    }
    
    /**
     * Builds a provision information block from an XML fragment 
     * ("ProvisionInformation", as represented by a DOM node).
     */
    public MobyProvisionInfo(Element e){
	Element child = MobyPrefixResolver.getChildElement(e, MobyTags.SERVICESOFTWARE);
	// all three child elements are optional.
	if(child != null){
	    setSoftwareName(MobyPrefixResolver.getAttr(child, MobyTags.SOFTWARENAME));
	    setSoftwareVersion(MobyPrefixResolver.getAttr(child, MobyTags.SOFTWAREVERSION));
	    setSoftwareComment(MobyPrefixResolver.getAttr(child, MobyTags.SOFTWARECOMMENT));
	}

	child = MobyPrefixResolver.getChildElement(e, MobyTags.SERVICEDATABASE);
	// all three child elements are optional.
	if(child != null){
	    setSoftwareName(MobyPrefixResolver.getAttr(child, MobyTags.DATABASENAME));
	    setSoftwareVersion(MobyPrefixResolver.getAttr(child, MobyTags.DATABASEVERSION));
	    setSoftwareComment(MobyPrefixResolver.getAttr(child, MobyTags.DATABASECOMMENT));
	}
	child = MobyPrefixResolver.getChildElement(e, MobyTags.SERVICECOMMENT);
	if(child != null){
	    setComment(child.getTextContent());
	}
    }

    public void setSoftwareName(String name){
	softwareName = name;
    }
    
    public String getSoftwareName(){
	return softwareName;
    }

    public void setSoftwareVersion(String version){
	softwareVersion = version;
    }
    
    public String getSoftwareVersion(){
	return softwareVersion;
    }

    public void setSoftwareComment(String comment){
	softwareComment = comment;
    }
    
    /**
     * A human readable message about the software used to generate the object.
     */
    public String getSoftwareComment(){
	return softwareComment;
    }

    public void setDBName(String name){
	dbName = name;
    }
    
    public String getDBName(){
	return dbName;
    }

    public void setDBVersion(String version){
	dbVersion = version;
    }
    
    public String getDBVersion(){
	return dbVersion;
    }

    public void setDBComment(String comment){
	dbComment = comment;
    }
    
    public String getDBComment(){
	return dbComment;
    }

    /**
     * This is a general comment about the provision of the object, some human readable message.
     */
    public void setComment(String comment){
	serviceComment = comment;
    }

    public String getComment(){
	return serviceComment;
    }

    /**
     * For escaping XML meta-characters from attribute strings, 
     * namely ampersand, double quote, and greater-than
     */
    private String escape(String text){
	if(text == null){
	    return "";
	}
	text = text.replaceAll("&(?!(amp|#x\\d+);)", "&amp;");
	text = text.replaceAll("<", "&lt;");
	return text.replaceAll("\"", "&quot;");
    }

    /**
     * This method formats the available information into an XML format 
     * suitable for inclusion in a MOBY Object.  If all fields are null, 
     * an empty string is returned (the MOBY-S API specifies that a ProvisionInformation
     * block must contain at least one child tag).
     */
    public String toXML(){
	StringBuffer xml = new StringBuffer();
	if(softwareName != null || softwareVersion != null || softwareComment != null){
	    xml.append("<"+MobyTags.SERVICESOFTWARE+" " + MobyTags.SOFTWARENAME + "=\"" + escape(softwareName) +
		       "\" " + MobyTags.SOFTWAREVERSION + "=\"" + escape(softwareVersion) +
		       "\" " + MobyTags.SOFTWARECOMMENT + "=\"" + escape(softwareComment) + "/>\n");
	}
	if(dbName != null || dbVersion != null || dbComment != null){
	    xml.append("<" + MobyTags.SERVICEDATABASE + " " + MobyTags.DATABASENAME + "=\"" + escape(dbName) +
		       "\" " + MobyTags.DATABASEVERSION + "=\"" + escape(dbVersion) +
		       "\" " + MobyTags.DATABASECOMMENT + "=\"" + escape(dbComment) + "/>\n");
	}
	if(serviceComment != null){
	    xml.append("<" + MobyTags.SERVICECOMMENT + ">"+escape(serviceComment)+"</" + MobyTags.SERVICECOMMENT + ">");
	}
	
	if(xml.length() == 0){
	    // Empty info, return empty string
	    return "";
	}

	return "<" + MobyTags.PROVISIONINFORMATION + ">\n"+xml.toString()+"</" + MobyTags.PROVISIONINFORMATION + ">\n";
    }

     /**************************************************************************
      *
      *************************************************************************/
     public String toString() {
 	StringBuffer buf = new StringBuffer();
 	buf.append ("Provision information:\n");
 	if (softwareName    != null) buf.append ("   Software name: " + softwareName + "\n");
 	if (softwareVersion != null) buf.append ("   Software version: " + softwareVersion + "\n");
 	if (softwareComment != null) buf.append ("   Software comment: " + softwareComment + "\n");
 	if (dbName    != null) buf.append ("   Database name: " + dbName + "\n");
 	if (dbVersion != null) buf.append ("   Database version: " + dbVersion + "\n");
 	if (dbComment != null) buf.append ("   Database comment: " + dbComment + "\n");
 	if (serviceComment != null) buf.append ("   Service comment: " + serviceComment + "\n");
 	return new String (buf);
     }
 
     /**************************************************************************
      *
      *************************************************************************/
     public String format (int indent) {
 	return org.biomoby.shared.Utils.format (this, indent);
     }

}
