<%@ 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(); } } } } %>