diff --git a/productMods/WEB-INF/visualization/visualizations-beans-injection-fm.xml b/productMods/WEB-INF/visualization/visualizations-beans-injection-fm.xml
index f27ef1eb..88548065 100644
--- a/productMods/WEB-INF/visualization/visualizations-beans-injection-fm.xml
+++ b/productMods/WEB-INF/visualization/visualizations-beans-injection-fm.xml
@@ -29,10 +29,10 @@
class="edu.cornell.mannlib.vitro.webapp.visualization.coprincipalinvestigator.CoPIGrantCountRequestHandler" />
+ class="edu.cornell.mannlib.vitro.webapp.visualization.temporalgraph.TemporalPublicationVisualizationRequestHandler" />
+ class="edu.cornell.mannlib.vitro.webapp.visualization.temporalgraph.TemporalGrantVisualizationRequestHandler" />
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/mapofscience/MapOfScienceVisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/mapofscience/MapOfScienceVisualizationRequestHandler.java
index a1173957..df7b0457 100644
--- a/src/edu/cornell/mannlib/vitro/webapp/visualization/mapofscience/MapOfScienceVisualizationRequestHandler.java
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/mapofscience/MapOfScienceVisualizationRequestHandler.java
@@ -28,8 +28,8 @@ import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFr
import edu.cornell.mannlib.vitro.webapp.visualization.constants.MapOfScienceConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
-import edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison.OrganizationUtilityFunctions;
import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.temporalgraph.OrganizationUtilityFunctions;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Activity;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Entity;
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.GenericQueryMap;
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/entitycomparison/OrganizationUtilityFunctions.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/OrganizationUtilityFunctions.java
similarity index 98%
rename from src/edu/cornell/mannlib/vitro/webapp/visualization/entitycomparison/OrganizationUtilityFunctions.java
rename to src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/OrganizationUtilityFunctions.java
index 08fc6aa6..539cc976 100644
--- a/src/edu/cornell/mannlib/vitro/webapp/visualization/entitycomparison/OrganizationUtilityFunctions.java
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/OrganizationUtilityFunctions.java
@@ -1,5 +1,5 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
-package edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison;
+package edu.cornell.mannlib.vitro.webapp.visualization.temporalgraph;
import java.util.HashMap;
import java.util.Map;
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/entitycomparison/TemporalGrantVisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/TemporalGrantVisualizationRequestHandler.java
similarity index 96%
rename from src/edu/cornell/mannlib/vitro/webapp/visualization/entitycomparison/TemporalGrantVisualizationRequestHandler.java
rename to src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/TemporalGrantVisualizationRequestHandler.java
index 5ce59b05..fc09bb07 100644
--- a/src/edu/cornell/mannlib/vitro/webapp/visualization/entitycomparison/TemporalGrantVisualizationRequestHandler.java
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/TemporalGrantVisualizationRequestHandler.java
@@ -1,6 +1,6 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
-package edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison;
+package edu.cornell.mannlib.vitro.webapp.visualization.temporalgraph;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/entitycomparison/TemporalPublicationVisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/TemporalPublicationVisualizationRequestHandler.java
similarity index 96%
rename from src/edu/cornell/mannlib/vitro/webapp/visualization/entitycomparison/TemporalPublicationVisualizationRequestHandler.java
rename to src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/TemporalPublicationVisualizationRequestHandler.java
index 9eb086be..1fa6576c 100644
--- a/src/edu/cornell/mannlib/vitro/webapp/visualization/entitycomparison/TemporalPublicationVisualizationRequestHandler.java
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/TemporalPublicationVisualizationRequestHandler.java
@@ -1,6 +1,6 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
-package edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison;
+package edu.cornell.mannlib.vitro.webapp.visualization.temporalgraph;
import java.util.ArrayList;
import java.util.HashMap;
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/cached/TemporalGrantVisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/cached/TemporalGrantVisualizationRequestHandler.java
new file mode 100644
index 00000000..a7455f60
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/cached/TemporalGrantVisualizationRequestHandler.java
@@ -0,0 +1,389 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison.cached;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+
+import com.google.gson.Gson;
+import com.hp.hpl.jena.query.Dataset;
+
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.DataVisualizationController;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison.OrganizationUtilityFunctions;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Activity;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Entity;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SubEntity;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.json.JsonObject;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.json.SubjectEntityJSON;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.SelectOnModelUtilities;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler;
+
+
+public class TemporalGrantVisualizationRequestHandler implements
+ VisualizationRequestHandler {
+
+ @Override
+ public ResponseValues generateStandardVisualization(
+ VitroRequest vitroRequest, Log log, Dataset dataset)
+ throws MalformedQueryParametersException {
+
+ String entityURI = vitroRequest
+ .getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
+
+ return generateStandardVisualizationForGrantTemporalVis(vitroRequest,
+ log, dataset, entityURI);
+ }
+
+
+ private ResponseValues generateStandardVisualizationForGrantTemporalVis(
+ VitroRequest vitroRequest, Log log, Dataset dataset,
+ String entityURI) throws MalformedQueryParametersException {
+ if (StringUtils.isBlank(entityURI)) {
+
+ entityURI = OrganizationUtilityFunctions
+ .getStaffProvidedOrComputedHighestLevelOrganization(
+ log,
+ dataset,
+ vitroRequest);
+
+ }
+
+/* System.out.println("current models in the system are");
+ for (Map.Entry entry : ConstructedModelTracker.getAllModels().entrySet()) {
+ System.out.println(entry.getKey() + " -> " + entry.getValue().size());
+ }
+*/
+ return prepareStandaloneMarkupResponse(vitroRequest, entityURI);
+ }
+
+
+ @Override
+ public ResponseValues generateVisualizationForShortURLRequests(
+ Map parameters, VitroRequest vitroRequest, Log log,
+ Dataset dataset) throws MalformedQueryParametersException {
+
+
+ return generateStandardVisualizationForGrantTemporalVis(
+ vitroRequest, log, dataset, parameters.get(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY));
+
+ }
+
+ @Override
+ public Map generateDataVisualization(
+ VitroRequest vitroRequest, Log log, Dataset dataset)
+ throws MalformedQueryParametersException {
+
+ String entityURI = vitroRequest
+ .getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
+
+ /*
+ * This will provide the data in json format mainly used for standalone temporal vis.
+ * */
+ if (VisualizationFrameworkConstants.JSON_OUTPUT_FORMAT
+ .equalsIgnoreCase(vitroRequest
+ .getParameter(VisualizationFrameworkConstants.VIS_MODE_KEY))) {
+
+ if (StringUtils.isNotBlank(entityURI)) {
+
+ return getSubjectEntityAndGenerateDataResponse(
+ vitroRequest,
+ log,
+ dataset,
+ entityURI,
+ VisConstants.DataVisMode.JSON);
+ } else {
+
+ return getSubjectEntityAndGenerateDataResponse(
+ vitroRequest,
+ log,
+ dataset,
+ OrganizationUtilityFunctions
+ .getStaffProvidedOrComputedHighestLevelOrganization(
+ log,
+ dataset,
+ vitroRequest),
+ VisConstants.DataVisMode.JSON);
+ }
+
+ } else {
+ /*
+ * This provides csv download files for the content in the tables.
+ * */
+ return getSubjectEntityAndGenerateDataResponse(
+ vitroRequest,
+ log,
+ dataset,
+ entityURI,
+ VisConstants.DataVisMode.CSV);
+ }
+ }
+
+ private Map prepareDataErrorResponse() {
+
+ String outputFileName = "no-organization_grants-per-year.csv";
+
+ Map fileData = new HashMap();
+
+ fileData.put(DataVisualizationController.FILE_NAME_KEY,
+ outputFileName);
+ fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
+ "application/octet-stream");
+ fileData.put(DataVisualizationController.FILE_CONTENT_KEY, "");
+ return fileData;
+ }
+
+ @Override
+ public Object generateAjaxVisualization(VitroRequest vitroRequest, Log log,
+ Dataset dataset) throws MalformedQueryParametersException {
+
+ throw new UnsupportedOperationException("Entity Grant Count "
+ + "does not provide Ajax response.");
+ }
+
+ private Map getSubjectEntityAndGenerateDataResponse(
+ VitroRequest vitroRequest, Log log, Dataset dataset,
+ String subjectEntityURI, VisConstants.DataVisMode visMode)
+ throws MalformedQueryParametersException {
+
+ Entity organizationEntity = SelectOnModelUtilities
+ .getSubjectOrganizationHierarchy(dataset, subjectEntityURI);
+
+ if (organizationEntity.getSubEntities() == null) {
+
+ if (VisConstants.DataVisMode.JSON.equals(visMode)) {
+ return prepareStandaloneDataErrorResponse();
+ } else {
+ return prepareDataErrorResponse();
+ }
+ }
+
+ Map grantURIForAssociatedPeopleToVO = new HashMap();
+ Map allGrantURIToVO = new HashMap();
+
+/**
+ * TODO: Change this to use DataSet when an optimum solution is reached. Currently grant constructs are causing
+ * endless wait times on a large dataset like UFl. When I tried to add all the datasets manually to the Datasource
+ * it responded in an order of magnitude higher than with just the defaultOntModel.
+ * Brian Lowe is looking into this weird behavior see http://issues.library.cornell.edu/browse/NIHVIVO-2275
+ */
+// DataSource dataSource = DatasetFactory.create();
+// dataSource.setDefaultModel(vitroRequest.getJenaOntModel());
+
+ allGrantURIToVO = SelectOnModelUtilities.getGrantsForAllSubOrganizations(dataset, organizationEntity);
+
+ Entity organizationWithAssociatedPeople = SelectOnModelUtilities
+ .getSubjectOrganizationAssociatedPeople(dataset, subjectEntityURI);
+
+ if (organizationWithAssociatedPeople.getSubEntities() != null) {
+
+ grantURIForAssociatedPeopleToVO = SelectOnModelUtilities
+ .getGrantsForAssociatedPeople(dataset, organizationWithAssociatedPeople.getSubEntities());
+
+ organizationEntity = OrganizationUtilityFunctions.mergeEntityIfShareSameURI(
+ organizationEntity,
+ organizationWithAssociatedPeople);
+ }
+
+ if (allGrantURIToVO.isEmpty() && grantURIForAssociatedPeopleToVO.isEmpty()) {
+
+ if (VisConstants.DataVisMode.JSON.equals(visMode)) {
+ return prepareStandaloneDataErrorResponse();
+ } else {
+ return prepareDataErrorResponse();
+ }
+
+ } else {
+
+ if (VisConstants.DataVisMode.JSON.equals(visMode)) {
+ return prepareStandaloneDataResponse(vitroRequest, organizationEntity);
+ } else {
+ return prepareDataResponse(organizationEntity);
+ }
+ }
+ }
+
+ private Map prepareStandaloneDataErrorResponse() {
+
+ Map fileData = new HashMap();
+
+ fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
+ "application/octet-stream");
+ fileData.put(DataVisualizationController.FILE_CONTENT_KEY,
+ "{\"error\" : \"No Grants for this Organization found in VIVO.\"}");
+ return fileData;
+ }
+
+
+ private Map prepareStandaloneDataResponse(
+ VitroRequest vitroRequest,
+ Entity entity) {
+
+ Map fileData = new HashMap();
+
+ fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
+ "application/octet-stream");
+ fileData.put(DataVisualizationController.FILE_CONTENT_KEY,
+ writeGrantsOverTimeJSON(vitroRequest,
+ entity));
+ return fileData;
+ }
+
+ /**
+ * Provides response when json file containing the grant count over the
+ * years is requested.
+ *
+ * @param entity
+ * @param subentities
+ * @param subOrganizationTypesResult
+ */
+ private Map prepareDataResponse(Entity entity) {
+
+ String entityLabel = entity.getEntityLabel();
+
+ /*
+ * To make sure that null/empty records for entity names do not cause any mischief.
+ * */
+ if (StringUtils.isBlank(entityLabel)) {
+ entityLabel = "no-organization";
+ }
+
+ String outputFileName = UtilityFunctions.slugify(entityLabel)
+ + "_grants-per-year" + ".csv";
+
+
+ Map fileData = new HashMap();
+
+ fileData.put(DataVisualizationController.FILE_NAME_KEY,
+ outputFileName);
+ fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
+ "application/octet-stream");
+ fileData.put(DataVisualizationController.FILE_CONTENT_KEY,
+ getEntityGrantsPerYearCSVContent(entity));
+ return fileData;
+ }
+
+
+ private TemplateResponseValues prepareStandaloneMarkupResponse(VitroRequest vreq,
+ String entityURI) {
+
+ String standaloneTemplate = "entityComparisonOnGrantsStandalone.ftl";
+
+ String organizationLabel = OrganizationUtilityFunctions.getEntityLabelFromDAO(vreq,
+ entityURI);
+
+ Map body = new HashMap();
+ body.put("title", organizationLabel + " - Temporal Graph Visualization");
+ body.put("organizationURI", entityURI);
+ body.put("organizationLocalName", UtilityFunctions.getIndividualLocalName(entityURI, vreq));
+ body.put("vivoDefaultNamespace", vreq.getWebappDaoFactory().getDefaultNamespace());
+ body.put("organizationLabel", organizationLabel);
+
+ return new TemplateResponseValues(standaloneTemplate, body);
+ }
+
+ /**
+ * Function to generate a json file for year <-> grant count mapping.
+ * @param vreq
+ * @param subentities
+ * @param subOrganizationTypesResult
+ */
+ private String writeGrantsOverTimeJSON(VitroRequest vreq,
+ Entity subjectEntity) {
+
+ Gson json = new Gson();
+ Set jsonifiedResponse = new HashSet();
+
+ for (SubEntity subentity : subjectEntity.getSubEntities()) {
+ JsonObject entityJson = new JsonObject(
+ subentity.getIndividualLabel());
+
+ List> yearGrantCount = new ArrayList>();
+
+ for (Map.Entry grantEntry : UtilityFunctions
+ .getYearToActivityCount(subentity.getActivities())
+ .entrySet()) {
+
+ List currentGrantYear = new ArrayList();
+ if (grantEntry.getKey().equals(
+ VOConstants.DEFAULT_GRANT_YEAR)) {
+ currentGrantYear.add(-1);
+ } else {
+ currentGrantYear.add(Integer.parseInt(grantEntry.getKey()));
+ }
+
+ currentGrantYear.add(grantEntry.getValue());
+ yearGrantCount.add(currentGrantYear);
+ }
+
+ entityJson.setYearToActivityCount(yearGrantCount);
+
+ entityJson.setOrganizationTypes(subentity.getEntityTypeLabels());
+
+ entityJson.setEntityURI(subentity.getIndividualURI());
+
+ entityJson.setLastCachedAtDateTime(subentity.getLastCachedAtDateTime());
+
+ if (subentity.getEntityClass().equals(VOConstants.EntityClassType.PERSON)) {
+ entityJson.setVisMode("PERSON");
+ } else if (subentity.getEntityClass().equals(VOConstants.EntityClassType.ORGANIZATION)) {
+ entityJson.setVisMode("ORGANIZATION");
+ }
+
+ jsonifiedResponse.add(entityJson);
+ }
+
+
+ SubjectEntityJSON subjectEntityJSON = new SubjectEntityJSON(subjectEntity.getEntityLabel(),
+ subjectEntity.getEntityURI(),
+ subjectEntity.getParents());
+
+ jsonifiedResponse.add(subjectEntityJSON);
+
+ return json.toJson(jsonifiedResponse);
+ }
+
+ private String getEntityGrantsPerYearCSVContent(Entity entity) {
+
+ StringBuilder csvFileContent = new StringBuilder();
+
+ csvFileContent.append("Entity Name, Grant Count, Entity Type\n");
+
+ for (SubEntity subEntity : entity.getSubEntities()) {
+
+ csvFileContent.append(StringEscapeUtils.escapeCsv(subEntity.getIndividualLabel()));
+ csvFileContent.append(", ");
+ csvFileContent.append(subEntity.getActivities().size());
+ csvFileContent.append(", ");
+
+ String allTypes = StringUtils.join(subEntity.getEntityTypeLabels(), "; ");
+
+ csvFileContent.append(StringEscapeUtils.escapeCsv(allTypes));
+ csvFileContent.append("\n");
+ }
+
+ return csvFileContent.toString();
+ }
+
+
+ @Override
+ public Actions getRequiredPrivileges() {
+ return null;
+ }
+}
diff --git a/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/cached/TemporalPublicationVisualizationRequestHandler.java b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/cached/TemporalPublicationVisualizationRequestHandler.java
new file mode 100644
index 00000000..49a73356
--- /dev/null
+++ b/src/edu/cornell/mannlib/vitro/webapp/visualization/temporalgraph/cached/TemporalPublicationVisualizationRequestHandler.java
@@ -0,0 +1,380 @@
+/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+
+package edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison.cached;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.logging.Log;
+
+import com.google.gson.Gson;
+import com.hp.hpl.jena.query.Dataset;
+
+import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions;
+import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
+import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.DataVisualizationController;
+import edu.cornell.mannlib.vitro.webapp.controller.visualization.VisualizationFrameworkConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VOConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.constants.VisConstants;
+import edu.cornell.mannlib.vitro.webapp.visualization.entitycomparison.OrganizationUtilityFunctions;
+import edu.cornell.mannlib.vitro.webapp.visualization.exceptions.MalformedQueryParametersException;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Activity;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Entity;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.SubEntity;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.json.JsonObject;
+import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.json.SubjectEntityJSON;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.SelectOnModelUtilities;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.UtilityFunctions;
+import edu.cornell.mannlib.vitro.webapp.visualization.visutils.VisualizationRequestHandler;
+
+public class TemporalPublicationVisualizationRequestHandler implements
+ VisualizationRequestHandler {
+
+ @Override
+ public ResponseValues generateStandardVisualization(
+ VitroRequest vitroRequest, Log log, Dataset dataset)
+ throws MalformedQueryParametersException {
+
+
+ String entityURI = vitroRequest
+ .getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
+
+ return generateStandardVisualizationForPublicationTemporalVis(
+ vitroRequest, log, dataset, entityURI);
+ }
+
+ @Override
+ public ResponseValues generateVisualizationForShortURLRequests(
+ Map parameters, VitroRequest vitroRequest, Log log,
+ Dataset dataset) throws MalformedQueryParametersException {
+
+
+ return generateStandardVisualizationForPublicationTemporalVis(
+ vitroRequest, log, dataset, parameters.get(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY));
+
+ }
+
+ private ResponseValues generateStandardVisualizationForPublicationTemporalVis(
+ VitroRequest vitroRequest, Log log, Dataset dataset,
+ String entityURI) throws MalformedQueryParametersException {
+
+ if (StringUtils.isBlank(entityURI)) {
+
+ entityURI = OrganizationUtilityFunctions
+ .getStaffProvidedOrComputedHighestLevelOrganization(
+ log,
+ dataset,
+ vitroRequest);
+
+ }
+
+
+// System.out.println("current models in the system are");
+// for (Map.Entry entry : ConstructedModelTracker.getAllModels().entrySet()) {
+// System.out.println(entry.getKey() + " -> " + entry.getValue().size());
+// }
+//
+ return prepareStandaloneMarkupResponse(vitroRequest, entityURI);
+ }
+
+ private Map getSubjectEntityAndGenerateDataResponse(
+ VitroRequest vitroRequest, Log log, Dataset dataset,
+ String subjectEntityURI, VisConstants.DataVisMode visMode)
+ throws MalformedQueryParametersException {
+
+ Entity organizationEntity = SelectOnModelUtilities
+ .getSubjectOrganizationHierarchy(dataset, subjectEntityURI);
+
+ if (organizationEntity.getSubEntities() == null) {
+
+ if (VisConstants.DataVisMode.JSON.equals(visMode)) {
+ return prepareStandaloneDataErrorResponse();
+ } else {
+ return prepareDataErrorResponse();
+ }
+ }
+
+ Map documentURIForAssociatedPeopleTOVO = new HashMap();
+ Map allDocumentURIToVOs = new HashMap();
+
+ allDocumentURIToVOs = SelectOnModelUtilities.getPublicationsForAllSubOrganizations(dataset, organizationEntity);
+
+ Entity organizationWithAssociatedPeople = SelectOnModelUtilities
+ .getSubjectOrganizationAssociatedPeople(dataset, subjectEntityURI);
+
+ if (organizationWithAssociatedPeople.getSubEntities() != null) {
+
+ documentURIForAssociatedPeopleTOVO = SelectOnModelUtilities
+ .getPublicationsForAssociatedPeople(dataset, organizationWithAssociatedPeople.getSubEntities());
+
+ organizationEntity = OrganizationUtilityFunctions.mergeEntityIfShareSameURI(
+ organizationEntity,
+ organizationWithAssociatedPeople);
+ }
+
+ if (allDocumentURIToVOs.isEmpty() && documentURIForAssociatedPeopleTOVO.isEmpty()) {
+
+ if (VisConstants.DataVisMode.JSON.equals(visMode)) {
+ return prepareStandaloneDataErrorResponse();
+ } else {
+ return prepareDataErrorResponse();
+ }
+
+ } else {
+
+ if (VisConstants.DataVisMode.JSON.equals(visMode)) {
+ return prepareStandaloneDataResponse(vitroRequest, organizationEntity);
+ } else {
+ return prepareDataResponse(organizationEntity);
+ }
+ }
+ }
+
+ /**
+ * Provides response when json file containing the publication count over the
+ * years is requested.
+ *
+ * @param entity
+ * @param subentities
+ * @param subOrganizationTypesResult
+ */
+ private Map prepareDataResponse(Entity entity) {
+
+ String entityLabel = entity.getEntityLabel();
+
+ /*
+ * To make sure that null/empty records for entity names do not cause any mischief.
+ * */
+ if (StringUtils.isBlank(entityLabel)) {
+ entityLabel = "no-organization";
+ }
+
+ String outputFileName = UtilityFunctions.slugify(entityLabel)
+ + "_publications-per-year" + ".csv";
+
+
+ Map fileData = new HashMap();
+
+ fileData.put(DataVisualizationController.FILE_NAME_KEY,
+ outputFileName);
+ fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
+ "application/octet-stream");
+ fileData.put(DataVisualizationController.FILE_CONTENT_KEY,
+ getEntityPublicationsPerYearCSVContent(entity));
+ return fileData;
+ }
+
+ private Map prepareDataErrorResponse() {
+
+ String outputFileName = "no-organization_publications-per-year.csv";
+
+ Map fileData = new HashMap();
+
+ fileData.put(DataVisualizationController.FILE_NAME_KEY,
+ outputFileName);
+ fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
+ "application/octet-stream");
+ fileData.put(DataVisualizationController.FILE_CONTENT_KEY, "");
+ return fileData;
+ }
+
+ private Map prepareStandaloneDataErrorResponse() {
+
+ Map fileData = new HashMap();
+
+ fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
+ "application/octet-stream");
+ fileData.put(DataVisualizationController.FILE_CONTENT_KEY,
+ "{\"error\" : \"No Publications for this Organization found in VIVO.\"}");
+ return fileData;
+ }
+
+ @Override
+ public Map generateDataVisualization(
+ VitroRequest vitroRequest, Log log, Dataset dataset)
+ throws MalformedQueryParametersException {
+
+ String entityURI = vitroRequest
+ .getParameter(VisualizationFrameworkConstants.INDIVIDUAL_URI_KEY);
+
+ /*
+ * This will provide the data in json format mainly used for standalone tmeporal vis.
+ * */
+ if (VisualizationFrameworkConstants.JSON_OUTPUT_FORMAT
+ .equalsIgnoreCase(vitroRequest.getParameter(
+ VisualizationFrameworkConstants.VIS_MODE_KEY))) {
+
+ if (StringUtils.isNotBlank(entityURI)) {
+
+ return getSubjectEntityAndGenerateDataResponse(
+ vitroRequest,
+ log,
+ dataset,
+ entityURI,
+ VisConstants.DataVisMode.JSON);
+ } else {
+
+ return getSubjectEntityAndGenerateDataResponse(
+ vitroRequest,
+ log,
+ dataset,
+ OrganizationUtilityFunctions
+ .getStaffProvidedOrComputedHighestLevelOrganization(
+ log,
+ dataset,
+ vitroRequest),
+ VisConstants.DataVisMode.JSON);
+ }
+
+ } else {
+ /*
+ * This provides csv download files for the content in the tables.
+ * */
+
+ return getSubjectEntityAndGenerateDataResponse(
+ vitroRequest,
+ log,
+ dataset,
+ entityURI,
+ VisConstants.DataVisMode.CSV);
+
+ }
+
+ }
+
+
+ @Override
+ public Object generateAjaxVisualization(VitroRequest vitroRequest, Log log,
+ Dataset dataset) throws MalformedQueryParametersException {
+ throw new UnsupportedOperationException("Entity Pub Count does not provide Ajax Response.");
+ }
+
+ private Map prepareStandaloneDataResponse(
+ VitroRequest vitroRequest,
+ Entity entity) {
+
+ Map fileData = new HashMap();
+
+ fileData.put(DataVisualizationController.FILE_CONTENT_TYPE_KEY,
+ "application/octet-stream");
+ fileData.put(DataVisualizationController.FILE_CONTENT_KEY,
+ writePublicationsOverTimeJSON(vitroRequest,
+ entity));
+ return fileData;
+ }
+
+ private TemplateResponseValues prepareStandaloneMarkupResponse(VitroRequest vreq,
+ String entityURI) {
+
+ String standaloneTemplate = "entityComparisonOnPublicationsStandalone.ftl";
+
+ String organizationLabel = OrganizationUtilityFunctions
+ .getEntityLabelFromDAO(vreq,
+ entityURI);
+
+ Map body = new HashMap();
+ body.put("title", organizationLabel + " - Temporal Graph Visualization");
+ body.put("organizationURI", entityURI);
+ body.put("organizationLocalName", UtilityFunctions.getIndividualLocalName(entityURI, vreq));
+ body.put("vivoDefaultNamespace", vreq.getWebappDaoFactory().getDefaultNamespace());
+ body.put("organizationLabel", organizationLabel);
+
+ return new TemplateResponseValues(standaloneTemplate, body);
+ }
+
+ /**
+ * Function to generate a json file for year <-> publication count mapping.
+ * @param vreq
+ * @param subentities
+ * @param subOrganizationTypesResult
+ */
+ private String writePublicationsOverTimeJSON(VitroRequest vreq,
+ Entity subjectEntity) {
+
+ Gson json = new Gson();
+ Set subEntitiesJson = new HashSet();
+
+ for (SubEntity subentity : subjectEntity.getSubEntities()) {
+
+ JsonObject entityJson = new JsonObject(
+ subentity.getIndividualLabel());
+
+ List> yearPubCount = new ArrayList>();
+
+ for (Map.Entry pubEntry : UtilityFunctions
+ .getYearToActivityCount(subentity.getActivities())
+ .entrySet()) {
+
+ List currentPubYear = new ArrayList();
+ if (pubEntry.getKey().equals(VOConstants.DEFAULT_PUBLICATION_YEAR)) {
+ currentPubYear.add(-1);
+ } else {
+ currentPubYear.add(Integer.parseInt(pubEntry.getKey()));
+ }
+
+ currentPubYear.add(pubEntry.getValue());
+ yearPubCount.add(currentPubYear);
+ }
+
+ entityJson.setYearToActivityCount(yearPubCount);
+
+ entityJson.setOrganizationTypes(subentity.getEntityTypeLabels());
+
+ entityJson.setEntityURI(subentity.getIndividualURI());
+
+ entityJson.setLastCachedAtDateTime(subentity.getLastCachedAtDateTime());
+
+ if (subentity.getEntityClass().equals(VOConstants.EntityClassType.PERSON)) {
+ entityJson.setVisMode("PERSON");
+ } else if (subentity.getEntityClass().equals(VOConstants.EntityClassType.ORGANIZATION)) {
+ entityJson.setVisMode("ORGANIZATION");
+ }
+
+ subEntitiesJson.add(entityJson);
+ }
+
+ SubjectEntityJSON subjectEntityJSON = new SubjectEntityJSON(subjectEntity.getEntityLabel(),
+ subjectEntity.getEntityURI(),
+ subjectEntity.getParents());
+
+ subEntitiesJson.add(subjectEntityJSON);
+
+ return json.toJson(subEntitiesJson);
+ }
+
+ private String getEntityPublicationsPerYearCSVContent(Entity entity) {
+
+ StringBuilder csvFileContent = new StringBuilder();
+
+ csvFileContent.append("Entity Name, Publication Count, Entity Type\n");
+
+ for (SubEntity subEntity : entity.getSubEntities()) {
+
+ csvFileContent.append(StringEscapeUtils.escapeCsv(subEntity.getIndividualLabel()));
+ csvFileContent.append(", ");
+ csvFileContent.append(subEntity.getActivities().size());
+ csvFileContent.append(", ");
+
+ String allTypes = StringUtils.join(subEntity.getEntityTypeLabels(), "; ");
+
+ csvFileContent.append(StringEscapeUtils.escapeCsv(allTypes));
+ csvFileContent.append("\n");
+ }
+ return csvFileContent.toString();
+ }
+
+ @Override
+ public Actions getRequiredPrivileges() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
\ No newline at end of file