%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ page import="org.crosswire.community.projects.ntmss.data.Apparatus" %>
<%@ page import="org.crosswire.community.projects.ntmss.data.Document" %>
<%@ page import="org.crosswire.community.projects.ntmss.data.Transcription" %>
<%@ page import="org.crosswire.community.projects.ntmss.data.Apparatus.Segment" %>
<%@ page import="org.crosswire.community.projects.ntmss.data.ProjectManagement" %>
<%@ page import="org.crosswire.webtools.RightsAndRoles" %>
<%@ page import="org.crosswire.utils.HTTPUtils" %>
<%@ page import="org.crosswire.sword.keys.VerseKey" %>
<%@ page import="org.crosswire.repo.VersionedRepo" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.Set" %>
<%@ page import="java.util.HashSet" %>
<%@ page import="java.util.HashMap" %>
<%@ page import="java.util.Map" %>
<%@ page import="java.util.Collections" %>
<%@ page import="java.util.Comparator" %>
<%@ page import="org.json.JSONObject" %>
<%@ page import="org.json.JSONArray" %>
<%@ page import="org.apache.commons.lang3.StringEscapeUtils" %>
<%@ page import="org.apache.log4j.Logger" %>
<%@ page import="javax.validation.constraints.NotNull" %>
<%@ page import="org.crosswire.xml.XMLBlock" %>
<%@ page import="org.crosswire.webtools.annotation.*" %>
<%@ page import="org.crosswire.webtools.*" %>
<%!
@Description(value = "Submit new or modified apparatus for a verse", name = "variant/apparatus/put")
public static class MyParameters extends Parameters {
@NotNull
@Description(value = "under which segment group (e.g., projectID) to save", example = "1")
public Integer segmentGroupID = null;
@NotNull
@Description(value = "(optional instead of segmentGroupID) under which project to save", example = "ECM Matthew")
public String projectName;
@NotNull
@Description(value = "which verse for which to save an apparatus", example = "John.3.16")
public String indexContent = null;
@Description(value = "limit approval data to a specified document", example = "40100")
public Integer docID = null;
@Description(value = "optional, data store key from where to retrieve the apparatus", example = "/collation/regularised/Matt.1.1")
public String dataPath = null;
@Override
protected void afterLoad() {
}
@Override
protected void customValidation() {
}
}
static Logger logger = Logger.getLogger("variant/apparatus/put");
%>
<%
MyParameters params = new MyParameters().loadFromRequest(request, response, false);
int segmentGroupID = -1; try {segmentGroupID = Integer.parseInt(request.getParameter("segmentGroupID"));} catch (Exception e){}
String projectName = Transcription.assureUnicode(request.getParameter("projectName"));
logger.info("variant/apparatus/put(segmentGroupID: " + segmentGroupID + "; indexContent: " + params.indexContent + "; projectName: " + projectName + "; dataPath: " + params.dataPath);
if ((segmentGroupID > -1 || projectName != null) && params.indexContent != null && params.dataPath != null) {
response.setContentType("text/xml");
ProjectManagement.Project pr = segmentGroupID > -1 ? ProjectManagement.getProject(segmentGroupID) : ProjectManagement.getProject(projectName);
segmentGroupID = pr.getProjectID();
if (pr == null) {
out.print("");
return;
}
String role="VMR Administrator";
String role2="Project Manager";
// let's check to see if we're a privileged user
boolean isAdmin = RightsAndRoles.hasRole(request, response, role);
if (!isAdmin) isAdmin = RightsAndRoles.hasRole(request, response, role2);
if (!isAdmin) isAdmin = RightsAndRoles.hasRole(request, response, "Site Administrator", pr.getProjectName());
if (isAdmin) {
List segments = new ArrayList();
// delete all existing segments for verse if we're not limited to a single docID
if (params.docID == null) {
segments = Apparatus.getSegments(params.indexContent, segmentGroupID);
for (Segment s : segments) {
Apparatus.Segment.deleteSegment(s.getSegmentID());
}
}
// else delete all existing witness instances for this segmentGroupID+verse+docID
else {
String v11n = null; // TODO: get project v11n; doc.getV11n();
VerseKey vk = new VerseKey();
vk.setIntros(true);
if (v11n != null) vk.setVersificationSystem(v11n);
vk.setText(params.indexContent);
Apparatus.SegmentReadingWitness.deleteSegmentReadingWitness(params.docID, segmentGroupID, vk.getHashNumber());
}
String path = pr.getProjectName() + "/";
if (!params.dataPath.endsWith("/")) params.dataPath += "/";
path += params.dataPath;
path += "primary.txt";
StringBuffer body = VersionedRepo.getFile(path, null, null, VersionedRepo.PATH_PROJECT);
if (body == null) {
out.print("");
return;
}
JSONObject json = new JSONObject(body.toString());
json = json.getJSONObject("structure");
JSONObject hands = json.getJSONObject("hand_id_map");
int segNum = 0;
List segs = new ArrayList();
for (int appNum = 1; true; ++appNum) {
JSONArray app = null; try { app = json.getJSONArray("apparatus"+(appNum > 1?appNum:"")); } catch (Exception e) {}
if (app == null) break;
for (int i = 0; i < app.length(); ++i) {
JSONObject s = app.getJSONObject(i);
segs.add(s);
}
}
Collections.sort(segs, new Comparator() {
@Override
public int compare(JSONObject o1, JSONObject o2) {
int start1 = -9999; try { start1 = o1.getInt("start"); } catch (Exception e) {}
int start2 = -9999; try { start2 = o2.getInt("start"); } catch (Exception e) {}
if (start1 != start2) return start1 < start2 ? -1 : 1;
int end1 = start1; try { end1 = o1.getInt("end"); } catch (Exception e) {}
int end2 = start2; try { end2 = o2.getInt("end"); } catch (Exception e) {}
return end1 == end2 ? 0 : end1 < end2 ? -1 : 1;
}
});
for (JSONObject s : segs) {
Segment segment = new Segment();
String v11n = null; // TODO: get project v11n; doc.getV11n();
VerseKey vk = new VerseKey();
vk.setIntros(true);
if (v11n != null) vk.setVersificationSystem(v11n);
vk.setText(params.indexContent);
segment.setVerseHash(vk.getHashNumber());
int start = s.getInt("start");
int end = s.getInt("end");
segment.setContextDescription(start==end?(""+start) : (""+start+"-"+end));
if (params.docID == null) {
segment = segment.saveNew(segmentGroupID);
++segNum;
}
else {
segment = Segment.getSegment(segmentGroupID, segment.getVerseHash(), segment.getContextDescription());
}
// assert we have a segment
if (segment == null) continue;
JSONArray read = s.getJSONArray("readings");
for (int j = 0; j < read.length(); ++j) {
JSONObject r = read.getJSONObject(j);
String readingText = HTTPUtils.canonize(StringEscapeUtils.unescapeHtml4(r.getString("text_string")));
boolean isOm = false; try { isOm = "om".equals(r.getString("type")); } catch(Exception e) {}
boolean isLac = false; try { isLac = "lac".equals(r.getString("type")); } catch(Exception e) {}
// TODO: combine both overlapped and deleted
boolean isOverlapped = false; try { isOverlapped = "overlapped".equals(r.getString("overlap_status")) || "deleted".equals(r.getString("overlap_status")); } catch(Exception e) {}
// skip overlapped and deleted entries, as they both are
// represented in subsequent apparatus(n) sections
// maybe should check "overlap_status" to be sure "deleted" or "overlapped"
// is not used in a different context
/*
if ("overlapped".equals(readingText)) {
continue;
}
*/
int segmentReadingID = 0;
String forEmptyTranscriptions = null;
String readingLabel = r.getString("label");
if (readingLabel.indexOf("/") > -1) {
forEmptyTranscriptions = readingText;
readingText = readingLabel;
readingLabel = "zw";
}
/* TODO: New?
if (params.docID == null) {
segmentReadingID = segment.addSegmentReading(isOverlapped ? "" : isOm ? "om." : readingText, readingLabel);
}
else {
Apparatus.SegmentReading sr = segment.getSegmentReading(readingLabel, isOverlapped ? "" : isOm ? "om." : readingText);
if (sr != null) segmentReadingID = sr.getSegmentReadingID();
}
*/
// first see if we have a reading already added which matches
Apparatus.SegmentReading sr = segment.getSegmentReading(readingLabel, isOverlapped ? "" : isOm ? "om." : readingText);
if (sr != null) segmentReadingID = sr.getSegmentReadingID();
// add reading if we don't have one
if (segmentReadingID == 0) {
// for now, skip adding new readings if we're re-processing a witness.
// if we don't do this, then we get readings added even if they don't contain the witness
// TODO: check if reading has our reprocessed witness and if so, then add
if (params.docID == null) {
segmentReadingID = segment.addSegmentReading(isOverlapped ? "" : isOm ? "om." : readingText, readingLabel);
}
}
// assert we have a segmentReadingID
// if (segmentReadingID <= 0) continue;
//
//logger.info("processing main reading: " + readingText + "...");
//
// process main (non-sub) reading r
processReadingWits(params, segmentGroupID, segment, segmentReadingID, hands, readingText, r, forEmptyTranscriptions);
JSONObject subreadingTypes = null; try { subreadingTypes = (JSONObject)r.getJSONObject("subreadings"); } catch(Exception e) {}
if (subreadingTypes != null) {
for (int l = 0; l < subreadingTypes.length(); ++l) {
JSONArray subreadingType = subreadingTypes.getJSONArray(subreadingTypes.names().getString(l));
for (int m = 0; m < subreadingType.length(); ++m) {
JSONObject subreading = subreadingType.getJSONObject(m);
// process subreading subreading
//logger.info("processing subreading: " + readingText + "...");
processReadingWits(params, segmentGroupID, segment, segmentReadingID, hands, readingText, subreading, forEmptyTranscriptions);
}
}
}
}
}
%>
<%
}
else {
%>
<%
}
return;
}
else params.format = "html";
Serializer.reportErrors(request, response, out, params, true);
%>
<%!
protected static class WitnessElements {
int docID = -1;
String hand = "";
String verseInstance = "";
int verseInstancePage = -1;
int verseInstancePageInstance = -1;
String baseSiglum = "";
}
/***
* this needs a comment
*/
static WitnessElements getWitnessElements(String witness, JSONObject hands) {
WitnessElements retVal = new WitnessElements();
try { retVal.docID = Integer.parseInt(hands.getString(witness)); } catch (Exception e) {}
if (retVal.docID == -1) return retVal;
// skip over all but the last segments separated by spaces
// this needs a comment
int handStart = witness.lastIndexOf(" ");
if (handStart < 0) handStart = 0;
handStart = witness.indexOf("-", handStart);
retVal.hand = (handStart > -1) ? witness.substring(handStart+1) : "";
// again, comment this. Why?
int verseInstanceStart = witness.lastIndexOf(" ");
if (verseInstanceStart < 0) verseInstanceStart = 0;
verseInstanceStart = witness.indexOf("+", verseInstanceStart);
if (verseInstanceStart > 0) retVal.verseInstance = (handStart > -1) ? witness.substring(verseInstanceStart+1, handStart) : witness.substring(verseInstanceStart+1);
// verse instance handling
if (!retVal.verseInstance.isEmpty()) {
String elements[] = retVal.verseInstance.split("\\.");
if (elements.length > 4) {
try {retVal.verseInstancePage = Integer.parseInt(elements[3].substring(1)); } catch (Exception e) {}
try {retVal.verseInstancePageInstance = Integer.parseInt(elements[4].substring(1)); } catch (Exception e) {}
}
}
retVal.baseSiglum = verseInstanceStart > 0 ? witness.substring(0, verseInstanceStart) : handStart > -1 ? witness.substring(handStart) : witness;
return retVal;
}
static Map handConversion = new HashMap() {{
put("firsthand", "");
put("corrector", "C");
put("corrector*", "C*");
put("corrector1", "C1");
put("corrector2", "C2");
put("corrector3", "C3");
put("corrector1a", "C1a");
put("corrector2a", "C2a");
put("corrector3a", "C3a");
put("corrector1b", "C1b");
put("corrector2b", "C2b");
put("corrector3b", "C3b");
}};
static void processReadingWits(MyParameters params, int segmentGroupID, Segment segment, int segmentReadingID, JSONObject hands, String readingText, JSONObject reading, String forEmptyTranscriptions) {
String subLabel = ""; try { subLabel = reading.getString("suffix"); } catch (Exception e) {}
JSONArray wits = null; try { wits = reading.getJSONArray("witnesses"); } catch (Exception e) {}
JSONArray siglaSuffix = null; try { siglaSuffix = reading.getJSONArray("suffixes"); } catch (Exception e) {}
JSONArray words = null; try { words = reading.getJSONArray("text"); } catch (Exception e) {}
JSONObject overrides = null; try { overrides = reading.getJSONObject("SR_text"); } catch (Exception e) {}
String subReadingText = null; if (!"".equals(subLabel)) try { subReadingText = HTTPUtils.canonize(StringEscapeUtils.unescapeHtml4(reading.getString("text_string"))); } catch (Exception e) {}
JSONArray witWords = null;
if (wits == null) return;
// convert from WCE text to transcription text
readingText = Transcription.getWCETranscriptionText(readingText);
if (subReadingText != null) {
subReadingText = Transcription.getWCETranscriptionText(subReadingText);
}
if (subLabel != null && subLabel.length() > 0) {
//params.getLogger().info("******** Subreading Text for "+subLabel+": " + subReadingText + "; wits.length: " + wits.length());
}
// process all original hands first (h == 0)
// then process all other hands (h == 1)
for (int h = 0; h < 2; ++h) {
for (int k = 0; k < wits.length(); ++k) {
boolean unsure = false;
boolean unsureMajor = false;
boolean omHap = false;
boolean omComAbbr = false;
// TODO: handle multiple verse instances
String verseInstance = "";
String witSubReadingText = subReadingText;
try {
String siglum = wits.getString(k);
WitnessElements we = getWitnessElements(siglum, hands);
String siglumSuffix = null;
try { if (siglaSuffix != null) siglumSuffix = siglaSuffix.getString(k); } catch (Exception e) {}
siglumSuffix = (siglumSuffix == null) ? "" : siglumSuffix.trim();
int docID = we.docID;
if (docID == -1) {
logger.info("Couldn't lookup witness in VMR: " + hands.getString(siglum));
continue;
}
// if we havve been asked to limit processing to a particular docID
// skip all docIDs which are not the docID we have been asked to process
if (params.docID != null && docID != params.docID) continue;
String hand = we.hand;
verseInstance = we.verseInstance;
if (we.verseInstancePage > -1) {
Set instances = new HashSet();
Iterator hk = hands.keys();
while (hk.hasNext()) {
String hkey = hk.next();
if (hkey.length() >= we.baseSiglum.length() && hkey.substring(0, we.baseSiglum.length()).equals(we.baseSiglum)) {
WitnessElements anotherInstance = getWitnessElements(hkey, hands);
instances.add(anotherInstance.verseInstancePage * 100L + anotherInstance.verseInstancePageInstance);
}
}
List sortedUniqueInstances = new ArrayList(instances);
java.util.Collections.sort(sortedUniqueInstances);
int indexOf = sortedUniqueInstances.indexOf(we.verseInstancePage * 100L + we.verseInstancePageInstance);
verseInstance = Integer.toString(indexOf+1);
}
// translate hands
hand = handConversion.getOrDefault(hand, hand);
/* what should we do with firsthandV???
if ("firsthandV".equals(hand)) {
hand = "";
unsure = true;
}
*/
//logger.info("processing siglum: " + siglum + "; docID: " + docID + "; hand: " + hand);
// process all original hands first
if (h == 0 && hand.length() > 0) continue;
if (h == 1 && hand.length() == 0) continue;
if (docID == 20001) {
logger.info("processing siglum: " + siglum + "; docID: " + docID + "; hand: " + hand);
}
String t = null;
witWords = null;
try {
JSONObject overrideWitness = overrides.getJSONObject(siglum);
if (overrideWitness != null) {
witWords = overrideWitness.getJSONArray("text");
}
}
catch (Exception e) {}
if (witWords == null) witWords = words;
if (witWords != null && witWords.length() > 0) {
t = "";
for (int m = 0; m < witWords.length(); ++m) {
try {
JSONObject word = witWords.getJSONObject(m);
JSONObject witword = word.getJSONObject(siglum);
if (witword != null) {
t += (HTTPUtils.canonize(StringEscapeUtils.unescapeHtml4(witword.getString("original"))) + " ");
}
}
catch (Exception e) {}
}
t = t.trim();
// convert from WCE text to transcription text
t = Transcription.getWCETranscriptionText(t);
//logger.info("siglum: " + siglum + ": " + t);
//
// First, have we been given text for empty transcriptions
if (forEmptyTranscriptions != null) {
if (t.length() == 0) t = forEmptyTranscriptions;
}
else {
if (readingText.equals(t)) t = null;
}
}
unsure = siglumSuffix.indexOf("V") > -1;
boolean regularized = siglumSuffix.indexOf("r") > -1;
boolean nonsense = siglumSuffix.indexOf("f") > -1;
boolean supplement = false;
// Check for supplement
if (Document.checkSupplement(docID, segment.getVerseHash())) {
siglumSuffix = "S" + siglumSuffix;
supplement = true;
}
// if our subreading text is simply our transcription text,
// then we don't need to supply subReadingText for this witness
// because subReadingText defaults to transcription text simply set to null to default to transcription
if (witSubReadingText != null) {
if (witSubReadingText.equals(t)) witSubReadingText = null;
//params.getLogger().info("******** Subreading Text for "+subLabel+ "; siglum: " + siglum + ": " + witSubReadingText);
}
// lets see if our siglumSuffix is already handled completely by our siglum modifiers
String checkSiglumSuffix = siglumSuffix;
if (supplement) checkSiglumSuffix = checkSiglumSuffix.replaceFirst("S", "");
if (regularized) checkSiglumSuffix = checkSiglumSuffix.replaceFirst("r", "");
if (unsure) checkSiglumSuffix = checkSiglumSuffix.replaceFirst("V", "");
if (nonsense) checkSiglumSuffix = checkSiglumSuffix.replaceFirst("f", "");
if (checkSiglumSuffix.trim().length() == 0) siglumSuffix = "";
// TODO: handle unsureMajor, omHap, omComAbbr
if (docID == 20001) {
logger.info("Apparatus.setSegmentReadingWitness(" + segment.getSegmentID() + ", " + docID + ", " + verseInstance + ", " + hand + ", " + segmentReadingID + ", " + unsure + ", " + unsureMajor + ", " + regularized + ", " + supplement + ", " + nonsense + ", " + omHap + ", " + omComAbbr + ", " + t + ", null," + subLabel + ", " + witSubReadingText + ", " + (hand.length() > 0) + ", " + siglumSuffix + ", " + null + ", " + segmentGroupID + ", " + false + ", " + params.getUser().getUserName() + ")");
}
Apparatus.setSegmentReadingWitness(segment.getSegmentID(), docID, verseInstance, hand, segmentReadingID, unsure, unsureMajor, regularized, supplement, nonsense, omHap, omComAbbr, t, null, subLabel, witSubReadingText, hand.length() > 0, siglumSuffix, null, segmentGroupID, false, params.getUser().getUserName());
}
catch (Exception e) { e.printStackTrace(); }
}
}
}
%>