package org.genedb.db.loading;
import org.apache.log4j.Logger;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This class represents a specific GO entry.
*
* @author <a href="mailto:art@sanger.ac.uk">Adrian Tivey</a>
*/
public class GoInstance {
private List<String> qualifiers = new ArrayList<String>(0);
private String id;
private String ref;
private String withFrom;
private GoEvidenceCode evidence = GoEvidenceCode.NR;
private GoAspect subtype;
private String name;
private String date;
private String attribution;
private String residue;
protected static final Logger logger = Logger.getLogger(GoInstance.class);
private static String today;
static {
DateFormat dFormat = new SimpleDateFormat("yyyyMMdd");
today = dFormat.format(new Date());
}
/**
* Get the value of date.
*
* @return value of date.
*/
public String getDate() {
if (date == null) {
return today;
}
return date;
}
/**
* Set the date.
*
* @param date The date, in ISO format without dashes: for example, "<code>19760924</code>".
*/
public void setDate(String date) {
if (date == null) {
throw new NullPointerException("Date is null");
}
if (!date.matches("\\d{8}")) {
throw new IllegalArgumentException("Date format is invalid (" + date + "); should be eight digits");
}
this.date = date;
}
/**
* Get the subtype.
*
* @return the GO subtype.
*/
public GoAspect getSubtype() {
return subtype;
}
private enum GoAspect {PROCESS, FUNCTION, COMPONENT};
private static final Map<String, GoAspect> aspectsByUcString = new HashMap<String, GoAspect>();
static {
aspectsByUcString.put("P", GoAspect.PROCESS);
aspectsByUcString.put("F", GoAspect.FUNCTION);
aspectsByUcString.put("C", GoAspect.COMPONENT);
aspectsByUcString.put("PROCESS", GoAspect.PROCESS);
aspectsByUcString.put("FUNCTION", GoAspect.FUNCTION);
aspectsByUcString.put("COMPONENT", GoAspect.COMPONENT);
aspectsByUcString.put("BIOLOGICAL PROCESS", GoAspect.PROCESS);
aspectsByUcString.put("MOLECULAR FUNCTION", GoAspect.FUNCTION);
aspectsByUcString.put("CELLULAR COMPONENT", GoAspect.COMPONENT);
}
/**
* Set the subtype.
*
* @param subtype The GO subtype.
* May be specified as:<ul>
* <li> A single character: 'P', 'C' or 'F';
* <li> A single word: "process", "component" or "function";
* <li> The full phrase: "biological process", "cellular component", or "molecular function".
* </ul>
* Capitalisation is ignored: the string is handled case-insensitively.
*/
public void setSubtype(String subtype) {
String ucSubtype = subtype.toUpperCase();
if (!aspectsByUcString.containsKey(ucSubtype)) {
throw new IllegalArgumentException(String.format("Unrecognised GO subtype '%s'", subtype));
}
this.subtype = aspectsByUcString.get(ucSubtype);
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
/**
* Get the list of qualifiers.
*
* @return List of qualifiers.
*/
public List<String> getQualifierList() {
if (qualifiers == null) {
return Collections.unmodifiableList(new ArrayList<String>(0));
}
return qualifiers;
}
/**
* Add qualifiers.
*
* @param qualifiers A pipe-separated list of qualifiers
*/
public void addQualifier(String qualifiers) {
for (String qualifier: qualifiers.split("\\|")) {
this.qualifiers.add(qualifier);
}
}
private static Set<String> validQualifiers = new HashSet<String>();
static { Collections.addAll(validQualifiers, "NOT", "contributes_to", "colocalizes_with"); }
private boolean isQualifierValid(String qualifier) {
return validQualifiers.contains(qualifier);
}
public String getQualifierDisplay(boolean officialOnly, String def, String separator,
boolean replaceUnderscore) {
StringBuffer ret = new StringBuffer();
List<String> allQualifier = getQualifierList();
if (allQualifier == null || allQualifier.size() == 0) {
return def;
}
List<String> filteredList = null;
if (!officialOnly) {
filteredList = allQualifier;
} else {
filteredList = new ArrayList<String>();
for (String qualifier : allQualifier) {
if (isQualifierValid(qualifier)) {
filteredList.add(qualifier);
}
}
}
if (filteredList.isEmpty()) {
return def;
}
for (String qualifier : filteredList) {
if (ret.length() != 0) {
ret.append(separator);
}
if (replaceUnderscore) {
ret.append(qualifier.replaceAll("_", " "));
} else {
ret.append(qualifier);
}
}
return ret.toString();
}
public void setWithFrom(String withFrom, GoEvidenceCode evidence) {
switch (evidence) {
case IC:
case IGI:
case IPI:
case IEA:
case ISS:
setWithFrom(withFrom);
break;
default:
logger.warn("Attempting to set with/from for evidence code of '"
+ evidence.getDescription() + "'");
break;
}
}
public void setWithFrom(String withFrom) {
this.withFrom = withFrom;
}
/**
* Get the accession number of the Classification.
*
* @return The accession number
*/
public String getId() {
return id;
}
private static final Pattern GO_ID_PATTERN = Pattern.compile("(?:GO:)?(\\d{7})");
/**
* Set the accession number of the entry
*
* @param v The accession number
*/
public void setId(String id) throws DataError {
Matcher matcher = GO_ID_PATTERN.matcher(id);
if (!matcher.matches()) {
throw new DataError("GO id doesn't look right '" + id + "'");
}
this.id = matcher.group(1);
}
/**
* Get the value of ref.
*
* @return Value of ref.
*/
public String getRef() {
return ref;
}
/**
* Set the value of ref.
*
* @param v Value to assign to ref.
*/
public void setRef(String v) {
this.ref = v;
}
/**
* Get the value of evidence.
*
* @return Value of evidence.
*/
public GoEvidenceCode getEvidence() {
return evidence;
}
/**
* Set the value of evidence.
*
* @param v Value to assign to evidence.
*/
public void setEvidence(GoEvidenceCode evidence) {
this.evidence = evidence;
}
public String getAttribution() {
return attribution;
}
public void setAttribution(String attribution) {
this.attribution = attribution;
}
public String getWithFrom() {
return this.withFrom;
}
public String getResidue() {
return residue;
}
public void setResidue(String residue) {
this.residue = residue;
}
}