diff --git a/webapp/config/web.xml b/webapp/config/web.xml index 466bf0490..bbd3381eb 100644 --- a/webapp/config/web.xml +++ b/webapp/config/web.xml @@ -1085,6 +1085,26 @@ SparqlQuery /admin/sparqlquery + + + DummyVisClient + edu.cornell.mannlib.vitro.webapp.controller.visualization.DummyVisClientController + + + + DummyVisClient + /admin/dummyVisClient + + + + VisualizationController + edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController + + + + VisualizationController + /admin/visQuery + authtest diff --git a/webapp/lib/iText-5.0.2.jar b/webapp/lib/iText-5.0.2.jar new file mode 100644 index 000000000..ed9565316 Binary files /dev/null and b/webapp/lib/iText-5.0.2.jar differ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/SparqlQueryServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/SparqlQueryServlet.java index 1e3acc0c5..5868d70d2 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/SparqlQueryServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/SparqlQueryServlet.java @@ -417,7 +417,11 @@ public class SparqlQueryServlet extends BaseEditController { "PREFIX swrl: \n" + "PREFIX swrlb: \n" + "PREFIX vitro: \n"+ - "PREFIX vivo: \n"+ + "PREFIX vivo: \n" + + "PREFIX bibo: \n" + + "PREFIX foaf: \n" + + "PREFIX core: \n" + + "PREFIX aktp: \n"+ "#\n" + "# This query gets all range entities labels and types of a person\n"+ "# A query like this could be used to get enough info to create a display\n"+ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/DummyVisClientController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/DummyVisClientController.java new file mode 100644 index 000000000..413b80e7e --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/DummyVisClientController.java @@ -0,0 +1,136 @@ +package edu.cornell.mannlib.vitro.webapp.controller.visualization; + +/* +Copyright (c) 2010, Cornell University +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Cornell University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import java.io.IOException; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vedit.beans.LoginFormBean; +import edu.cornell.mannlib.vedit.controller.BaseEditController; +import edu.cornell.mannlib.vitro.webapp.beans.Portal; +import edu.cornell.mannlib.vitro.webapp.controller.Controllers; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; + +/** + * Services a sparql query. This will return a simple error message and a 501 if + * there is no jena Model. + * + * @author bdc34 + * + */ +public class DummyVisClientController extends BaseEditController { + + private static final long serialVersionUID = 1L; + + private static final Log log = LogFactory.getLog(DummyVisClientController.class.getName()); + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + this.doGet(request,response); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + super.doGet(request, response); + + VitroRequest vreq = handleLoginAuthentication(request, response); + prepareVisualizationQueryResponse(request, response, vreq); + + return; + } + + private void prepareVisualizationQueryResponse(HttpServletRequest request, + HttpServletResponse response, VitroRequest vreq) { + + Portal portal = vreq.getPortal(); + + RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); + request.setAttribute("bodyJsp", "/templates/visualization/dummy_vis_client.jsp"); + request.setAttribute("portalBean", portal); + request.setAttribute("title", "Dummy Visualization Client"); + request.setAttribute("scripts", "/templates/visualization/visualization_scripts.jsp"); + + try { + requestDispatcher.forward(request, response); + } catch (Exception e) { + log.error("EntityEditController could not forward to view."); + log.error(e.getMessage()); + log.error(e.getStackTrace()); + } + + } + + private VitroRequest handleLoginAuthentication(HttpServletRequest request, + HttpServletResponse response) throws IOException { + // This might not be required + /* + * why are there multiple places where the login is checked? shud be abtracted into + * new methoid? + * */ +// if( !checkLoginStatus(request, response) ) +// return null; + + VitroRequest vreq = new VitroRequest(request); + + Object obj = vreq.getSession().getAttribute("loginHandler"); + LoginFormBean loginHandler = null; + + if( obj != null && obj instanceof LoginFormBean ) + loginHandler = ((LoginFormBean)obj); + + + /* + * what is the speciality of 5 in the conditions? + * + if( loginHandler == null || + ! "authenticated".equalsIgnoreCase(loginHandler.getLoginStatus()) || + Integer.parseInt(loginHandler.getLoginRole()) <= 5 ){ + HttpSession session = request.getSession(true); + + session.setAttribute("postLoginRequest", + vreq.getRequestURI()+( vreq.getQueryString()!=null?('?' + vreq.getQueryString()):"" )); + String redirectURL = request.getContextPath() + Controllers.SITE_ADMIN + "?login=block"; + response.sendRedirect(redirectURL); + return null; + }*/ + return vreq; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java new file mode 100644 index 000000000..dcb8a6564 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/visualization/VisualizationController.java @@ -0,0 +1,295 @@ +package edu.cornell.mannlib.vitro.webapp.controller.visualization; + +/* +Copyright (c) 2010, Cornell University +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Cornell University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +import java.io.IOException; +import java.util.HashMap; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.query.DataSource; +import com.hp.hpl.jena.query.DatasetFactory; +import com.hp.hpl.jena.query.Syntax; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelMaker; +import com.hp.hpl.jena.sparql.resultset.ResultSetFormat; + +import edu.cornell.mannlib.vedit.beans.LoginFormBean; +import edu.cornell.mannlib.vedit.controller.BaseEditController; +import edu.cornell.mannlib.vitro.webapp.beans.Portal; +import edu.cornell.mannlib.vitro.webapp.controller.Controllers; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; + +/** + * Services a sparql query. This will return a simple error message and a 501 if + * there is no jena Model. + * + * @author bdc34 + * + */ +public class VisualizationController extends BaseEditController { + + private static final String VIS_TYPE_URL_HANDLE = "vis"; + + public static final String URL_ENCODING_SCHEME = "UTF-8"; + + private static final long serialVersionUID = 1L; + + private static final Log log = LogFactory.getLog(VisualizationController.class.getName()); + + protected static final Syntax SYNTAX = Syntax.syntaxARQ; + + protected static HashMap formatSymbols = new HashMap(); + static{ + formatSymbols.put( ResultSetFormat.syntaxXML.getSymbol(), ResultSetFormat.syntaxXML); + formatSymbols.put( ResultSetFormat.syntaxRDF_XML.getSymbol(), ResultSetFormat.syntaxRDF_XML); + formatSymbols.put( ResultSetFormat.syntaxRDF_N3.getSymbol(), ResultSetFormat.syntaxRDF_N3); + formatSymbols.put( ResultSetFormat.syntaxText.getSymbol() , ResultSetFormat.syntaxText); + formatSymbols.put( ResultSetFormat.syntaxJSON.getSymbol() , ResultSetFormat.syntaxJSON); + formatSymbols.put( "vitro:csv", null); + } + + protected static HashMap rdfFormatSymbols = new HashMap(); + static { + rdfFormatSymbols.put( "RDF/XML", "application/rdf+xml" ); + rdfFormatSymbols.put( "RDF/XML-ABBREV", "application/rdf+xml" ); + rdfFormatSymbols.put( "N3", "text/n3" ); + rdfFormatSymbols.put( "N-TRIPLE", "text/plain" ); + rdfFormatSymbols.put( "TTL", "application/x-turtle" ); + } + + protected static HashMap mimeTypes = new HashMap(); + static{ + mimeTypes.put( ResultSetFormat.syntaxXML.getSymbol() , "text/xml" ); + mimeTypes.put( ResultSetFormat.syntaxRDF_XML.getSymbol(), "application/rdf+xml" ); + mimeTypes.put( ResultSetFormat.syntaxRDF_N3.getSymbol(), "text/plain" ); + mimeTypes.put( ResultSetFormat.syntaxText.getSymbol() , "text/plain"); + mimeTypes.put( ResultSetFormat.syntaxJSON.getSymbol(), "application/javascript" ); + mimeTypes.put( "vitro:csv", "text/csv"); + } + + public static final String PERSON_PUBLICATION_COUNT_VIS_URL_VALUE + = "person_pub_count"; + + public static final String PDF_REPORT_VIS_URL_VALUE + = "pdf_report"; + + + public static final String COLLEGE_PUBLICATION_COUNT_VIS_URL_VALUE + = "college_pub_count"; + + + @Override + protected void doPost(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + this.doGet(request,response); + } + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + super.doGet(request, response); + + VitroRequest vreq = handleLoginAuthentication(request, response); + + + if (PERSON_PUBLICATION_COUNT_VIS_URL_VALUE + .equalsIgnoreCase(vreq.getParameter(VIS_TYPE_URL_HANDLE))) { + + edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationRequestHandler visRequestHandler = + new edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationRequestHandler(vreq, request, response, log); + + String rdfResultFormatParam = "RDF/XML-ABBREV"; + + DataSource dataSource = setupJENADataSource(request, + response, + vreq, + rdfResultFormatParam); + + if (dataSource != null) { + + /* + * This is side-effecting because the visualization content is added + * to the request object. + * */ + visRequestHandler.generateVisualization(dataSource); + + } else { + + log.error("ERROR! Data Model Empty"); + } + + } else if (COLLEGE_PUBLICATION_COUNT_VIS_URL_VALUE + .equalsIgnoreCase(vreq.getParameter(VIS_TYPE_URL_HANDLE))) { + + edu.cornell.mannlib.vitro.webapp.visualization.collegepubcount.VisualizationRequestHandler visRequestHandler = + new edu.cornell.mannlib.vitro.webapp.visualization.collegepubcount.VisualizationRequestHandler(vreq, request, response, log); + + String rdfResultFormatParam = "RDF/XML-ABBREV"; + + DataSource dataSource = setupJENADataSource(request, + response, + vreq, + rdfResultFormatParam); + + if (dataSource != null) { + + /* + * This is side-effecting because the visualization content is added + * to the request object. + * */ + visRequestHandler.generateVisualization(dataSource); + + } else { + log.error("ERROR! data model empoty"); + } + + } else if (PDF_REPORT_VIS_URL_VALUE + .equalsIgnoreCase(vreq.getParameter(VIS_TYPE_URL_HANDLE))) { + + } else { + + log.debug("vis uqery parameter value -> " + vreq.getParameter("vis")); + log.debug("uri uqery parameter value -> " + vreq.getParameter("uri")); + log.debug("render_mode query parameter value -> " + vreq.getParameter("render_mode")); + + /* + * This is side-effecting because the error content is directly + * added to the request object. From where it is redirected to + * the error page. + * */ + handleMalformedParameters("Inappropriate query parameters were submitted. ", request, response); + } + + return; + } + + private VitroRequest handleLoginAuthentication(HttpServletRequest request, + HttpServletResponse response) throws IOException { + // This might not be required + /* + * why are there multiple places where the login is checked? shud be abtracted into + * new methoid? + * */ +// if( !checkLoginStatus(request, response) ) +// return null; + + VitroRequest vreq = new VitroRequest(request); + + Object obj = vreq.getSession().getAttribute("loginHandler"); + LoginFormBean loginHandler = null; + + + if( obj != null && obj instanceof LoginFormBean ) + loginHandler = ((LoginFormBean)obj); + + /* + * what is the speciality of 5 in the conditions? + * + if( loginHandler == null || + ! "authenticated".equalsIgnoreCase(loginHandler.getLoginStatus()) || + Integer.parseInt(loginHandler.getLoginRole()) <= 5 ){ + HttpSession session = request.getSession(true); + + session.setAttribute("postLoginRequest", + vreq.getRequestURI()+( vreq.getQueryString()!=null?('?' + vreq.getQueryString()):"" )); + String redirectURL = request.getContextPath() + Controllers.SITE_ADMIN + "?login=block"; + response.sendRedirect(redirectURL); + return null; + } + */ + return vreq; + } + + private DataSource setupJENADataSource(HttpServletRequest request, + HttpServletResponse response, VitroRequest vreq, + String rdfResultFormatParam) { + + Model model = vreq.getJenaOntModel(); // getModel() + if( model == null ){ + doNoModelInContext(request,response); + return null; + } + + log.debug("rdfResultFormat was: " + rdfResultFormatParam); + + DataSource dataSource = DatasetFactory.create() ; + ModelMaker maker = (ModelMaker) getServletContext().getAttribute("vitroJenaModelMaker"); + + dataSource.setDefaultModel(model) ; + + return dataSource; + } + + private void doNoModelInContext(HttpServletRequest request, HttpServletResponse res){ + try { + res.setStatus(HttpServletResponse.SC_NOT_IMPLEMENTED); + ServletOutputStream sos = res.getOutputStream(); + sos.println("this service is not supporeted by the current " + + "webapp configuration. A jena model is required in the servlet context." ); + } catch (IOException e) { + log.error("Could not write to ServletOutputStream"); + } + } + + + private void handleMalformedParameters(String errorMessage, HttpServletRequest request, + HttpServletResponse response) + throws ServletException, IOException { + + VitroRequest vreq = new VitroRequest(request); + Portal portal = vreq.getPortal(); + + request.setAttribute("error", errorMessage); + + RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); + request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp"); + request.setAttribute("portalBean", portal); + request.setAttribute("title", "Visualization Query Error"); + + try { + requestDispatcher.forward(request, response); + } catch (Exception e) { + log.error("EntityEditController could not forward to view."); + log.error(e.getMessage()); + log.error(e.getStackTrace()); + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/PDFDocument.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/PDFDocument.java new file mode 100644 index 000000000..1fca6b138 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/PDFDocument.java @@ -0,0 +1,295 @@ +package edu.cornell.mannlib.vitro.webapp.visualization; + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Stroke; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; +import java.util.Map.Entry; + +import com.itextpdf.text.BadElementException; +import com.itextpdf.text.BaseColor; +import com.itextpdf.text.Chunk; +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.Element; +import com.itextpdf.text.Font; +import com.itextpdf.text.FontFactory; +import com.itextpdf.text.Image; +import com.itextpdf.text.Paragraph; +import com.itextpdf.text.Phrase; +import com.itextpdf.text.pdf.ColumnText; +import com.itextpdf.text.pdf.PdfContentByte; +import com.itextpdf.text.pdf.PdfGState; +import com.itextpdf.text.pdf.PdfPCell; +import com.itextpdf.text.pdf.PdfPTable; +import com.itextpdf.text.pdf.PdfWriter; + +public class PDFDocument{ + + + static Stroke stroke = new BasicStroke(5.f, BasicStroke.CAP_ROUND, + BasicStroke.JOIN_ROUND); + + final static Color bg = Color.green; + + final static Color fg = Color.black; + + public PDFDocument(String authorName, + Map yearToPublicationCount, + Document document, + PdfWriter pdfWriter) { + +// setPreferredSize(new Dimension(600,400)); + + try { + + document.addTitle("PDF Pipeline iText Prototype"); + document.addAuthor(authorName); + document.addSubject("This example tests text, color, image, transparency & table functionality."); + document.addKeywords("text, color, image, transparency, table"); + document.addCreator("Standalone PDF Renderer using iText"); + + Paragraph header = new Paragraph(); + + Font pageHeaderStyle = FontFactory.getFont(FontFactory.TIMES_ROMAN, 15, Font.BOLDITALIC | Font.UNDERLINE); + Font featureHeaderStyle = FontFactory.getFont(FontFactory.TIMES_ROMAN, 10, new BaseColor(Color.red)); + + header.add(new Chunk("PDF Pipeline Prototype v2 using iText\n", + pageHeaderStyle)); + + header.setSpacingAfter(15f); + + + document.add(header); + + + Paragraph content = new Paragraph(); + + content.add(new Chunk("Publication Count - Author Name - " + authorName, + featureHeaderStyle)); + + content.setSpacingAfter(15f); + + document.add(content); + // step4 + + PdfPTable publicationCount = createTable(yearToPublicationCount); + + document.add(publicationCount); + + content = new Paragraph(); + + content.add(new Chunk("Transparency of Shapes", + featureHeaderStyle)); + + content.setSpacingAfter(15f); + + document.add(content); + + createTransparencyShapes(document, pdfWriter); + + + createImage(document, pdfWriter, featureHeaderStyle); + + } catch (DocumentException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } + + + private void createImage(Document document, PdfWriter writer, + Font featureHeaderStyle) throws BadElementException, + MalformedURLException, IOException, DocumentException { + Image imageSprite = Image.getInstance(new URL("http://lh3.ggpht.com/_4msVPAgKJv8/SCRYD-pPVKI/AAAAAAAAAYU/zUN963EPoZc/s1024/102_0609.JPG")); + imageSprite.setAbsolutePosition(400, 500); + imageSprite.scaleAbsolute(171.0f, 250.0f); + float imageSpriteY = document.getPageSize().getHeight() * 0.60f; + float imageSpriteX = document.getPageSize().getWidth() * 0.65f; + imageSprite.setAlignment(Image.UNDERLYING); + + document.add(imageSprite); + + PdfContentByte cb = writer.getDirectContent(); + ColumnText ct = new ColumnText(cb); + Chunk imageHeader = new Chunk("Images", + featureHeaderStyle); + ct.addText(imageHeader); + ct.setAlignment(Element.ALIGN_LEFT); + ct.setSimpleColumn(imageSpriteX, imageSpriteY - imageSprite.getScaledHeight(), + imageSpriteX + imageSprite.getScaledWidth(), imageSpriteY + imageSprite.getScaledHeight() + 20); + ct.go(); + + ct = new ColumnText(cb); + Chunk imageFooter = new Chunk("Footer to be set for a figure. Similar to 'image cpation'.", + FontFactory.getFont(FontFactory.TIMES_ROMAN, 8)); + ct.addText(imageFooter); + ct.setAlignment(Element.ALIGN_CENTER); + ct.setSimpleColumn(imageSpriteX, imageSpriteY - 150, imageSpriteX + imageSprite.getScaledWidth(), imageSpriteY); + ct.go(); + } + + private void createTransparencyShapes(Document document, + PdfWriter writer) throws Exception { + PdfContentByte cb = writer.getDirectContent(); + + pictureBackdrop(document.leftMargin(), 350, cb); + cb.saveState(); + PdfGState gs1 = new PdfGState(); + gs1.setFillOpacity(0.5f); + cb.setGState(gs1); + pictureCircles(document.leftMargin(), 350, cb); + cb.restoreState(); + + cb.resetRGBColorFill(); + } + + /** + * Prints a square and fills half of it with a gray rectangle. + * @param x + * @param y + * @param cb + * @throws Exception + */ + public void pictureBackdrop(float x, float y, PdfContentByte cb) throws Exception { + cb.setColorStroke(new BaseColor(Color.black)); + cb.setColorFill(new BaseColor(Color.gray)); + cb.rectangle(x, y, 100, 200); + cb.fill(); + cb.setLineWidth(2); + cb.rectangle(x, y, 200, 200); + cb.stroke(); + } + + /** + * Prints 3 circles in different colors that intersect with eachother. + * @param x + * @param y + * @param cb + * @throws Exception + */ + public void pictureCircles(float x, float y, PdfContentByte cb) throws Exception { + + cb.saveState(); + PdfGState gs1 = new PdfGState(); + gs1.setFillOpacity(1.0f); + cb.setGState(gs1); + cb.setColorFill(new BaseColor(Color.red)); + cb.circle(x + 70, y + 70, 50); + cb.fill(); + cb.restoreState(); + + cb.setColorFill(new BaseColor(Color.yellow)); + cb.circle(x + 100, y + 130, 50); + cb.fill(); + cb.setColorFill(new BaseColor(Color.blue)); + cb.circle(x + 130, y + 70, 50); + cb.fill(); + } + + private PdfPTable createTable(Map yearToPublicationCount) { + + Font normalContentStyle = FontFactory.getFont(FontFactory.TIMES_ROMAN, 11); + Font summaryContentStyle = FontFactory.getFont(FontFactory.TIMES_ROMAN, 11, Font.BOLDITALIC); + BaseColor summaryBackgroundColor = new BaseColor(0xEE, 0xEE, 0xEE); + BaseColor headerBackgroundColor = new BaseColor(0xC3, 0xD9, 0xFF); + BaseColor bodyBackgroundColor = new BaseColor(Color.white); + + PdfPTable table = new PdfPTable(2); + table.setWidthPercentage(36.0f); + + table.setHorizontalAlignment(Element.ALIGN_LEFT); + table.getDefaultCell().setBorderWidth(0.0f); + table.setHeaderRows(2); + + PdfPCell cell; + cell = new PdfPCell(new Phrase("Publications per year", normalContentStyle)); + setTableCaptionStyle(summaryBackgroundColor, cell); + table.addCell(cell); + + cell = new PdfPCell(new Phrase("Year", normalContentStyle)); + setTableHeaderStyle(headerBackgroundColor, cell); + table.addCell(cell); + + cell.setPhrase(new Phrase("Publications", normalContentStyle)); + table.addCell(cell); + + + + setTableBodyStyle(bodyBackgroundColor, cell); + int totalPublications = 0; + + for (Entry currentEntry : yearToPublicationCount.entrySet()) { + + cell.setPhrase(new Phrase(currentEntry.getKey(), normalContentStyle)); + table.addCell(cell); + + cell.setPhrase(new Phrase(currentEntry.getValue().toString(), normalContentStyle)); + table.addCell(cell); + + totalPublications += currentEntry.getValue(); + } + + setTableFooterStyle(summaryBackgroundColor, cell); + cell.setPhrase(new Phrase("Total", summaryContentStyle)); + table.addCell(cell); + + cell.setPhrase(new Phrase(String.valueOf(totalPublications), summaryContentStyle)); + table.addCell(cell); + + return table; + } + + private void setTableFooterStyle(BaseColor footerBackgroundColor, + PdfPCell cell) { + cell.setBorderWidth(0.0f); + cell.setBackgroundColor(footerBackgroundColor); + cell.setHorizontalAlignment(Element.ALIGN_CENTER); + cell.setPaddingTop(5f); + cell.setPaddingRight(10f); + cell.setPaddingBottom(5f); + cell.setPaddingLeft(10f); + } + + private void setTableBodyStyle(BaseColor bodyBackgroundColor, + PdfPCell cell) { + cell.setBorderWidth(0.0f); + cell.setBackgroundColor(bodyBackgroundColor); + cell.setHorizontalAlignment(Element.ALIGN_CENTER); + cell.setPaddingTop(5f); + cell.setPaddingRight(10f); + cell.setPaddingBottom(5f); + cell.setPaddingLeft(10f); + } + + private void setTableHeaderStyle(BaseColor headerBackgroundColor, + PdfPCell cell) { + cell.setBorderWidth(0.0f); + cell.setBackgroundColor(headerBackgroundColor); + cell.setHorizontalAlignment(Element.ALIGN_CENTER); + cell.setPaddingTop(5f); + cell.setPaddingRight(10f); + cell.setPaddingBottom(5f); + cell.setPaddingLeft(10f); + } + + private void setTableCaptionStyle(BaseColor summaryBackgroundColor, + PdfPCell cell) { + cell.setBorderWidth(0.0f); + cell.setBackgroundColor(summaryBackgroundColor); + cell.setHorizontalAlignment(Element.ALIGN_CENTER); + cell.setPaddingTop(5.0f); + cell.setPaddingRight(10.0f); + cell.setPaddingBottom(5.0f); + cell.setPaddingLeft(10.0f); + cell.setColspan(2); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/TestJava.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/TestJava.java new file mode 100644 index 000000000..97966b4d7 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/TestJava.java @@ -0,0 +1,86 @@ +package edu.cornell.mannlib.vitro.webapp.visualization; + +import java.util.Map; +import java.util.TreeMap; + +import com.hp.hpl.jena.iri.IRIFactory; + +public class TestJava { + + /** + * @param args + */ + public static void main(String[] args) { + String uriStr = "http%3A%2F%2Fvivo.library.cornell.edu%2Fns%2F0.1%23individual8588"; + IRIFactory factory = IRIFactory.jenaImplementation(); + + String[] sampleBlurns = {"Gold, J R [Reprint Author, Author]; Perkins, G A; Erb, H N; Ainsworth, D M | Journal of Veterinary Internal Medicine, 2006; 20(3): 720", + "Goldstein, Richard E; Lin, Rebecca C; Langston, Catherine E; Scrivani, Peter V; Erb, Hollis N; Barr, Stephen C | Journal of Veterinary Internal Medicine, 2006; 20(3): 489-494", + "McClellan, Jennifer M; Goldstein, Richard E; Erb, Hollis N; Dykes, Ned L; Cowgill, Larry D | American Journal of Veterinary Research, 2006; 67(4): 715-722", + "Cook, Christopher P; Scott, Danny W; Erb, Hollis N; Miller, William H | Vet Dermatol. 2005; 16(1): 47-51", + "Estrada, Amara; Moise, N Sydney; Erb, Hollis N; McDonough, Sean P; Renaud, Farrell, Shari | Journal of Veterinary Internal Medicine, 2006; 20(4): 862-872", + "Aguirre, A L [Reprint Author, Author]; Center, S A; Yeager, A E; Randolph, J F; Erb, H N | Journal of Veterinary Internal Medicine, 2006; 20(3): 787-788", + "MacLeod, K D; Scott, D W; Erb, H N | Journal of Veterinary Medicine Series A, 2004; 51(9-10): 400-404", + "Bailey, Dennis B; Rassnick, Kenneth M; Erb, Hollis N; Dykes, Nathan L; Hoopes, P Jack; Page, Rodney L | American Journal of Veterinary Research, 2004; 65(11): 1502-1507", + "Ainsworth, Dorothy M; Wagner, Bettina; Franchini, Marco; Grunig, Gabriele; Erb, Hollis N; Tan, Jean Yin | American Journal of Veterinary Research, 2006; 67(4): 669-677", + "Page, Richard B; Scrivani, Peter V; Dykes, Nathan L; Erb, Hollis N; Hobbs, Jeff M | Veterinary Radiology and Ultrasound, 2006; 47(2): 206-211", + "Scrivani, Peter V; Dykes, Nathan L; Erb, Hollis N | Veterinary Radiology and Ultrasound, 2004; 45(5): 419-423", + "Sepesy, Lisa M; Center, Sharon A; Randolph, John F; Warner, Karen L; Erb, Hollis N | Journal of the American Veterinary Medical Association, 2006; 229(2): 246-252", + "Dereszynski, D [Reprint Author, Author]; Center, S; Hadden, A; Randolph, J; Brooks, M; Palyada, K; McDonough, S; Messick, J; Bischoff, K; Erb, H; Gluckman, S; Sanders, S | Journal of Veterinary Internal Medicine, 2006; 20(3): 751-752", + "Kroll, Tracy L; Houpt, Katherine A; Erb, Hollis N | Journal of the American Animal Hospital Association, 2004; 40(1): 13-19", + "Fortier, Lisa A; Gregg, Abigail J; Erb, Hollis N; Fubini, Susan L | Vet Surg. 33(6): 661-7", + "Wagner, Bettina; Flaminio, Julia B F; Hillegas, Julie; Leibold, Wolfgang; Erb, Hollis N; Antczak, Douglas F | Veterinary Immunology and Immunopathology, 2006; 110(3-4): 269-278", + "Chalmers, H J; Scrivani, Peter V; Dykes, Nathan L; Erb, Hollis N; Hobbs, J M; Hubble, Lorna J | Veterinary Radiology and Ultrasound, 2006; 47(5): 507-509", + "Center, Sharon A; Warner, Karen L; McCabe, Jennifer; Foureman, Polly; Hoffmann, Walter E; Erb, Hollis N | Am J Vet Res. 2005; 66(2): 330-41"}; + + System.out.println(sampleBlurns); + for (String blurb : sampleBlurns) { + + System.out.println(blurb); + } + Map yearToPublicationCount = new TreeMap(); + + yearToPublicationCount.put("2003", 5); + yearToPublicationCount.put("2001", 5); + yearToPublicationCount.put("2002", 5); + yearToPublicationCount.put("2090", 7); + yearToPublicationCount.put("2087", 6); + +// System.out.println(Collections.max(yearToPublicationCount.keySet())); +// System.out.println(Collections.min(yearToPublicationCount.keySet())); + +// yearToPublicationCount.put("2087", testIt(5, yearToPublicationCount.get("2087"))); + +// try { +// factory.setEncoding("HEX"); +// } catch (UnsupportedEncodingException e) { +// // TODO Auto-generated catch block +// e.printStackTrace(); +// } + + + /* + IRI iri = factory.create(uriStr); + + + + if (iri.hasViolation(false) ) { + boolean validURI = false; + String errorMsg = ((Violation)iri.violations(false).next()).getShortMessage()+" "; + System.out.println("MURDER!!!!!" + errorMsg); + + } else { + System.out.println(iri.hasViolation(true)); + + }*/ + + + } + + private static Integer testIt(int i, Integer integer) { +// System.out.println("testit - " + i + " --- " + integer); + + return 10; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/VisualizationCodeGenerator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/VisualizationCodeGenerator.java new file mode 100644 index 000000000..90f4e4b2a --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/VisualizationCodeGenerator.java @@ -0,0 +1,442 @@ +package edu.cornell.mannlib.vitro.webapp.visualization; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.util.Calendar; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.Map.Entry; + +import org.apache.commons.logging.Log; + +import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationController; +import edu.cornell.mannlib.vitro.webapp.visualization.personpubcount.VisualizationRequestHandler; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; + + +public class VisualizationCodeGenerator { + + private final static Map visDivNames = new HashMap() {{ + + put("SHORT_SPARK", "pub_count_short_sparkline_vis"); + put("FULL_SPARK", "pub_count_full_sparkline_vis"); + + }}; + + private static final String visualizationStyleClass = "sparkline_style"; + + private static final String defaultVisContainerDivID = "vis_container"; + + private static final String SHORT_SPARKLINE_MODE_URL_HANDLE = "short"; + + private static final String FULL_SPARKLINE_MODE_URL_HANDLE = "full"; + + private Map yearToPublicationCount; + + private Log log; + + public VisualizationCodeGenerator(Map yearToPublicationCount, Log log) { + this.yearToPublicationCount = yearToPublicationCount; + this.log = log; + } + public String getMainVisualizationCode(List authorDocuments, + Set publishedYears, + String visMode, + String providedVisContainerID) { + + int numOfYearsToBeRendered = 0; + int currentYear = Calendar.getInstance().get(Calendar.YEAR); + int shortSparkMinYear = currentYear - 10 + 1; + + /* + * We are setting the default value of minPublishedYear to be 10 years before + * the current year (which is suitably represented by the shortSparkMinYear), + * this in case we run into invalid set of published years. + * */ + int minPublishedYear = shortSparkMinYear; + + String visContainerID = null; + + StringBuilder visualizationCode = new StringBuilder(); + +// System.out.println(yearToPublicationCount); + if (yearToPublicationCount.size() > 0) { + try { + minPublishedYear = Integer.parseInt(Collections.min(publishedYears)); + } catch (NoSuchElementException e1) { + log.debug("vis: " + e1.getMessage() + " error occurred for " + yearToPublicationCount.toString()); + } catch (NumberFormatException e2) { + log.debug("vis: " + e2.getMessage() + " error occurred for " + yearToPublicationCount.toString()); + } + numOfYearsToBeRendered = currentYear - minPublishedYear + 1; + } + + visualizationCode.append("\n"); + + visualizationCode.append("\n"; + } + + public String getVisualizationContextCode(String uri, String individualURI, String visMode) { + + String visualizationContextCode = ""; + if (SHORT_SPARKLINE_MODE_URL_HANDLE.equalsIgnoreCase(visMode)) { + visualizationContextCode = generateShortVisContext(uri, individualURI); + } else { + visualizationContextCode = generateFullVisContext(uri, individualURI); + } + + + + + + +// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + log.debug(visualizationContextCode); +// System.out.println("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); + + return visualizationContextCode; + } + + private String generateFullVisContext(String uri, + String individualURI) { + + StringBuilder divContextCode = new StringBuilder(); + + try { + + String downloadFileCode; + if (yearToPublicationCount.size() > 0) { + downloadFileCode = "Download data as .csv file.
"; + } else { + downloadFileCode = "No data available to export.
"; + + } + + divContextCode.append("

" + generateDataTable() + + downloadFileCode + "

"); + + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + return divContextCode.toString(); + + } + + + private String generateShortVisContext(String uri, + String individualURI) { + + StringBuilder divContextCode = new StringBuilder(); + + try { + + String fullTimelineLink; + if (yearToPublicationCount.size() > 0) { + fullTimelineLink = "View full timeline and network.
"; + } else { + fullTimelineLink = "No data available to render full timeline.
"; + + } + + divContextCode.append("

" + fullTimelineLink + "

"); + + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + + return divContextCode.toString(); + + } + + + private String generateDataTable() { + + StringBuilder dataTable = new StringBuilder(); + + dataTable.append("" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""); + + for (Entry currentEntry : yearToPublicationCount.entrySet()) { + dataTable.append("" + + "" + + "" + + ""); + } + + dataTable.append("\n" + + "" + +// "" + +// "" + +// "\n" + + "
Publications per year
YearPublications
" + currentEntry.getKey() + "" + currentEntry.getValue() + "
*DNA - Data not available
\n"); + + + return dataTable.toString(); + } + + + + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/QueryHandler.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/QueryHandler.java new file mode 100644 index 000000000..532ca311e --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/QueryHandler.java @@ -0,0 +1,366 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.collegepubcount; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; + +import com.hp.hpl.jena.iri.IRI; +import com.hp.hpl.jena.iri.IRIFactory; +import com.hp.hpl.jena.iri.Violation; +import com.hp.hpl.jena.query.DataSource; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.ResultSet; +import com.hp.hpl.jena.query.Syntax; +import com.hp.hpl.jena.rdf.model.RDFNode; + +import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; +import edu.cornell.mannlib.vitro.webapp.visualization.sparqlutils.QueryConstants; +import edu.cornell.mannlib.vitro.webapp.visualization.sparqlutils.QueryFieldLabels; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoCollegeOrSchool; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoDepartmentOrDivision; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoEmployee; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VOConstants.EmployeeType; + + + +/** + * Very dumb name of the class. change it. + * @author cdtank + * + */ +public class QueryHandler { + + protected static final Syntax SYNTAX = Syntax.syntaxARQ; + + private String collegeURIParam, resultFormatParam, rdfResultFormatParam; + private Map collegeURLToVO = new HashMap(); + private DataSource dataSource; + + private Log log; + + public QueryHandler(String collegeURIParam, + String resultFormatParam, String rdfResultFormatParam, + DataSource dataSource, Log log) { + + this.collegeURIParam = collegeURIParam; + this.resultFormatParam = resultFormatParam; + this.rdfResultFormatParam = rdfResultFormatParam; + this.dataSource = dataSource; + this.log = log; + + } + + private Set createJavaValueObjects(ResultSet resultSet) { + + Set collegeAcademicEmployees = new HashSet(); + + Map departmentURLToVO = new HashMap(); + Map employeeURLToVO = new HashMap(); + + while (resultSet.hasNext()) { + QuerySolution solution = resultSet.nextSolution(); + + String collegeURL = solution.get(QueryFieldLabels.COLLEGE_URL).toString(); + + VivoCollegeOrSchool currentCollege; + + if (collegeURLToVO.containsKey(collegeURL)) { + currentCollege = collegeURLToVO.get(collegeURL); + } else { + currentCollege = new VivoCollegeOrSchool(collegeURL); + collegeURLToVO.put(collegeURL, currentCollege); + + RDFNode collegeLabelNode = solution.get(QueryFieldLabels.COLLEGE_LABEL); + if (collegeLabelNode != null) { + currentCollege.setCollegeLabel(collegeLabelNode.toString()); + } + } + + String departmentURL = solution.get(QueryFieldLabels.DEPARTMENT_URL).toString(); + + VivoDepartmentOrDivision currentDepartment; + + if (departmentURLToVO.containsKey(departmentURL)) { + currentDepartment = departmentURLToVO.get(departmentURL); + currentDepartment.addParentCollege(currentCollege); + } else { + currentDepartment = new VivoDepartmentOrDivision(departmentURL, currentCollege); + departmentURLToVO.put(departmentURL, currentDepartment); + + RDFNode departmentLabelNode = solution.get(QueryFieldLabels.DEPARTMENT_LABEL); + if (departmentLabelNode != null) { + currentDepartment.setDepartmentLabel(departmentLabelNode.toString()); + } + } + + currentCollege.addDepartment(currentDepartment); + + RDFNode employeeNode = solution.get(QueryFieldLabels.ACADEMIC_FACULTY_EMPLOYEE_URL); + EmployeeType currentEmployeeType; + VivoEmployee currentEmployee; + + if (employeeNode != null) { + currentEmployeeType = EmployeeType.ACADEMIC_FACULTY_EMPLOYEE; + } else { + currentEmployeeType = EmployeeType.ACADEMIC_STAFF_EMPLOYEE; + employeeNode = solution.get(QueryFieldLabels.ACADEMIC_STAFF_EMPLOYEE_URL); + } + + if (employeeURLToVO.containsKey(employeeNode.toString())) { + currentEmployee = employeeURLToVO.get(employeeNode.toString()); + currentEmployee.addParentDepartment(currentDepartment); + } else { + currentEmployee = new VivoEmployee(employeeNode.toString(), currentEmployeeType, currentDepartment); + employeeURLToVO.put(employeeNode.toString(), currentEmployee); + + } + + RDFNode documentNode = solution.get(QueryFieldLabels.DOCUMENT_URL); + if (documentNode != null) { + + /* + * A document can have multiple authors but if the same author serves in multiple departments + * then we need to account for "An Authored Document" only once. This check will make sure that + * a document by same author is not added twice just because that author serves in 2 distinct + * department. + * */ + boolean isNewDocumentAlreadyAdded = testForDuplicateEntryOfDocument( + currentEmployee, + documentNode); + + if (!isNewDocumentAlreadyAdded) { + currentEmployee.addAuthorDocument(createAuthorDocumentsVO(solution, documentNode.toString())); + } + + } + + collegeAcademicEmployees.add(currentEmployee); + } + + +/* System.out.println(collegeURLToVO); + System.out.println("------------------------------------------------------------"); + System.out.println(departmentURLToVO); + System.out.println("------------------------------------------------------------"); + System.out.println(employeeURLToVO); + System.out.println("------------------------------------------------------------"); +*/ + return collegeAcademicEmployees; + } + + private boolean testForDuplicateEntryOfDocument( + VivoEmployee currentEmployee, RDFNode documentNode) { + boolean isNewDocumentAlreadyAdded = false; + + for (BiboDocument currentAuthoredDocument : currentEmployee.getAuthorDocuments()) { + if (currentAuthoredDocument.getDocumentURL().equalsIgnoreCase(documentNode.toString())) { + isNewDocumentAlreadyAdded = true; + break; + } + } + return isNewDocumentAlreadyAdded; + } + + public Map getCollegeURLToVO() { + return collegeURLToVO; + } + + private BiboDocument createAuthorDocumentsVO(QuerySolution solution, String documentURI) { + + BiboDocument biboDocument = new BiboDocument(documentURI); + + RDFNode documentLabelNode = solution.get(QueryFieldLabels.DOCUMENT_LABEL); + if (documentLabelNode != null) { + biboDocument.setDocumentLabel(documentLabelNode.toString()); + } + + RDFNode documentBlurbNode = solution.get(QueryFieldLabels.DOCUMENT_BLURB); + if (documentBlurbNode != null) { + biboDocument.setDocumentBlurb(documentBlurbNode.toString()); + } + + RDFNode documentMonikerNode = solution.get(QueryFieldLabels.DOCUMENT_MONIKER); + if (documentMonikerNode != null) { + biboDocument.setDocumentMoniker(documentMonikerNode.toString()); + } + + RDFNode documentDescriptionNode = solution.get(QueryFieldLabels.DOCUMENT_DESCRIPTION); + if (documentDescriptionNode != null) { + biboDocument.setDocumentDescription(documentDescriptionNode.toString()); + } + + RDFNode publicationYearNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR); + if (publicationYearNode != null) { + biboDocument.setPublicationYear(publicationYearNode.toString()); + } + + RDFNode authorLabelNode = solution.get(QueryFieldLabels.AUTHOR_LABEL); + if (authorLabelNode != null) { + biboDocument.setAuthorLabel(authorLabelNode.toString()); + } + + return biboDocument; + } + + private ResultSet executeQuery(String queryText, + String resultFormatParam, + String rdfResultFormatParam, + DataSource dataSource) { + + QueryExecution queryExecution = null; + try{ + Query query = QueryFactory.create(queryText, SYNTAX); + +// QuerySolutionMap qs = new QuerySolutionMap(); +// qs.add("authPerson", queryParam); // bind resource to s + + queryExecution = QueryExecutionFactory.create(query, dataSource); + + + //remocve this if loop after knowing what is describe & construct sparql stuff. + if (query.isSelectType()){ + return queryExecution.execSelect(); + } + } finally { + if(queryExecution != null) { + queryExecution.close(); + } + + } + return null; + } + + private String generateCollegeEmployeeSparqlQuery(String queryURI) { +// Resource uri1 = ResourceFactory.createResource(queryURI); + + String sparqlQuery = QueryConstants.SPARQL_QUERY_PREFIXES + + "SELECT (str(?collegeLabel) as ?" + QueryFieldLabels.COLLEGE_LABEL + ") " + + " (str(?department) as ?" + QueryFieldLabels.DEPARTMENT_URL + ") " + + " (str(?departmentLabel) as ?" + QueryFieldLabels.DEPARTMENT_LABEL + ") " + + " (str(?academicFacultyEmployee) as ?" + QueryFieldLabels.ACADEMIC_FACULTY_EMPLOYEE_URL + ") " + + " (str(?academicStaffEmployee) as ?" + QueryFieldLabels.ACADEMIC_STAFF_EMPLOYEE_URL + ") " + + " (str(<" + queryURI + ">) as ?" + QueryFieldLabels.COLLEGE_URL + ") " + + " (str(?authorLabel) as ?" + QueryFieldLabels.AUTHOR_LABEL + ") " + + " (str(?document) as ?" + QueryFieldLabels.DOCUMENT_URL + ") " + + " (str(?documentMoniker) as ?" + QueryFieldLabels.DOCUMENT_MONIKER + ") " + + " (str(?documentLabel) as ?" + QueryFieldLabels.DOCUMENT_LABEL + ") " + + " (str(?documentBlurb) as ?" + QueryFieldLabels.DOCUMENT_BLURB + ") " + + " (str(?documentDescription) as ?" + QueryFieldLabels.DOCUMENT_DESCRIPTION + ") " + + " (str(?publicationYear) as ?" + QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR + ") " + + "WHERE { " + + "<" + queryURI + "> rdf:type vivo:CollegeOrSchoolWithinUniversity; " + + "rdfs:label ?collegeLabel; " + + "vivo:hasAcademicDepartmentOrDivision ?department . " + + "?department rdfs:label ?departmentLabel ." + + "{ " + + getAcademicEmployeePublicationsSparqlQuery("academicFacultyEmployee", "vivo:hasEmployeeAcademicFacultyMember") + + " UNION " + + getAcademicEmployeePublicationsSparqlQuery("academicStaffEmployee", "vivo:hasEmployeeAcademicStaffMember") + + "}" + + "}"; + + System.out.println(sparqlQuery); + + return sparqlQuery; + } + + + private String getAcademicEmployeePublicationsSparqlQuery(String employeeHandle, + String ontologyHandle) { + + String sparqlQuery = " {?department " + ontologyHandle + " ?" + employeeHandle + " . " + + "?" + employeeHandle + " rdf:type foaf:Person; rdfs:label ?authorLabel. " + + "OPTIONAL { ?" + employeeHandle + " vivo:authorOf ?document ." + + " ?document rdf:type bibo:Document ." + + " ?document rdfs:label ?documentLabel ." + + " OPTIONAL { ?document vitro:moniker ?documentMoniker } ." + + " OPTIONAL { ?document vitro:blurb ?documentBlurb } ." + + " OPTIONAL { ?document vitro:description ?documentDescription } ." + + " OPTIONAL { ?document vivo:publicationYear ?publicationYear } ." + + "}" + + "} "; + + return sparqlQuery; + + } + + public Set getVisualizationJavaValueObjects() + throws MalformedQueryParametersException { + + if (this.collegeURIParam == null || "".equals(collegeURIParam)) { + throw new MalformedQueryParametersException("URI parameter is either null or empty."); + } else { + + /* + * To test for the validity of the URI submitted. + * */ + IRIFactory iRIFactory = IRIFactory.jenaImplementation(); + IRI iri = iRIFactory.create(this.collegeURIParam); + if (iri.hasViolation(false)) { + String errorMsg = ((Violation)iri.violations(false).next()).getShortMessage()+" "; + log.error("Pub Count Vis Query " + errorMsg); + throw new MalformedQueryParametersException("URI provided for an individual is malformed."); + } + } + + ResultSet resultSet = executeQuery(generateCollegeEmployeeSparqlQuery(this.collegeURIParam), + this.resultFormatParam, + this.rdfResultFormatParam, + this.dataSource); + + return createJavaValueObjects(resultSet); + } + + public Map getYearToPublicationCount( + Set authorDocuments) { + + /* + * Create a map from the year to number of publications. Use the BiboDocument's + * parsedPublicationYear to populate the data. + * */ + Map yearToPublicationCount = new TreeMap(); + + for (BiboDocument curr : authorDocuments) { + + /* + * Increment the count because there is an entry already available for + * that particular year. + * */ + String publicationYear; + if (curr.getPublicationYear() != null + && curr.getPublicationYear().length() != 0 + && curr.getPublicationYear().trim().length() != 0) { + publicationYear = curr.getPublicationYear(); + } else { + publicationYear = curr.getParsedPublicationYear(); + } + + if (yearToPublicationCount.containsKey(publicationYear)) { + yearToPublicationCount.put(publicationYear, + yearToPublicationCount + .get(publicationYear) + 1); + + } else { + yearToPublicationCount.put(publicationYear, 1); + } + + } + +// System.out.println("****************************\n" + yearToPublicationCount); + return yearToPublicationCount; + } + + + + + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/VisualizationRequestHandler.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/VisualizationRequestHandler.java new file mode 100644 index 000000000..a3ce0f80f --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/collegepubcount/VisualizationRequestHandler.java @@ -0,0 +1,482 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.collegepubcount; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.Map.Entry; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.skife.csv.CSVWriter; +import org.skife.csv.SimpleWriter; + +import com.hp.hpl.jena.query.DataSource; +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.pdf.PdfWriter; + +import edu.cornell.mannlib.vitro.webapp.beans.Portal; +import edu.cornell.mannlib.vitro.webapp.controller.Controllers; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.visualization.PDFDocument; +import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoCollegeOrSchool; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoDepartmentOrDivision; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VivoEmployee; + +public class VisualizationRequestHandler { + + public static final String VIS_CONTAINER_URL_HANDLE = "container"; + + public static final String COLLEGE_URI_URL_HANDLE = "uri"; + + public static final String VIS_MODE_URL_HANDLE = "vis_mode"; + + public static final String RENDER_MODE_URL_HANDLE = "render_mode"; + + public static final String STANDALONE_RENDER_MODE_URL_VALUE = "standalone"; + + public static final String DYNAMIC_RENDER_MODE_URL_VALUE = "dynamic"; + + public static final String DATA_RENDER_MODE_URL_VALUE = "data"; + + public static final String PDF_RENDER_MODE_URL_VALUE = "pdf"; + + private VitroRequest vitroRequest; + private HttpServletRequest request; + private HttpServletResponse response; + private Log log; + + + + public VisualizationRequestHandler(VitroRequest vitroRequest, + HttpServletRequest request, HttpServletResponse response, Log log) { + + this.vitroRequest = vitroRequest; + this.request = request; + this.response = response; + this.log = log; + + } + + public void generateVisualization(DataSource dataSource) { + + String resultFormatParam = "RS_TEXT"; + String rdfResultFormatParam = "RDF/XML-ABBREV"; + + String collegeURIParam = vitroRequest.getParameter(COLLEGE_URI_URL_HANDLE); + + String renderMode = vitroRequest.getParameter(RENDER_MODE_URL_HANDLE); + + String visMode = vitroRequest.getParameter(VIS_MODE_URL_HANDLE); + + String visContainer = vitroRequest.getParameter(VIS_CONTAINER_URL_HANDLE); + + QueryHandler queryManager = + new QueryHandler(collegeURIParam, + resultFormatParam, + rdfResultFormatParam, + dataSource, + log); + + try { + + Set employees = queryManager.getVisualizationJavaValueObjects(); + + Map> departmentToPublicationsOverTime = + new HashMap>(); + + Set publishedYearsForCollege = new HashSet(); + + for (VivoEmployee currentEmployee : employees) { + + Map currentEmployeeYearToPublicationCount = + queryManager.getYearToPublicationCount(currentEmployee.getAuthorDocuments()); + + if (currentEmployeeYearToPublicationCount.size() > 0) { + + + publishedYearsForCollege.addAll(currentEmployeeYearToPublicationCount.keySet()); + + for (VivoDepartmentOrDivision currentDepartment : currentEmployee.getParentDepartments()) { + + departmentToPublicationsOverTime.put(currentDepartment, + getUpdatedDepartmentPublicationsOverTime( + currentEmployeeYearToPublicationCount, + departmentToPublicationsOverTime + .get(currentDepartment))); + + } + + } + } + + + /* + * In order to avoid unneeded computations we have pushed this "if" condition up. + * This case arises when the render mode is data. In that case we dont want to generate + * HTML code to render sparkline, tables etc. Ideally I would want to avoid this flow. + * It is ugly! + * */ + if (DATA_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) { + prepareVisualizationQueryDataResponse(departmentToPublicationsOverTime, + queryManager.getCollegeURLToVO()); + + System.out.println(publishedYearsForCollege); + return; + } + + /* + if (PDF_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) { + prepareVisualizationQueryPDFResponse(authorDocuments, + yearToPublicationCount); + return; + } + */ + + /* + * Computations required to generate HTML for the sparklines & related context. + * */ + + /* + * This is required because when deciding the range of years over which the vis + * was rendered we dont want to be influenced by the "DEFAULT_PUBLICATION_YEAR". + * */ + publishedYearsForCollege.remove(BiboDocument.DEFAULT_PUBLICATION_YEAR); + + /* + VisualizationCodeGenerator visualizationCodeGenerator = + new VisualizationCodeGenerator(yearToPublicationCount, log); + + String visContentCode = visualizationCodeGenerator + .getMainVisualizationCode(authorDocuments, + publishedYears, + visMode, + visContainer); + + String visContextCode = visualizationCodeGenerator + .getVisualizationContextCode(vitroRequest.getRequestURI(), + collegeURIParam, + visMode); + */ + + /* + * This is side-effecting because the response of this method is just to redirect to + * a page with visualization on it. + * */ + + /* + RequestDispatcher requestDispatcher = null; + + if (DYNAMIC_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) { + + prepareVisualizationQueryDynamicResponse(request, response, vitroRequest, + visContentCode, visContextCode); + requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp"); + + } else { + prepareVisualizationQueryStandaloneResponse(request, response, vitroRequest, + visContentCode, visContextCode); + + requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); + } + + try { + requestDispatcher.forward(request, response); + } catch (Exception e) { + log.error("EntityEditController could not forward to view."); + log.error(e.getMessage()); + log.error(e.getStackTrace()); + } + +*/ + } catch (MalformedQueryParametersException e) { + try { + handleMalformedParameters(e.getMessage()); + } catch (ServletException e1) { + log.error(e1.getStackTrace()); + } catch (IOException e1) { + log.error(e1.getStackTrace()); + } + return; + } + + } + + private Map getUpdatedDepartmentPublicationsOverTime( + Map currentEmployeeYearToPublicationCount, + Map currentDepartmentYearToPublicationCount) { + + Map departmentYearToPublicationCount; + +// System.out.println("inside get updated dept pub obr time"); + + /* + * In case this is the first time we are consolidating publication counts over time for a department. + * */ + if (currentDepartmentYearToPublicationCount == null) { + departmentYearToPublicationCount = new TreeMap(); + +// System.out.println("new dept yr pub cnt"); + + } else { + departmentYearToPublicationCount = currentDepartmentYearToPublicationCount; + } + + + Iterator employeePubCountIterator = currentEmployeeYearToPublicationCount.entrySet().iterator(); + + while (employeePubCountIterator.hasNext()) { + Map.Entry employeePubCountEntry = (Map.Entry) employeePubCountIterator.next(); + + String employeePublicationYear = employeePubCountEntry.getKey(); + Integer employeePublicationCount = employeePubCountEntry.getValue(); + + try { + if (departmentYearToPublicationCount.containsKey(employeePublicationYear)) { + departmentYearToPublicationCount.put(employeePublicationYear, + departmentYearToPublicationCount + .get(employeePublicationYear) + + employeePublicationCount); + + } else { + departmentYearToPublicationCount.put(employeePublicationYear, employeePublicationCount); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + return departmentYearToPublicationCount; + } + + private void prepareVisualizationQueryPDFResponse(List authorDocuments, + Map yearToPublicationCount) { + + String authorName = null; + + /* + * To protect against cases where there are no author documents associated with the + * individual. + * */ + if (authorDocuments.size() > 0) { + authorName = ((BiboDocument) authorDocuments.get(0)).getAuthorLabel(); + } + + /* + * To make sure that null/empty records for author names do not cause any mischief. + * */ + if (authorName == null) { + authorName = ""; + } + + String outputFileName = slugify(authorName + "-report") + + ".pdf"; + + response.setContentType("application/pdf"); + response.setHeader("Content-Disposition","attachment;filename=" + outputFileName); + + ServletOutputStream responseOutputStream; + try { + responseOutputStream = response.getOutputStream(); + + + Document document = new Document(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PdfWriter pdfWriter = PdfWriter.getInstance(document, baos); + document.open(); +// document.add(new Paragraph("JSS Chintan Deepak Tank ")); +// document.add(Chunk.NEWLINE); +// document.add(new Paragraph("The method used to generate this PDF was: TEST OPST")); + + PDFDocument pdfDocument = new PDFDocument(authorName, yearToPublicationCount, document, pdfWriter); + + + document.close(); + + // setting some response headers + response.setHeader("Expires", "0"); + response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0"); + response.setHeader("Pragma", "public"); + // setting the content type + // the contentlength is needed for MSIE!!! + response.setContentLength(baos.size()); + // write ByteArrayOutputStream to the ServletOutputStream + baos.writeTo(responseOutputStream); + responseOutputStream.flush(); + responseOutputStream.close(); + +// System.out.println("done with response o/p stream"); + + } catch (IOException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } + } + + private void prepareVisualizationQueryDataResponse( + Map> departmentToPublicationsOverTime, + Map collegeURLToVO) { + + String collegeName = null; + + /* + * To protect against cases where there are no author documents associated with the + * individual. + * */ +// System.out.println(collegeURLToVO); + if (collegeURLToVO.size() > 0) { +// collegeName = ((VivoCollegeOrSchool) collegeURLToVO.entrySet().iterator().next()).getCollegeLabel(); + } + + /* + * To make sure that null/empty records for author names do not cause any mischief. + * */ + if (collegeName == null) { + collegeName = ""; + } + + String outputFileName = slugify(collegeName + "depts-pub-count") + + ".csv"; + + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition","attachment;filename=" + outputFileName); + + try { + + PrintWriter responseWriter = response.getWriter(); + + /* + * We are side-effecting responseWriter since we are directly manipulating the response + * object of the servlet. + * */ + generateCsvFileBuffer(departmentToPublicationsOverTime, + collegeURLToVO, + responseWriter); + + responseWriter.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Currently the approach for slugifying filenames is naive. In future if there is need, + * we can write more sophisticated method. + * @param textToBeSlugified + * @return + */ + private String slugify(String textToBeSlugified) { + return textToBeSlugified.toLowerCase().replaceAll("[^a-zA-Z0-9-]", "-"); + } + + private void generateCsvFileBuffer( + Map> departmentToPublicationsOverTime, + Map collegeURLToVO, PrintWriter printWriter) { + + CSVWriter csvWriter = new SimpleWriter(printWriter); + + try { + csvWriter.append(new String[]{"School", "Department", "Year", "Publications"}); + + Iterator collegeIterator = collegeURLToVO.values().iterator(); + + while (collegeIterator.hasNext()) { + VivoCollegeOrSchool college = collegeIterator.next(); + String collegeLabel = college.getCollegeLabel(); + for (VivoDepartmentOrDivision currentDepartment : college.getDepartments()) { + + Map currentDepartmentPublicationsOverTime = departmentToPublicationsOverTime.get(currentDepartment); + + /* + * This because many departments might not have any publication. + * */ + if (currentDepartmentPublicationsOverTime != null) { + + for (Entry currentEntry : currentDepartmentPublicationsOverTime.entrySet()) { + csvWriter.append(new Object[]{collegeLabel, + currentDepartment.getDepartmentLabel(), + currentEntry.getKey(), + currentEntry.getValue()}); + } + + } + + } + } + + } catch (IOException e) { + e.printStackTrace(); + } + + printWriter.flush(); + + } + + private void prepareVisualizationQueryStandaloneResponse(HttpServletRequest request, + HttpServletResponse response, VitroRequest vreq, + String visContentCode, String visContextCode) { + + Portal portal = vreq.getPortal(); + + request.setAttribute("visContentCode", visContentCode); + request.setAttribute("visContextCode", visContextCode); + + request.setAttribute("bodyJsp", "/templates/visualization/publication_count.jsp"); + request.setAttribute("portalBean", portal); + request.setAttribute("title", "Person Publication Count Visualization"); + request.setAttribute("scripts", "/templates/visualization/visualization_scripts.jsp"); + + } + + private void prepareVisualizationQueryDynamicResponse(HttpServletRequest request, + HttpServletResponse response, VitroRequest vreq, + String visContentCode, String visContextCode) { + + Portal portal = vreq.getPortal(); + + request.setAttribute("visContentCode", visContentCode); + request.setAttribute("visContextCode", visContextCode); + + request.setAttribute("portalBean", portal); + request.setAttribute("bodyJsp", "/templates/visualization/ajax_vis_content.jsp"); + + } + + private void handleMalformedParameters(String errorMessage) + throws ServletException, IOException { + + Portal portal = vitroRequest.getPortal(); + + request.setAttribute("error", errorMessage); + + RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); + request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp"); + request.setAttribute("portalBean", portal); + request.setAttribute("title", "Visualization Query Error - Person Publication Count"); + + try { + requestDispatcher.forward(request, response); + } catch (Exception e) { + log.error("EntityEditController could not forward to view."); + log.error(e.getMessage()); + log.error(e.getStackTrace()); + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/DocumentFieldNotFoundException.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/DocumentFieldNotFoundException.java new file mode 100644 index 000000000..63a6a512a --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/DocumentFieldNotFoundException.java @@ -0,0 +1,19 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.exceptions; + +public class DocumentFieldNotFoundException extends Exception { + + private static final long serialVersionUID = 1L; + + public DocumentFieldNotFoundException(String message) { + super(message); + } + + public DocumentFieldNotFoundException(Exception cause) { + super(createMessage(cause), cause); + } + + private static String createMessage(Exception cause) { + return "Document Field is empty " + cause.getMessage(); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/MalformedQueryParametersException.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/MalformedQueryParametersException.java new file mode 100644 index 000000000..8db7efb59 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/exceptions/MalformedQueryParametersException.java @@ -0,0 +1,19 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.exceptions; + +public class MalformedQueryParametersException extends Exception { + + private static final long serialVersionUID = 1L; + + public MalformedQueryParametersException(String message) { + super(message); + } + + public MalformedQueryParametersException(Exception cause) { + super(createMessage(cause), cause); + } + + private static String createMessage(Exception cause) { + return "Malformed Query Params " + cause.getMessage(); + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/QueryHandler.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/QueryHandler.java new file mode 100644 index 000000000..8901531c5 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/QueryHandler.java @@ -0,0 +1,243 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; + +import org.apache.commons.logging.Log; + +import com.hp.hpl.jena.iri.IRI; +import com.hp.hpl.jena.iri.IRIFactory; +import com.hp.hpl.jena.iri.Violation; +import com.hp.hpl.jena.query.DataSource; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.ResultSet; +import com.hp.hpl.jena.query.Syntax; +import com.hp.hpl.jena.rdf.model.RDFNode; + +import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; +import edu.cornell.mannlib.vitro.webapp.visualization.sparqlutils.QueryConstants; +import edu.cornell.mannlib.vitro.webapp.visualization.sparqlutils.QueryFieldLabels; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; + + + +/** + * Very dumb name of the class. change it. + * @author cdtank + * + */ +public class QueryHandler { + + protected static final Syntax SYNTAX = Syntax.syntaxARQ; + + private String queryParam, resultFormatParam, rdfResultFormatParam; + private DataSource dataSource; + + private Log log; + + private static final String SPARQL_QUERY_COMMON_SELECT_CLAUSE = "" + + "SELECT (str(?authorLabel) as ?authorLabelLit) " + + " (str(?document) as ?documentLit) " + + " (str(?documentMoniker) as ?documentMonikerLit) " + + " (str(?documentLabel) as ?documentLabelLit) " + + " (str(?documentBlurb) as ?documentBlurbLit) " + + " (str(?publicationYear) as ?publicationYearLit) " + + " (str(?documentDescription) as ?documentDescriptionLit) "; + + private static final String SPARQL_QUERY_COMMON_WHERE_CLAUSE = "" + + "?document rdf:type bibo:Document ." + + "?document rdfs:label ?documentLabel ." + + "OPTIONAL { ?document vivo:publicationYear ?publicationYear } ." + + "OPTIONAL { ?document vitro:moniker ?documentMoniker } ." + + "OPTIONAL { ?document vitro:blurb ?documentBlurb } ." + + "OPTIONAL { ?document vitro:description ?documentDescription }"; + + public QueryHandler(String queryParam, + String resultFormatParam, String rdfResultFormatParam, + DataSource dataSource, Log log) { + + this.queryParam = queryParam; + this.resultFormatParam = resultFormatParam; + this.rdfResultFormatParam = rdfResultFormatParam; + this.dataSource = dataSource; + this.log = log; + + } + + private List createJavaValueObjects(ResultSet resultSet) { + List authorDocuments = new ArrayList(); + + while (resultSet.hasNext()) { + QuerySolution solution = resultSet.nextSolution(); + + BiboDocument biboDocument = new BiboDocument( + solution.get(QueryFieldLabels.DOCUMENT_URL) + .toString()); + + RDFNode documentLabelNode = solution.get(QueryFieldLabels.DOCUMENT_LABEL); + if (documentLabelNode != null) { + biboDocument.setDocumentLabel(documentLabelNode.toString()); + } + + + RDFNode documentBlurbNode = solution.get(QueryFieldLabels.DOCUMENT_BLURB); + if (documentBlurbNode != null) { + biboDocument.setDocumentBlurb(documentBlurbNode.toString()); + } + + RDFNode documentmonikerNode = solution.get(QueryFieldLabels.DOCUMENT_MONIKER); + if (documentmonikerNode != null) { + biboDocument.setDocumentMoniker(documentmonikerNode.toString()); + } + + RDFNode documentDescriptionNode = solution.get(QueryFieldLabels.DOCUMENT_DESCRIPTION); + if (documentDescriptionNode != null) { + biboDocument.setDocumentDescription(documentDescriptionNode.toString()); + } + + RDFNode publicationYearNode = solution.get(QueryFieldLabels.DOCUMENT_PUBLICATION_YEAR); + if (publicationYearNode != null) { + biboDocument.setPublicationYear(publicationYearNode.toString()); + } + + RDFNode authorURLNode = solution.get(QueryFieldLabels.AUTHOR_URL); + if (authorURLNode != null) { + biboDocument.setAuthorURL(authorURLNode.toString()); + } + + RDFNode authorLabelNode = solution.get(QueryFieldLabels.AUTHOR_LABEL); + if (authorLabelNode != null) { + biboDocument.setAuthorLabel(authorLabelNode.toString()); + } + + authorDocuments.add(biboDocument); + } + return authorDocuments; + } + + private ResultSet executeQuery(String queryURI, + String resultFormatParam, String rdfResultFormatParam, DataSource dataSource) { + + QueryExecution queryExecution = null; + try{ + Query query = QueryFactory.create(generateSparqlQuery(queryURI), SYNTAX); + +// QuerySolutionMap qs = new QuerySolutionMap(); +// qs.add("authPerson", queryParam); // bind resource to s + + queryExecution = QueryExecutionFactory.create(query, dataSource); + + + //remocve this if loop after knowing what is describe & construct sparql stuff. + if( query.isSelectType() ){ + return queryExecution.execSelect(); + } + } finally { + if(queryExecution != null) { + queryExecution.close(); + } + + } + return null; + } + + private String generateSparqlQuery(String queryURI) { +// Resource uri1 = ResourceFactory.createResource(queryURI); + + String sparqlQuery = QueryConstants.SPARQL_QUERY_PREFIXES + + SPARQL_QUERY_COMMON_SELECT_CLAUSE + + "(str(<" + queryURI + ">) as ?authPersonLit) " + + "WHERE { " + + "<" + queryURI + "> rdf:type foaf:Person ; vivo:authorOf ?document ; rdfs:label ?authorLabel. " + + SPARQL_QUERY_COMMON_WHERE_CLAUSE + + "}"; + + log.debug("SPARQL query for person pub count -> \n" + sparqlQuery); + + return sparqlQuery; + } + + public List getVisualizationJavaValueObjects() + throws MalformedQueryParametersException { + + if(this.queryParam == null || "".equals(queryParam)) { + throw new MalformedQueryParametersException("URI parameter is either null or empty."); + } else { + + /* + * To test for the validity of the URI submitted. + * */ + IRIFactory iRIFactory = IRIFactory.jenaImplementation(); + IRI iri = iRIFactory.create(this.queryParam); + if (iri.hasViolation(false)) { + String errorMsg = ((Violation)iri.violations(false).next()).getShortMessage()+" "; + log.error("Pub Count vis Query " + errorMsg); + throw new MalformedQueryParametersException("URI provided for an individual is malformed."); + } + } + + + + ResultSet resultSet = executeQuery(this.queryParam, + this.resultFormatParam, + this.rdfResultFormatParam, + this.dataSource); + + return createJavaValueObjects(resultSet); + } + + public Map getYearToPublicationCount( + List authorDocuments) { + + //List publishedYears = new ArrayList(); + + /* + * Create a map from the year to number of publications. Use the BiboDocument's + * parsedPublicationYear to populate the data. + * */ + Map yearToPublicationCount = new TreeMap(); + + for (BiboDocument curr : authorDocuments) { + + /* + * Increment the count because there is an entry already available for + * that particular year. + * */ + String publicationYear; + if (curr.getPublicationYear() != null + && curr.getPublicationYear().length() != 0 + && curr.getPublicationYear().trim().length() != 0) { + publicationYear = curr.getPublicationYear(); + } else { + publicationYear = curr.getParsedPublicationYear(); + } + + if (yearToPublicationCount.containsKey(publicationYear)) { + yearToPublicationCount.put(publicationYear, + yearToPublicationCount + .get(publicationYear) + 1); + + } else { + yearToPublicationCount.put(publicationYear, 1); + } + +// if (!parsedPublicationYear.equalsIgnoreCase(BiboDocument.DEFAULT_PUBLICATION_YEAR)) { +// publishedYears.add(Integer.parseInt(parsedPublicationYear)); +// } + + } + + return yearToPublicationCount; + } + + + + + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationRequestHandler.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationRequestHandler.java new file mode 100644 index 000000000..9c0f473a9 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/personpubcount/VisualizationRequestHandler.java @@ -0,0 +1,366 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.personpubcount; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletException; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.skife.csv.CSVWriter; +import org.skife.csv.SimpleWriter; + +import com.hp.hpl.jena.query.DataSource; +import com.itextpdf.text.Document; +import com.itextpdf.text.DocumentException; +import com.itextpdf.text.pdf.PdfWriter; + +import edu.cornell.mannlib.vitro.webapp.beans.Portal; +import edu.cornell.mannlib.vitro.webapp.controller.Controllers; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.visualization.PDFDocument; +import edu.cornell.mannlib.vitro.webapp.visualization.VisualizationCodeGenerator; +import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException; +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.BiboDocument; + +public class VisualizationRequestHandler { + + public static final String VIS_CONTAINER_URL_HANDLE = "container"; + + public static final String INDIVIDUAL_URI_URL_HANDLE = "uri"; + + public static final String VIS_MODE_URL_HANDLE = "vis_mode"; + + public static final String RENDER_MODE_URL_HANDLE = "render_mode"; + + public static final String STANDALONE_RENDER_MODE_URL_VALUE = "standalone"; + + public static final String DYNAMIC_RENDER_MODE_URL_VALUE = "dynamic"; + + public static final String DATA_RENDER_MODE_URL_VALUE = "data"; + + public static final String PDF_RENDER_MODE_URL_VALUE = "pdf"; + + private VitroRequest vitroRequest; + private HttpServletRequest request; + private HttpServletResponse response; + private Log log; + + + + public VisualizationRequestHandler(VitroRequest vitroRequest, + HttpServletRequest request, HttpServletResponse response, Log log) { + + this.vitroRequest = vitroRequest; + this.request = request; + this.response = response; + this.log = log; + + } + + public void generateVisualization(DataSource dataSource) { + + String resultFormatParam = "RS_TEXT"; + String rdfResultFormatParam = "RDF/XML-ABBREV"; + + String individualURIParam = vitroRequest.getParameter(INDIVIDUAL_URI_URL_HANDLE); + + String renderMode = vitroRequest.getParameter(RENDER_MODE_URL_HANDLE); + + String visMode = vitroRequest.getParameter(VIS_MODE_URL_HANDLE); + + String visContainer = vitroRequest.getParameter(VIS_CONTAINER_URL_HANDLE); + + QueryHandler queryManager = + new QueryHandler(individualURIParam, + resultFormatParam, + rdfResultFormatParam, + dataSource, + log); + + try { + List authorDocuments = queryManager.getVisualizationJavaValueObjects(); + + /* + * Create a map from the year to number of publications. Use the BiboDocument's + * parsedPublicationYear to populate the data. + * */ + Map yearToPublicationCount = + queryManager.getYearToPublicationCount(authorDocuments); + + /* + * In order to avoid unneeded computations we have pushed this "if" condition up. + * This case arises when the render mode is data. In that case we dont want to generate + * HTML code to render sparkline, tables etc. Ideally I would want to avoid this flow. + * It is ugly! + * */ + if (DATA_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) { + prepareVisualizationQueryDataResponse(authorDocuments, + yearToPublicationCount); + return; + } + + + if (PDF_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) { + prepareVisualizationQueryPDFResponse(authorDocuments, + yearToPublicationCount); + return; + } + + /* + * Computations required to generate HTML for the sparklines & related context. + * */ + + /* + * This is required because when deciding the range of years over which the vis + * was rendered we dont want to be influenced by the "DEFAULT_PUBLICATION_YEAR". + * */ + Set publishedYears = new HashSet(yearToPublicationCount.keySet()); + publishedYears.remove(BiboDocument.DEFAULT_PUBLICATION_YEAR); + + VisualizationCodeGenerator visualizationCodeGenerator = + new VisualizationCodeGenerator(yearToPublicationCount, log); + + String visContentCode = visualizationCodeGenerator + .getMainVisualizationCode(authorDocuments, + publishedYears, + visMode, + visContainer); + + String visContextCode = visualizationCodeGenerator + .getVisualizationContextCode(vitroRequest.getRequestURI(), + individualURIParam, + visMode); + + + /* + * This is side-effecting because the response of this method is just to redirect to + * a page with visualization on it. + * */ + RequestDispatcher requestDispatcher = null; + + if (DYNAMIC_RENDER_MODE_URL_VALUE.equalsIgnoreCase(renderMode)) { + + prepareVisualizationQueryDynamicResponse(request, response, vitroRequest, + visContentCode, visContextCode); + requestDispatcher = request.getRequestDispatcher("/templates/page/blankPage.jsp"); + + } else { + prepareVisualizationQueryStandaloneResponse(request, response, vitroRequest, + visContentCode, visContextCode); + + requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); + } + + try { + requestDispatcher.forward(request, response); + } catch (Exception e) { + log.error("EntityEditController could not forward to view."); + log.error(e.getMessage()); + log.error(e.getStackTrace()); + } + + } catch (MalformedQueryParametersException e) { + try { + handleMalformedParameters(e.getMessage()); + } catch (ServletException e1) { + log.error(e1.getStackTrace()); + } catch (IOException e1) { + log.error(e1.getStackTrace()); + } + return; + } + + } + + private void prepareVisualizationQueryPDFResponse(List authorDocuments, + Map yearToPublicationCount) { + + String authorName = null; + + /* + * To protect against cases where there are no author documents associated with the + * individual. + * */ + if (authorDocuments.size() > 0) { + authorName = ((BiboDocument) authorDocuments.get(0)).getAuthorLabel(); + } + + /* + * To make sure that null/empty records for author names do not cause any mischief. + * */ + if (authorName == null) { + authorName = ""; + } + + String outputFileName = slugify(authorName + "report") + + ".pdf"; + + response.setContentType("application/pdf"); + response.setHeader("Content-Disposition", "attachment;filename=" + outputFileName); + + ServletOutputStream responseOutputStream; + try { + responseOutputStream = response.getOutputStream(); + + + Document document = new Document(); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PdfWriter pdfWriter = PdfWriter.getInstance(document, baos); + document.open(); + + PDFDocument pdfDocument = new PDFDocument(authorName, yearToPublicationCount, document, pdfWriter); + + document.close(); + + // setting some response headers & content type + response.setHeader("Expires", "0"); + response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0"); + response.setHeader("Pragma", "public"); + response.setContentLength(baos.size()); + // write ByteArrayOutputStream to the ServletOutputStream + baos.writeTo(responseOutputStream); + responseOutputStream.flush(); + responseOutputStream.close(); + + } catch (IOException e) { + e.printStackTrace(); + } catch (DocumentException e) { + e.printStackTrace(); + } + } + + private void prepareVisualizationQueryDataResponse(List authorDocuments, + Map yearToPublicationCount) { + + String authorName = null; + + /* + * To protect against cases where there are no author documents associated with the + * individual. + * */ + if (authorDocuments.size() > 0) { + authorName = ((BiboDocument) authorDocuments.get(0)).getAuthorLabel(); + } + + /* + * To make sure that null/empty records for author names do not cause any mischief. + * */ + if (authorName == null) { + authorName = ""; + } + + String outputFileName = slugify(authorName + "pub-count-sparkline") + + ".csv"; + + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition","attachment;filename=" + outputFileName); + + try { + + PrintWriter responseWriter = response.getWriter(); + + /* + * We are side-effecting responseWriter since we are directly manipulating the response + * object of the servlet. + * */ + generateCsvFileBuffer(yearToPublicationCount, + responseWriter); + + responseWriter.close(); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Currently the approach for slugifying filenames is naive. In future if there is need, + * we can write more sophisticated method. + * @param textToBeSlugified + * @return + */ + private String slugify(String textToBeSlugified) { + return textToBeSlugified.toLowerCase().replaceAll("[^a-zA-Z0-9-]", "-"); + } + + private void generateCsvFileBuffer(Map yearToPublicationCount, + PrintWriter responseWriter) { + + CSVWriter csvWriter = new SimpleWriter(responseWriter); + + try { + csvWriter.append(new String[]{"Year", "Publications"}); + for (Entry currentEntry : yearToPublicationCount.entrySet()) { + csvWriter.append(new Object[]{currentEntry.getKey(), currentEntry.getValue()}); + } + + } catch (IOException e) { + e.printStackTrace(); + } + + responseWriter.flush(); + + } + + private void prepareVisualizationQueryStandaloneResponse(HttpServletRequest request, + HttpServletResponse response, VitroRequest vreq, + String visContentCode, String visContextCode) { + + Portal portal = vreq.getPortal(); + + request.setAttribute("visContentCode", visContentCode); + request.setAttribute("visContextCode", visContextCode); + + request.setAttribute("bodyJsp", "/templates/visualization/publication_count.jsp"); + request.setAttribute("portalBean", portal); + request.setAttribute("title", "Person Publication Count visualization"); + request.setAttribute("scripts", "/templates/visualization/visualization_scripts.jsp"); + + } + + private void prepareVisualizationQueryDynamicResponse(HttpServletRequest request, + HttpServletResponse response, VitroRequest vreq, + String visContentCode, String visContextCode) { + + Portal portal = vreq.getPortal(); + + request.setAttribute("visContentCode", visContentCode); + request.setAttribute("visContextCode", visContextCode); + + request.setAttribute("portalBean", portal); + request.setAttribute("bodyJsp", "/templates/visualization/ajax_vis_content.jsp"); + + } + + private void handleMalformedParameters(String errorMessage) + throws ServletException, IOException { + + Portal portal = vitroRequest.getPortal(); + + request.setAttribute("error", errorMessage); + + RequestDispatcher requestDispatcher = request.getRequestDispatcher(Controllers.BASIC_JSP); + request.setAttribute("bodyJsp", "/templates/visualization/visualization_error.jsp"); + request.setAttribute("portalBean", portal); + request.setAttribute("title", "Visualization Query Error - Person Publication Count"); + + try { + requestDispatcher.forward(request, response); + } catch (Exception e) { + log.error("EntityEditController could not forward to view."); + log.error(e.getMessage()); + log.error(e.getStackTrace()); + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/sparqlutils/QueryConstants.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/sparqlutils/QueryConstants.java new file mode 100644 index 000000000..c046cc054 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/sparqlutils/QueryConstants.java @@ -0,0 +1,16 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.sparqlutils; + +public class QueryConstants { + + public static final String SPARQL_QUERY_PREFIXES = "" + + "PREFIX rdf: \n" + + "PREFIX rdfs: \n" + + "PREFIX vitro: \n" + + "PREFIX vivo: \n" + + "PREFIX core: \n" + + "PREFIX bibo: \n" + + "PREFIX foaf: \n" + + "PREFIX aktp: \n"; + + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/sparqlutils/QueryFieldLabels.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/sparqlutils/QueryFieldLabels.java new file mode 100644 index 000000000..83d964037 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/sparqlutils/QueryFieldLabels.java @@ -0,0 +1,40 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.sparqlutils; + +public class QueryFieldLabels { + + /* + * Document related field labels + * */ + public static final String DOCUMENT_URL = "documentLit"; + public static final String DOCUMENT_MONIKER = "documentMonikerLit"; + public static final String DOCUMENT_LABEL = "documentLabelLit"; + public static final String DOCUMENT_BLURB = "documentBlurbLit"; + public static final String DOCUMENT_DESCRIPTION = "documentDescriptionLit"; + public static final String DOCUMENT_PUBLICATION_YEAR = "publicationYearLit"; + + + /* + * Author related field labels + * */ + public static final String AUTHOR_URL = "authPersonLit"; + public static final String AUTHOR_LABEL = "authorLabelLit"; + + /* + * College related field labels + * */ + public static final String COLLEGE_URL = "collegeLit"; + public static final String COLLEGE_LABEL = "collegeLabelLit"; + + /* + * Department related field labels + * */ + public static final String DEPARTMENT_URL = "departmentLit"; + public static final String DEPARTMENT_LABEL = "departmentLabelLit"; + + /* + * Employee related field labels + * */ + public static final String ACADEMIC_FACULTY_EMPLOYEE_URL = "academicFacultyEmployeeLit"; + public static final String ACADEMIC_STAFF_EMPLOYEE_URL = "academicStaffEmployeeLit"; + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java new file mode 100644 index 000000000..3dab7143e --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/BiboDocument.java @@ -0,0 +1,145 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; + +import java.util.Calendar; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class BiboDocument { + + public static final String DEFAULT_PUBLICATION_YEAR = "Unknown"; + public static final int MINIMUM_PUBLICATION_YEAR = 1800; + private static final int CURRENT_YEAR = Calendar.getInstance().get(Calendar.YEAR); + + private String authorURL; + private String authorLabel; + private String documentURL; + private String documentMoniker; + private String documentLabel; + private String documentBlurb; + private String documentDescription; + private String publicationYear; + private String parsedPublicationYear = DEFAULT_PUBLICATION_YEAR; + + + + public BiboDocument(String documentURL) { + this.documentURL = documentURL; + } + + public String getAuthorURL() { + return authorURL; + } + + public void setAuthorURL(String authorURL) { + this.authorURL = authorURL; + } + + public String getAuthorLabel() { + return authorLabel; + } + + public void setAuthorLabel(String authorLabel) { + this.authorLabel = authorLabel; + } + + public String getDocumentURL() { + return documentURL; + } + + public void setDocumentURL(String documentURL) { + this.documentURL = documentURL; + } + + public String getDocumentMoniker() { + return documentMoniker; + } + + public void setDocumentMoniker(String documentMoniker) { + this.documentMoniker = documentMoniker; + } + + public String getDocumentLabel() { + return documentLabel; + } + + public void setDocumentLabel(String documentLabel) { + this.documentLabel = documentLabel; + } + + public String getDocumentBlurb() { + return documentBlurb; + } + + public void setDocumentBlurb(String documentBlurb) { + this.documentBlurb = documentBlurb; + + if (documentBlurb != null) { + this.setParsedPublicationYear(parsePublicationYear(documentBlurb)); + } + } + + private String parsePublicationYear(String documentBlurb) { + + /* + * This pattern will match all group of numbers which have only 4 digits + * delimited by the word boundary. + * */ +// String pattern = "\\b\\d{4}\\b"; + String pattern = "(?= MINIMUM_PUBLICATION_YEAR) { + publishedYear = candidateYearInteger.toString(); + } + + } + + return publishedYear; + } + + public String getDocumentDescription() { + return documentDescription; + } + public void setDocumentDescription(String documentDescription) { + this.documentDescription = documentDescription; + } + + /* + * Only the + * */ + private void setParsedPublicationYear(String parsedPublicationYear) { + this.parsedPublicationYear = parsedPublicationYear; + } + + public String getParsedPublicationYear() { + return parsedPublicationYear; + } + + /* + * This publicationYear value is directly from the data supported by the ontology. If this is empty only + * then use the parsedPublicationYear. + * */ + public String getPublicationYear() { + return publicationYear; + } + + public void setPublicationYear(String publicationYear) { + this.publicationYear = publicationYear; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VOConstants.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VOConstants.java new file mode 100644 index 000000000..f1b24a7e1 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VOConstants.java @@ -0,0 +1,12 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; + +public class VOConstants { + + /* + * Employee related constants + * */ + public static enum EmployeeType { + ACADEMIC_FACULTY_EMPLOYEE, ACADEMIC_STAFF_EMPLOYEE + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java new file mode 100644 index 000000000..6627dd33e --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoCollegeOrSchool.java @@ -0,0 +1,46 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; + +import java.util.HashSet; +import java.util.Set; + +/** + * + * This is the Value Object equivalent for vivo:CollegeOrSchoolWithinUniversity object type. + * @author cdtank + * + */ +public class VivoCollegeOrSchool { + + private String collegeURL; + private String collegeLabel; + private Set departments = new HashSet(); + + public VivoCollegeOrSchool(String collegeURL) { + this.collegeURL = collegeURL; + } + + public Set getDepartments() { + return departments; + } + + public void addDepartment(VivoDepartmentOrDivision department) { + this.departments.add(department); + } + + public String getCollegeURL() { + return collegeURL; + } + + public String getCollegeLabel() { + if (collegeLabel != null) { + return collegeLabel; + } else { + return ""; + } + } + + public void setCollegeLabel(String collegeLabel) { + this.collegeLabel = collegeLabel; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java new file mode 100644 index 000000000..a79fbb798 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoDepartmentOrDivision.java @@ -0,0 +1,47 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; + +import java.util.HashSet; +import java.util.Set; + +/** + * + * This is the Value Object equivalent for vivo:AcademicDepartmentOrDivision object type. + * @author cdtank + * + */ +public class VivoDepartmentOrDivision { + + private String departmentURL; + private String departmentLabel; + private Set parentColleges = new HashSet(); + + public VivoDepartmentOrDivision(String departmentURL, VivoCollegeOrSchool parentCollege) { + this.departmentURL = departmentURL; + addParentCollege(parentCollege); + } + + public Set getParentCollege() { + return parentColleges; + } + + public void addParentCollege(VivoCollegeOrSchool parentCollege) { + this.parentColleges.add(parentCollege); + } + + public String getDepartmentURL() { + return departmentURL; + } + + public String getDepartmentLabel() { + if (departmentLabel != null) { + return departmentLabel; + } else { + return ""; + } + } + + public void setDepartmentLabel(String departmentLabel) { + this.departmentLabel = departmentLabel; + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java new file mode 100644 index 000000000..838ab3970 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/visualization/valueobjects/VivoEmployee.java @@ -0,0 +1,59 @@ +package edu.cornell.mannlib.vitro.webapp.visualization.valueobjects; + +import java.util.HashSet; +import java.util.Set; + +import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.VOConstants.EmployeeType; + +/** + * + * This is the Value Object equivalent for vivo's Employee object type. + * @author cdtank + * + */ +public class VivoEmployee { + + private String employeeURL; + private EmployeeType employeeType; + private Set parentDepartments = new HashSet(); + private Set authorDocuments = new HashSet(); + + public VivoEmployee(String employeeURL, EmployeeType employeeType, VivoDepartmentOrDivision parentDepartment) { + this.employeeURL = employeeURL; + addParentDepartment(parentDepartment); + } + + public String getEmployeeURL() { + return employeeURL; + } + + public void setEmployeeURL(String employeeURL) { + this.employeeURL = employeeURL; + } + + public EmployeeType getEmployeeType() { + return employeeType; + } + + public void setEmployeeType(EmployeeType employeeType) { + this.employeeType = employeeType; + } + + public Set getParentDepartments() { + return parentDepartments; + } + + public void addParentDepartment(VivoDepartmentOrDivision parentDepartment) { + this.parentDepartments.add(parentDepartment); + } + + public Set getAuthorDocuments() { + return authorDocuments; + } + + public void addAuthorDocument(BiboDocument authorDocument) { + this.authorDocuments.add(authorDocument); + } + + +} diff --git a/webapp/web/templates/entity/entityBasic.jsp b/webapp/web/templates/entity/entityBasic.jsp index 6bbd477e5..aaddb98d0 100644 --- a/webapp/web/templates/entity/entityBasic.jsp +++ b/webapp/web/templates/entity/entityBasic.jsp @@ -131,6 +131,10 @@ if (VitroRequestPrep.isSelfEditing(request) || LoginFormBean.loggedIn(request, L + + + + <%-- Links --%>