package org.wordcorr.db;
import org.jdom.*;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import org.wordcorr.gui.AppPrefs;
import org.wordcorr.gui.Dialogs;
/**
* Represents a user's view on a collection.
* @author Keith Hamasaki, Jim Shiba
**/
public class View extends AbstractPersistent {
View(Database db, long id, WordCollection collection) {
super(db, id);
_collection = collection;
}
//---------------------------------------------------------------//
// Attributes
//---------------------------------------------------------------//
/**
* Get the value of threshold.
**/
public Integer getThreshold() {
return _threshold;
}
/**
* Get the numeric value of threshold based on number of varieties.
**/
public int getThresholdValue() {
int threshold =
new Double(Math.ceil(getThreshold().doubleValue() * _varieties.size() / 100))
.intValue();
return threshold;
}
/**
* Set the value of threshold.
* @param v Value to assign to threshold.
**/
public void setThreshold(Integer v) {
_threshold = v;
setDirty();
_thresholdChanged = true;
}
/**
* Get the value of remarks.
**/
public String getRemarks() {
return (_remarks == null) ? "" : _remarks;
}
/**
* Set the value of remarks.
* @param v Value to assign to remarks.
**/
public void setRemarks(String v) {
_remarks = v;
setDirty();
}
/**
* Get the members of this view.
* @return a list of Variety objects that are members of this
* view, in order.
**/
public List getMembers() {
return new ArrayList(_varieties);
}
/**
* Set the members of this view.
* @param varieties A list of variety objects to set for this
* view, in order.
**/
public void setMembers(List varieties) {
_varieties = new ArrayList(varieties);
setDirty();
_varietiesChanged = true;
}
/**
* Get this view's collection.
**/
public WordCollection getCollection() {
return _collection;
}
/**
* Reset change flags.
**/
private void resetChangeFlags() {
_thresholdChanged = false;
_varietiesChanged = false;
}
/**
* Delete this object.
**/
public void delete() throws DatabaseException {
getDatabase().deleteObject(this);
}
/**
* Delete this view's unused groups for the given entry.
**/
public void deleteUnusedGroups(final Entry entry) throws DatabaseException {
getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "DELETE_UNUSED_GROUPS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
stmt.setLong(2, entry.getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
return null;
}
});
}
/**
* Delete this view's unused protosegments except 'pro' and 'res'.
**/
public void deleteUnusedProtosegments() throws DatabaseException {
getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "DELETE_UNUSED_PROTOSEGMENTS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
return null;
}
});
}
/**
* Get this view's alignments for the given entry.
**/
public List getAlignments(final Entry entry) throws DatabaseException {
List existing = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_ALIGNMENTS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
stmt.setLong(2, entry.getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
try {
Datum datum = new Datum(db, rs.getLong(1), entry);
datum.revert();
Alignment alignment = new Alignment(db, rs.getLong(2), View.this, datum);
alignment.updateObject(rs);
return alignment;
} catch (DatabaseException e) {
throw new SQLException(e.getRootCause().getMessage());
}
}
});
List allData = entry.getData();
List ret = new ArrayList(existing);
// create new items for each datum not in the result set
// (unannotated datums)
// O(n^2) for now
for (Iterator it = allData.iterator(); it.hasNext();) {
Datum datum = (Datum) it.next();
boolean found = false;
for (Iterator it2 = existing.iterator(); it2.hasNext();) {
Alignment alignment = (Alignment) it2.next();
if (alignment.getDatum().equals(datum)) {
found = true;
break;
}
}
if (!found && getMembers().contains(datum.getVariety())) {
ret.add(makeAlignment(datum));
}
}
Collections.sort(ret, new Comparator() {
public int compare(Object o1, Object o2) {
Alignment a1 = (Alignment) o1;
Alignment a2 = (Alignment) o2;
int i1 = _varieties.indexOf(a1.getDatum().getVariety());
int i2 = _varieties.indexOf(a2.getDatum().getVariety());
return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
}
});
return ret;
}
/**
* Get untabulated entries.
**/
public List getUntabulatedEntries() throws DatabaseException {
return getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_UNTABULATED_ENTRIES";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
Entry entry = new Entry(db, rs.getLong(1), _collection);
entry.updateObject(rs);
return entry;
}
});
}
/**
* Get grapheme clusters.
**/
public List getGraphemeClusters() throws DatabaseException {
List allData = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_GRAPHEME_CLUSTERS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
return rs.getString(1);
}
});
// extract grapheme clusters
List ret = new ArrayList();
for (Iterator it = allData.iterator(); it.hasNext();) {
String data = (String) it.next();
int delim = data.indexOf(":");
String vector = data.substring(0, delim);
String rawDatum = data.substring(delim + 1);
// extract grapheme cluster
int pos = 0;
int startpos = 0;
for (int i = 0; i < vector.length(); i++) {
switch (vector.charAt(i)) {
case Alignment.HOLD_SYMBOL :
pos++;
break;
case Alignment.GRAPHEME_CLUSTER_START :
startpos = pos;
break;
case Alignment.GRAPHEME_CLUSTER_END :
String cluster = rawDatum.substring(startpos, pos);
if (!ret.contains(cluster))
ret.add(cluster);
break;
default :
break;
}
}
}
Collections.sort(ret, new Comparator() {
public int compare(Object o1, Object o2) {
return ((String) o1).compareTo((String) o2);
}
});
return ret;
}
/**
* Undefine grapheme clusters.
**/
public void undefineGraphemeCluster(String graphemeCluster)
throws DatabaseException {
// construct search string
final StringBuffer search = new StringBuffer(graphemeCluster.length() + 4);
search.append("%" + Alignment.GRAPHEME_CLUSTER_START);
for (int i = 0; i < graphemeCluster.length(); i++)
search.append("_");
search.append(Alignment.GRAPHEME_CLUSTER_END + "%");
List allData = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_UNDEFINE_GRAPHEME_CLUSTERS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
stmt.setString(2, search.toString());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
return rs.getString(1);
}
});
// extract grapheme clusters and compare
for (Iterator it = allData.iterator(); it.hasNext();) {
String data = (String) it.next();
int delim1 = data.indexOf(":");
int delim2 = data.indexOf(":", delim1 + 1);
int delim3 = data.lastIndexOf(":");
String vector = data.substring(0, delim1);
String rawDatum = data.substring(delim1 + 1, delim2);
long groupID = Long.parseLong(data.substring(delim2 + 1, delim3));
long alignmentID = Long.parseLong(data.substring(delim3 + 1));
// extract grapheme cluster
boolean undefine = false;
int pos = 0;
int vectorpos = 0;
int startpos = 0;
for (int i = 0; i < vector.length(); i++) {
switch (vector.charAt(i)) {
case Alignment.HOLD_SYMBOL :
pos++;
break;
case Alignment.GRAPHEME_CLUSTER_START :
startpos = pos;
vectorpos = i;
break;
case Alignment.GRAPHEME_CLUSTER_END :
String cluster = rawDatum.substring(startpos, pos);
if (cluster.equals(graphemeCluster)) {
// save new vector
vector =
vector.substring(0, vectorpos)
+ vector.substring(vectorpos + 1, i)
+ vector.substring(i + 1);
// reset
i = (i >= 2) ? i - 2 : 0;
vectorpos = i;
undefine = true;
}
break;
default :
break;
}
}
// undefine
if (undefine) {
// update alignment vector
final String updateVector = new String(vector);
final long updateID = alignmentID;
getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "UPDATE_ALIGNMENT_VECTOR";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setString(1, updateVector);
stmt.setLong(2, updateID);
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
return null;
}
});
// untabulate group
Group group = new Group(getDatabase(), groupID, this, null);
group.revert();
group.retabulate();
undefine = false;
}
}
}
/**
* Get this view's groups for the given entry.
**/
public List getGroups(final Entry entry) throws DatabaseException {
return getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_GROUPS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
stmt.setLong(2, entry.getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
Group group = new Group(db, rs.getLong(1), View.this, entry);
group.updateObject(rs);
return group;
}
});
}
/**
* Get the group specified for given entry if it persists
* or create a new one if it doesn't.
**/
public Group getGroup(String name, Entry entry) throws DatabaseException {
List groups = getGroups(entry);
for (Iterator it = groups.iterator(); it.hasNext();) {
Group group = (Group) it.next();
if (group.getName().equals(name))
return group;
}
// create group
Group newGroup = makeGroup(entry);
newGroup.setName(name);
newGroup.save();
return newGroup;
}
/**
* Get this view's groups that pass threshold for the given entry.
**/
public List getThresholdGroups(final Entry entry) throws DatabaseException {
// get groups that meet or exceed threshold
List groups = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_THRESHOLD_GROUPS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
stmt.setLong(2, entry.getID());
stmt.setInt(3, getThresholdValue());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
Group group = new Group(db, rs.getLong(1), View.this, entry);
group.updateObject(rs);
return group;
}
});
return groups;
}
/**
* Get this view's groups that are below threshold requirements for the given entry.
**/
public List getBelowThresholdGroups(final Entry entry)
throws DatabaseException {
// get groups that are below the threshold
List groups = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_BELOW_THRESHOLD_GROUPS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
stmt.setLong(2, entry.getID());
stmt.setInt(3, getThresholdValue());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
Group group = new Group(db, rs.getLong(1), View.this, entry);
group.updateObject(rs);
return group;
}
});
return groups;
}
/**
* Get this view's groups that have been tabulated.
**/
public List getTabulatedGroups() throws DatabaseException {
// get groups that have been tabulated
List groups = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_TABULATED_GROUPS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
Entry entry = new Entry(db, rs.getLong(1), getCollection());
entry.updateObject(rs);
Group group = new Group(db, rs.getLong(5), View.this, entry);
group.setName(rs.getString(6));
group.setDone(rs.getInt(7) != 0);
return group;
}
});
return groups;
}
/**
* Get this view's tabulated groups that are above threshold.
**/
public List getTabulatedThresholdGroups() throws DatabaseException {
// get groups that have been tabulated
List groups = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_TABULATED_THRESHOLD_GROUPS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
Entry entry = new Entry(db, rs.getLong(1), getCollection());
entry.updateObject(rs);
Group group = new Group(db, rs.getLong(5), View.this, entry);
group.setName(rs.getString(6));
group.setDone(rs.getInt(7) != 0);
return group;
}
});
return groups;
}
/**
* Get this view's Frantz Strength group count. Defined as tabulated groups
* that are above threshold and associated with non-residue protosegments.
**/
public int getFrantzStrengthGroupCount() throws DatabaseException {
List count = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_FRANTZ_STRENGTH_GROUP_COUNT";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
return new Integer(rs.getInt(1));
}
});
return ((Integer) count.get(0)).intValue();
}
/**
* Get this view's groups for a cluster used for summary.
**/
public List getSummaryClusterGroups(
final Cluster cluster,
final double minFrantz,
final String displayFrantz)
throws DatabaseException {
// get groups that have been tabulated
List groups = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return displayFrantz.equals("Protosegment")
? "GET_SUMMARY_CLUSTER_GROUPS_BY_FRANTZ_PROTO"
: "GET_SUMMARY_CLUSTER_GROUPS_BY_FRANTZ_CLUSTER";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, cluster.getID());
stmt.setDouble(2, minFrantz);
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
Entry entry = new Entry(db, rs.getLong(1), getCollection());
entry.updateObject(rs);
Group group = new Group(db, rs.getLong(5), View.this, entry);
group.setName(rs.getString(6));
group.setDone(rs.getInt(7) != 0);
group.setReconstruction(rs.getString(8));
group.setFrantzCluster(rs.getDouble(9));
group.setFrantzProtosegment(rs.getDouble(10));
group.setAllCitationsWithResidue(rs.getInt(11) != 0);
return group;
}
});
return groups;
}
/**
* Get protosegment.
* @param protosegment id
**/
public Protosegment getProtosegment(final long id) throws DatabaseException {
List list = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "org.wordcorr.db.Protosegment.RETRIEVE";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, id);
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
try {
Zone zone = new Zone(db, rs.getLong(1));
zone.revert();
Protosegment proto = new Protosegment(db, rs.getLong(2), View.this, zone);
proto.updateObject(rs);
return proto;
} catch (DatabaseException e) {
throw new SQLException(e.getRootCause().getMessage());
}
}
});
return (list.isEmpty()) ? null : (Protosegment) list.get(0);
}
/**
* Get this view's protosegments.
**/
public List getProtosegments() throws DatabaseException {
return getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_PROTOSEGMENTS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
try {
Zone zone = new Zone(db, rs.getLong(1));
zone.revert();
Protosegment proto = new Protosegment(db, rs.getLong(2), View.this, zone);
proto.updateObject(rs);
return proto;
} catch (DatabaseException e) {
throw new SQLException(e.getRootCause().getMessage());
}
}
});
}
/**
* Get this view's unused protosegments.
**/
public List getUnusedProtosegments() throws DatabaseException {
return getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_UNUSED_PROTOSEGMENTS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
try {
Zone zone = new Zone(db, rs.getLong(1));
zone.revert();
Protosegment proto = new Protosegment(db, rs.getLong(2), View.this, zone);
proto.updateObject(rs);
return proto;
} catch (DatabaseException e) {
throw new SQLException(e.getRootCause().getMessage());
}
}
});
}
/**
* Get this view's protosegments.
**/
public List getRefineTable() throws DatabaseException {
return getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_REFINE_TABLE";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
Object[] objs =
{
rs.getString(1),
rs.getString(2),
rs.getString(3),
new Integer(rs.getInt(4)),
rs.getString(5),
rs.getString(6),
rs.getString(7),
rs.getString(8),
rs.getString(9),
rs.getString(10)};
return objs;
}
});
}
/**
* Get Groups Tabulated.
**/
public int getGroupsTabulated() throws DatabaseException {
List count = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_VIEW_GROUPS_TABULATED";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
return new Integer(rs.getInt(1));
}
});
return ((Integer) count.get(0)).intValue();
}
/**
* Get count of groups that are done.
**/
public int getGroupDoneCount(final Entry entry) throws DatabaseException {
List count = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_GROUP_DONE_COUNT";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
stmt.setLong(2, entry.getID());
}
public Object createObject(Database db, ResultSet rs) throws SQLException {
return new Integer(rs.getInt(1));
}
});
return ((Integer) count.get(0)).intValue();
}
/**
* Compute Frantz strenth for tabulated groups in view and update.
**/
public int updateFrantzStrength() throws DatabaseException {
int frantzN = getFrantzStrengthGroupCount();
List groups = getTabulatedThresholdGroups();
// N minimum set to 50
double n =
Math.rint(
((Math.log(((frantzN < 50) ? 50 : frantzN) / 100.) / Math.log(10.)) * 21) + 9);
for (Iterator it = groups.iterator(); it.hasNext();) {
Group group = (Group) it.next();
// init accumulators
int pcount = 0;
double acluster = 0.;
double aproto = 0.;
StringBuffer reconstruction = new StringBuffer();
boolean allCitationsWithResidue = true;
String grp = group.getEntry().getEntryNum() + group.getName();
// process each citation
for (Iterator itc = group.getCitations().iterator(); itc.hasNext();) {
Citation citation = (Citation) itc.next();
pcount++;
Cluster cluster = citation.getCorrespondenceSet().getCluster();
double ccluster = cluster.getCitationCount();
Protosegment proto = cluster.getProtosegment();
double cproto = proto.getCitationCount();
reconstruction.append(proto.getProtosegment());
acluster = getFrantzAccumulator(ccluster, acluster, n);
aproto = getFrantzAccumulator(cproto, aproto, n);
// check residue protosegments
if (!proto.getZone().getAbbreviation().equals("RES"))
allCitationsWithResidue = false;
}
if (pcount > 0) {
double frantzCluster = acluster / pcount;
double frantzProtosegment = aproto / pcount;
group.setReconstruction(reconstruction.toString());
group.setFrantzCluster(frantzCluster);
group.setFrantzProtosegment(frantzProtosegment);
group.setAllCitationsWithResidue(allCitationsWithResidue);
group.save();
}
}
return frantzN;
}
/**
* Compute Frantz strenth accumulator.
**/
private double getFrantzAccumulator(double c, double a, double n) {
double acc = a;
if (c >= n)
acc += 1.0;
if ((c < n) && (c > 2))
acc += c / n;
if (c == 2.)
acc -= 0.5;
if (c == 1.)
acc -= 1.0;
return acc;
}
/**
* Get element representing this view.
**/
public Element getElement() {
Element element = new Element("view");
// set attributes
element.setAttribute("view-name", getName());
Integer threshold = getThreshold();
element.setAttribute(
"threshold",
(threshold == null) ? "" : threshold.intValue() + "");
// set elements
element.addContent(createElement("remarks", getRemarks()));
// view members
int i = 0;
for (Iterator it = getMembers().iterator(); it.hasNext();) {
Variety variety = (Variety) it.next();
Element memberElem = new Element("view-member");
element.addContent(memberElem);
// set attributes
memberElem.setAttribute("short-name", variety.getShortName());
memberElem.setAttribute("order-number", ++i + "");
}
try {
// annotations
Element listElem = new Element("annotations");
element.addContent(listElem);
for (Iterator it = getCollection().getEntries().iterator(); it.hasNext();) {
Entry entry = (Entry) it.next();
for (Iterator it2 = getAlignments(entry).iterator(); it2.hasNext();) {
Alignment alignment = (Alignment) it2.next();
// skip records for unannotated datums
if (alignment.getGroup() != null)
listElem.addContent(alignment.getElement());
}
}
// results
listElem = new Element("results");
element.addContent(listElem);
for (Iterator it = getProtosegments().iterator(); it.hasNext();) {
Protosegment protosegment = (Protosegment) it.next();
listElem.addContent(protosegment.getElement());
}
// tabulated groups
listElem = new Element("tabulated-groups");
element.addContent(listElem);
for (Iterator it = getTabulatedGroups().iterator(); it.hasNext();) {
Group group = (Group) it.next();
listElem.addContent(group.getElement());
}
} catch (DatabaseException e) {
e.printStackTrace();
}
return element;
}
/**
* Get summary element representing this view.
**/
public Element getSummaryElement(
float minFrantz,
int maxReconstructions,
String displayFrantz,
boolean includeResidue,
String gloss) {
Element element = new Element("view");
// set attributes
element.setAttribute("view-name", getName());
Integer threshold = getThreshold();
element.setAttribute(
"threshold",
(threshold == null) ? "" : threshold.intValue() + "");
// set elements
element.addContent(createElement("remarks", getRemarks()));
// view members
int i = 0;
for (Iterator it = getMembers().iterator(); it.hasNext();) {
Variety variety = (Variety) it.next();
Element memberElem = new Element("view-member");
element.addContent(memberElem);
// set attributes
memberElem.setAttribute("name", variety.getName());
memberElem.setAttribute("short-name", variety.getShortName());
memberElem.setAttribute("abbreviation", variety.getAbbreviation());
memberElem.setAttribute("order-number", ++i + "");
}
try {
// protosegments
Element listElem = new Element("protosegments");
element.addContent(listElem);
for (Iterator it = getProtosegments().iterator(); it.hasNext();) {
Protosegment protosegment = (Protosegment) it.next();
// check residue protosegment
if (!includeResidue && protosegment.getZone().getAbbreviation().equals("RES"))
continue;
listElem.addContent(
protosegment.getSummaryElement(
this,
minFrantz,
maxReconstructions,
displayFrantz,
includeResidue,
gloss));
}
} catch (DatabaseException e) {
e.printStackTrace();
}
return element;
}
/**
* Mark this view as imported.
**/
public void markImported() {
_imported = true;
}
/**
* Make an Alignment object. This does not add anything to the
* database. The returned object must be saved to be made
* permanent.
**/
public Alignment makeAlignment(Datum datum) {
return new Alignment(getDatabase(), -1, this, datum);
}
/**
* Make a Group object. This does not add anything to the
* database. The returned object must be saved to be made
* permanent.
**/
public Group makeGroup(Entry entry) {
return new Group(getDatabase(), -1, this, entry);
}
/**
* Make an Protosegment object. This does not add anything to the
* database. The returned object must be saved to be made
* permanent.
**/
public Protosegment makeProtosegment(Zone zone) {
return new Protosegment(getDatabase(), -1, this, zone);
}
//---------------------------------------------------------------//
// Persistent Methods
//---------------------------------------------------------------//
/**
* Override of check validation prior to save.
* Return null of okay, message if not.
**/
public String checkValidation() throws DatabaseException {
// check for modification
if (!isDirty())
return null;
// check for duplicate name
if (getID() == UNDEFINED_ID) {
for (Iterator it = getCollection().getViews().iterator(); it.hasNext();) {
View vw = (View) it.next();
if (getName().equalsIgnoreCase(vw.getName()))
return AppPrefs.getInstance().getMessages().getCompoundMessage(
"msgViewDuplicateName",
getName());
}
}
// check for tabulation
if (getGroupsTabulated() > 0 && (_thresholdChanged || _varietiesChanged)) {
revert();
return AppPrefs.getInstance().getMessages().getString("msgViewTabulated");
} else if (_varieties.size() < 2) {
return AppPrefs.getInstance().getMessages().getString(
"msgViewMinimumVarieties");
}
return null;
}
/**
* Override of save to also create default protosegments and link members.
**/
public synchronized void save() throws DatabaseException {
boolean newObject = (getID() == UNDEFINED_ID) ? true : false;
super.save();
// now do the view linking
final List all = new ArrayList(_collection.getVarieties());
getDatabase().linkObjects(new LinkParameters() {
public String getRemoveSQLKey() {
return "REMOVE_VIEW_MEMBER";
}
public String getCreateSQLKey() {
return "ADD_VIEW_MEMBER";
}
public String getUpdateSQLKey() {
return "UPDATE_VIEW_MEMBER";
}
public void setRemoveParameters(PreparedStatement stmt, int index)
throws SQLException {
stmt.setLong(1, getID());
stmt.setLong(2, ((Variety) all.get(index)).getID());
}
public void setCreateParameters(PreparedStatement stmt, int index)
throws SQLException {
Variety variety = (Variety) all.get(index);
stmt.setLong(1, getID());
stmt.setLong(2, variety.getID());
stmt.setInt(3, _varieties.indexOf(variety));
}
public void setUpdateParameters(PreparedStatement stmt, int index)
throws SQLException {
Variety variety = (Variety) all.get(index);
stmt.setInt(1, _varieties.indexOf(variety));
stmt.setLong(2, getID());
stmt.setLong(3, variety.getID());
}
public int getLinkCount() {
return all.size();
}
public boolean isLinked(int index) {
return _varieties.contains(all.get(index));
}
});
resetChangeFlags();
}
/**
* Revert this object.
**/
public synchronized void revert() throws DatabaseException {
super.revert();
resetChangeFlags();
}
/**
* Clear the dirty flag.
**/
public void clearDirty() {
super.clearDirty();
resetChangeFlags();
}
/**
* Update the object based on a result set.
**/
public void updateObject(ResultSet rs) throws SQLException {
setName(rs.getString(2));
setThreshold(new Integer(rs.getInt(3)));
if (rs.wasNull()) {
setThreshold(null);
}
setRemarks(rs.getString(4));
// load the view members
try {
_varieties = getDatabase().retrieveObjects(new RetrieveAllParameters() {
public String getRetrieveAllSQLKey() {
return "GET_VIEW_MEMBERS";
}
public void setRetrieveAllParameters(PreparedStatement stmt)
throws SQLException {
stmt.setLong(1, getID());
}
public Object createObject(Database db, ResultSet rs2) throws SQLException {
Variety variety = new Variety(db, rs2.getLong(1), _collection);
variety.updateObject(rs2);
return variety;
}
});
} catch (DatabaseException e) {
e.printStackTrace();
throw new SQLException(e.getRootCause().getMessage());
}
}
/**
* Set parameters on the update statement.
**/
public void setUpdateParameters(PreparedStatement stmt) throws SQLException {
stmt.setString(1, getName());
if (getThreshold() == null) {
stmt.setNull(2, java.sql.Types.INTEGER);
} else {
stmt.setInt(2, getThreshold().intValue());
}
stmt.setString(3, getRemarks());
stmt.setLong(4, getID());
}
/**
* Set parameters on the create statement.
**/
public void setCreateParameters(PreparedStatement stmt) throws SQLException {
stmt.setString(1, getName());
if (getThreshold() == null) {
stmt.setNull(2, java.sql.Types.INTEGER);
} else {
stmt.setInt(2, getThreshold().intValue());
}
stmt.setString(3, getRemarks());
stmt.setLong(4, _collection.getID());
stmt.setLong(5, _collection.getUser().getID());
}
/**
* Generates object and all children from Element and saves in db.
**/
public void generateFromElement(
Element element,
Map varieties,
Map entries,
Map datumsByEntry)
throws DatabaseException {
if (element == null)
return;
// set values
setName(element.getAttributeValue("view-name"));
String threshold = element.getAttributeValue("threshold");
if (!threshold.equals(""))
setThreshold(new Integer(threshold));
setRemarks(element.getChildText("remarks"));
// view members
List members = new ArrayList();
for (Iterator it = element.getChildren("view-member").iterator();
it.hasNext();
) {
Element elem = (Element) it.next();
String[] member =
{ elem.getAttributeValue("order-number"), elem.getAttributeValue("short-name")};
members.add(member);
}
Collections.sort(members, new Comparator() {
public int compare(Object o1, Object o2) {
String[] m1 = (String[]) o1;
String[] m2 = (String[]) o2;
int i1 = Integer.parseInt(m1[0]);
int i2 = Integer.parseInt(m2[0]);
return i1 < i2 ? -1 : i1 > i2 ? 1 : 0;
}
});
// convert to variety
for (int i = 0; i < members.size(); i++) {
String[] member = (String[]) members.get(i);
members.set(i, varieties.get(member[1]));
}
setMembers(members);
markImported();
save();
// annotations
Map groups = new HashMap();
Element listElem = element.getChild("annotations");
for (Iterator it = listElem.getChildren("annotated-datum").iterator();
it.hasNext();
) {
Element elem = (Element) it.next();
// get or create group if new
String entryNumber = elem.getAttributeValue("entry-number");
String tag = elem.getAttributeValue("tag");
String groupKey = entryNumber + ":" + tag;
Group group = (Group) groups.get(groupKey);
if (group == null) {
Entry ent = (Entry) entries.get(entryNumber);
group = makeGroup((Entry) entries.get(entryNumber));
group.setName(tag);
group.save();
groups.put(groupKey, group);
}
// get datum
Map datums = (Map) datumsByEntry.get(elem.getAttributeValue("entry-number"));
Datum datum = (Datum) datums.get(elem.getAttributeValue("datum-number"));
// create alignment
Alignment alignment = makeAlignment(datum);
alignment.setGroup(group);
alignment.generateFromElement(elem);
}
// results
Set tabulatedGroups = new HashSet();
listElem = element.getChild("results");
for (Iterator it = listElem.getChildren("protosegment").iterator();
it.hasNext();
) {
Element elem = (Element) it.next();
// get zone
Zone zone =
getDatabase().getZone(
new Integer(elem.getAttributeValue("zone-row")),
new Integer(elem.getAttributeValue("zone-column")));
// create protosegment
Protosegment protosegment = makeProtosegment(zone);
protosegment.generateFromElement(elem, groups, tabulatedGroups);
}
// get remaining tabulated groups (below threshold)
listElem = element.getChild("tabulated-groups");
if (listElem != null)
for (Iterator it = listElem.getChildren("group").iterator(); it.hasNext();) {
Element elem = (Element) it.next();
// get group
String entryNumber = elem.getAttributeValue("entry-number");
String tag = elem.getAttributeValue("tag");
String groupKey = entryNumber + ":" + tag;
Group group = (Group) groups.get(groupKey);
// mark group as tabulated
tabulatedGroups.add(group);
}
// mark tabulated groups
for (Iterator it = tabulatedGroups.iterator(); it.hasNext();) {
Group group = (Group) it.next();
group.setDone(true);
group.save();
}
}
private boolean _imported = false;
private boolean _thresholdChanged = false;
private boolean _varietiesChanged = false;
private Integer _threshold;
private String _remarks;
private List _varieties = Collections.EMPTY_LIST;
private final WordCollection _collection;
}