diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/MenuManagementEdit.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/MenuManagementEdit.java new file mode 100644 index 000000000..67fde50b2 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/MenuManagementEdit.java @@ -0,0 +1,475 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.edit; + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import javax.servlet.RequestDispatcher; +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.fileupload.FileItem; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.OntModelSpec; +import com.hp.hpl.jena.rdf.model.Literal; +import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.ResourceFactory; +import com.hp.hpl.jena.rdf.model.StmtIterator; +import com.hp.hpl.jena.shared.Lock; +import com.hp.hpl.jena.vocabulary.RDF; +import com.hp.hpl.jena.rdf.model.RDFNode; + + +import edu.cornell.mannlib.vedit.beans.LoginStatusBean; +import edu.cornell.mannlib.vitro.webapp.beans.UserAccount; +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; +import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet; +import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfiguration; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditN3Generator; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditN3Utils; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.processEdit.EditSubmission; +import edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest.FileUploadServletRequest; +import edu.cornell.mannlib.vitro.webapp.utils.MailUtil; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; + +/** + *Process edits from display model editing, so form should submit to this page which should + *then process the parameters and then make the necessary changes to the model. + */ +public class MenuManagementEdit extends VitroHttpServlet { + private static final String CMD_PARAM = "CMD"; + private final static String EDIT_FORM = "testMenuManagement.ftl"; + private final static String EDIT_PARAM_VALUE = "Edit"; + private final static String DELETE_PARAM_VALUE = "Remove"; + private final static String ADD_PARAM_VALUE = "Add"; + private final static String REORDER_PARAM_VALUE = "Reorder"; + private final static String REDIRECT_URL = "/individual?uri=http%3A%2F%2Fvitro.mannlib.cornell.edu%2Fontologies%2Fdisplay%2F1.1%23DefaultMenu&switchToDisplayModel=true"; + private Model removeStatements = ModelFactory.createDefaultModel(); + private Model addStatements = ModelFactory.createDefaultModel(); + + @Override + protected void doPost(HttpServletRequest rawRequest, HttpServletResponse resp) + throws ServletException, IOException { + /* + RequestDispatcher rd = request + .getRequestDispatcher("/edit/postEditCleanUp.jsp"); + rd.forward(request, resp);*/ + VitroRequest vreq = new VitroRequest(rawRequest); + String command = getCommand(vreq); + processCommand(command, vreq); + //Need to redirect correctly + //if(!isReorder(command)){ + //RequestDispatcher rd = rawRequest.getRequestDispatcher(REDIRECT_URL); + //rd.forward(rawRequest, resp); + //} + } + + + public String getCommand(VitroRequest vreq) { + String command = vreq.getParameter(CMD_PARAM); + return command; + } + + public boolean isEdit(String command) { + return command.equals(EDIT_PARAM_VALUE); + } + + public boolean isAdd(String command) { + return command.equals(ADD_PARAM_VALUE); + } + + public boolean isDelete(String command) { + return command.equals(DELETE_PARAM_VALUE); + } + + public boolean isReorder(String command) { + return command.equals(REORDER_PARAM_VALUE); + } + + public boolean isHomePage(String uri) { + return uri.equals(DisplayVocabulary.DISPLAY_NS + "Home"); + } + + //Parameter retrieval is identical, but in one case an entirey new menu item needs to be created + //along with a new page + public void processCommand(String command, VitroRequest vreq) { + //Get parameters for menu item being edited + String menuItem = vreq.getParameter("menuItem"); + OntModel displayModel = getDisplayModel(vreq); + //if Add, then create new menu item and new page elements, and use the values above + + if(isAdd(command)){ + processAdd(menuItem, displayModel, command, vreq); + } + //Otherwise use existing resource + else if(isEdit(command)) { + processEdit(menuItem, displayModel, command, vreq); + + } else if(isDelete(command)) { + processDelete(menuItem, displayModel, command, vreq); + } else if(isReorder(command)) { + processReorder(displayModel, vreq); + } + + //Edits to model occur here + displayModel.enterCriticalSection(Lock.WRITE); + try { + System.out.println("Statement to be revmoed are "); + removeStatements.write(System.out, "N3"); + + System.out.println("Statements to be added are "); + addStatements.write(System.out, "N3"); + //displayModel.remove(removeStatements); + //displayModel.add(addStatements); + + } catch(Exception ex) { + + }finally { + displayModel.leaveCriticalSection(); + } + + } + + private void processReorder(OntModel displayModel, VitroRequest vreq) { + //Get the new menu positions for all the elements + + } + + + private void processDelete(String menuItem, OntModel displayModel, + String command, VitroRequest vreq) { + Resource menuItemResource = getExistingMenuItem(menuItem, displayModel); + Resource pageResource = getExistingPage(menuItemResource, displayModel); + //What statements should be added and removed + removeStatements = getStatementsToRemove(command, displayModel, menuItemResource, pageResource); + //No statements to add + } + + + private void processEdit(String menuItem, OntModel displayModel, + String command, VitroRequest vreq) { + Resource menuItemResource = getExistingMenuItem(menuItem, displayModel); + Resource pageResource = getExistingPage(menuItemResource, displayModel); + //What statements should be added and removed + removeStatements = getStatementsToRemove(command, displayModel, menuItemResource, pageResource); + addStatements = getStatementsToAdd(vreq, command, displayModel, menuItemResource, pageResource); + } + + + private void processAdd(String menuItem, OntModel displayModel, String command, VitroRequest vreq) { + Resource menuItemResource = createNewMenuItem(menuItem, displayModel); + Resource pageResource = createNewPage(menuItemResource, displayModel); + associateMenuItemToPage(menuItemResource, pageResource); + //no statements to remove, just to add + addStatements = getStatementsToAdd(vreq, command, displayModel, menuItemResource, pageResource); + } + + //Get last menu item positin + private int getLastPosition(OntModel displayModel) { + StmtIterator positions = displayModel.listStatements(null, DisplayVocabulary.MENU_POSITION, (RDFNode) null); + int maxPosition = 1; + while(positions.hasNext()) { + int pos = positions.nextStatement().getInt(); + if(pos > maxPosition) { + maxPosition = pos; + } + } + return maxPosition; + } + + //Statements to add - should not be called for delete + private Model getStatementsToAdd(VitroRequest vreq, String command, OntModel displayModel, + Resource menuItemResource, Resource pageResource) { + Model addModel = ModelFactory.createDefaultModel(); + if(isAdd(command)) { + generateStatementsForAdd(addModel, displayModel, menuItemResource, pageResource); + } + generateStatementsForUpdates(vreq, addModel, displayModel, menuItemResource, pageResource); + + return addModel; + } + + //These statements need to be added based on parameter values + //This is a simple overwrite, no checking for existing values whatsoever + private void generateStatementsForUpdates(VitroRequest vreq, Model addModel, + OntModel displayModel, Resource menuItemResource, + Resource pageResource) { + + updateMenuName(addModel, vreq, menuItemResource, pageResource); + updateUrl(addModel, vreq, pageResource); + updateTemplate(addModel, vreq, pageResource); + updateDataGetter(addModel, displayModel, vreq, pageResource); + } + + + private void updateDataGetter(Model addModel, OntModel displayModel, VitroRequest vreq, + Resource pageResource) { + //Selected class group + String classGroup = vreq.getParameter("selectClassGroup"); + //Selected class + + String allClasses = vreq.getParameter("allSelected"); + //For this, need to check whether All or not b/c this will identify the data getter type + //There should be a "specify data getter" method that specifices the data getter + Resource dataGetterResource = getDataGetter(vreq, addModel, displayModel, pageResource); + //TODO: if null, throw an exception or error + if(dataGetterResource != null) { + Resource classGroupResource = ResourceFactory.createResource(classGroup); + //Whatever the data getter might be assign class group + addModel.add(addModel.createStatement( + dataGetterResource, + ResourceFactory.createProperty(DisplayVocabulary.FOR_CLASSGROUP), + classGroupResource)); + //If "All selected" then use class group else use individuals for classes + Model dataGetterModel = ModelFactory.createDefaultModel(); + if(allClasses != null && !allClasses.isEmpty()) { + dataGetterModel = getClassGroupDataGetter(vreq, dataGetterResource, addModel, displayModel); + } else { + dataGetterModel = getIndividualsForClassesDataGetter(vreq, dataGetterResource, addModel, displayModel); + } + + addModel.add(dataGetterModel); + + } + + } + + private Model getIndividualsForClassesDataGetter(VitroRequest vreq, Resource dataGetterResource, + Model addModel, OntModel displayModel) { + String[] selectedClasses = vreq.getParameterValues("selectedClasses"); + Model dgModel = ModelFactory.createDefaultModel(); + dgModel.add(dgModel.createStatement(dataGetterResource, RDF.type, DisplayVocabulary.CLASSINDIVIDUALS_PAGE_TYPE)); + for(String classUri: selectedClasses) { + dgModel.add(dgModel.createStatement( + dataGetterResource, + ResourceFactory.createProperty(DisplayVocabulary.GETINDIVIDUALS_FOR_CLASS), + ResourceFactory.createResource(classUri))); + } + return dgModel; + } + + private Model getClassGroupDataGetter(VitroRequest vreq, Resource dataGetterResource, Model addModel, + OntModel displayModel) { + Model dgModel = ModelFactory.createDefaultModel(); + dgModel.add(dgModel.createStatement(dataGetterResource, RDF.type, DisplayVocabulary.CLASSGROUP_PAGE_TYPE)); + return dgModel; + } + + //For now returning the first "data getter" we have - this will be a more complex operation + //if multiple data getters possible as then will have to determine which data getter required + //Based on whether this is an add or edit operation, return the appropriate data getter resource + //If add, then a new data getter has been created but not yet added to the display model + //If edit, then data getter already exists + private Resource getDataGetter(VitroRequest vreq, Model addModel, OntModel displayModel, Resource pageResource) { + String command = vreq.getParameter(CMD_PARAM); + return getDataGetter(command, addModel, displayModel, pageResource); + } + + private Resource getDataGetter(String command, Model addModel, OntModel displayModel, Resource pageResource) { + StmtIterator dataGetterIt = null; + //if addition, we havent' committed the data getter changes yet so the resource will be different + if(isAdd(command)) { + dataGetterIt = addModel.listStatements( + pageResource, + ResourceFactory.createProperty(DisplayVocabulary.HAS_DATA_GETTER), + (RDFNode) null); + } else { + dataGetterIt = displayModel.listStatements( + pageResource, + ResourceFactory.createProperty(DisplayVocabulary.HAS_DATA_GETTER), + (RDFNode) null); + } + + if(dataGetterIt != null && dataGetterIt.hasNext()) { + return dataGetterIt.nextStatement().getResource(); + } + return null; + } + + private Resource getDataGetterFromDisplayModel(Resource pageResource, OntModel displayModel) { + StmtIterator dataGetterIt = displayModel.listStatements( + pageResource, + ResourceFactory.createProperty(DisplayVocabulary.HAS_DATA_GETTER), + (RDFNode) null); + if(dataGetterIt != null && dataGetterIt.hasNext()) { + return dataGetterIt.nextStatement().getResource(); + } + return null; + } + + private void updateTemplate(Model addModel, VitroRequest vreq, + Resource pageResource) { + String selectedTemplate = vreq.getParameter("selectedTemplate"); + if(selectedTemplate.equals("custom")) { + String customTemplate = vreq.getParameter("customTemplate"); + addModel.add(addModel.createStatement(pageResource, DisplayVocabulary.REQUIRES_BODY_TEMPLATE, customTemplate)); + + } + + } + + private void updateUrl(Model addModel, VitroRequest vreq, + Resource pageResource) { + // TODO Auto-generated method stub + String prettyUrl = vreq.getParameter("prettyUrl"); + addModel.add(addModel.createStatement(pageResource, DisplayVocabulary.URL_MAPPING, prettyUrl)); + } + + private void updateMenuName(Model addModel, VitroRequest vreq, + Resource menuItemResource, Resource pageResource) { + String menuName = vreq.getParameter("menuName"); + addModel.add(addModel.createStatement(menuItemResource, DisplayVocabulary.LINK_TEXT, menuName)); + addModel.add(addModel.createStatement( + pageResource, + ResourceFactory.createProperty(DisplayVocabulary.TITLE), + menuName)); + + } + + private void generateStatementsForAdd(Model addModel, OntModel displayModel, Resource menuItemResource, Resource pageResource) { + //Need to generate the menu item and page in their entirety + //Menu item + addModel.add(addModel.createStatement(menuItemResource, RDF.type, DisplayVocabulary.NAVIGATION_ELEMENT)); + addModel.add(addModel.createStatement(menuItemResource, + DisplayVocabulary.MENU_POSITION, + addModel.createTypedLiteral(getLastPosition(displayModel)))); + //page resource, type, title and url mapping, and what data getter associated + addModel.add(addModel.createStatement(pageResource, RDF.type, DisplayVocabulary.PAGE_TYPE)); + //Need to create a data getter + Model dataGetterStatements = generateDataGetter(pageResource, displayModel); + addModel.add(dataGetterStatements); + } + + + + //Get statements for data getter + private Model generateDataGetter(Resource pageResource, OntModel displayModel) { + Model dataGetterModel = ModelFactory.createDefaultModel(); + String dataGetterUri = generateDataGetterUri(pageResource, displayModel); + Resource dataGetter = ResourceFactory.createResource(dataGetterUri); + dataGetterModel.add(dataGetterModel.createStatement( + pageResource, + ResourceFactory.createProperty(DisplayVocabulary.HAS_DATA_GETTER), + dataGetter)); + + return dataGetterModel; + } + + private String generateDataGetterUri(Resource pageResource, OntModel displayModel) { + String dataGetterUriBase = pageResource.getURI() + "-dataGetter"; + String dataGetterUri = dataGetterUriBase; + int counter = 0; + while(displayModel.getResource(dataGetterUriBase) != null) { + dataGetterUri = dataGetterUriBase + counter; + counter++; + } + return dataGetterUri; + } + + //What statements need to be removed + private Model getStatementsToRemove(String command, OntModel displayModel, + Resource menuItemResource, Resource pageResource) { + Model removeModel = ModelFactory.createDefaultModel(); + //if delete then remove all statements pertaining to any of the objects + if(isEdit(command)) { + //remove top level properties + removeModel.add(displayModel.listStatements( + pageResource, + ResourceFactory.createProperty(DisplayVocabulary.TITLE), + (RDFNode) null)); + removeModel.add(displayModel.listStatements( + pageResource, + DisplayVocabulary.URL_MAPPING, + (RDFNode) null)); + removeModel.add(displayModel.listStatements( + pageResource, + DisplayVocabulary.URL_MAPPING, + (RDFNode) null)); + //remove data getter properties - the link between page and data getter remains + Resource dataGetter = getDataGetterFromDisplayModel(pageResource, displayModel); + removeModel.add(displayModel.listStatements(dataGetter, null, (RDFNode) null)); + } + + if(isDelete(command)) { + //Remove all statements from data getter, page and menu item + Resource dataGetter = getDataGetterFromDisplayModel(pageResource, displayModel); + removeModel.add(displayModel.listStatements(dataGetter, null, (RDFNode) null)); + removeModel.add(displayModel.listStatements(pageResource, null, (RDFNode) null)); + removeModel.add(displayModel.listStatements(menuItemResource, null, (RDFNode) null)); + //Also remove any statements where menu item resource is an object + removeModel.add(displayModel.listStatements(null, null, menuItemResource)); + } + return removeModel; + } + + private Resource getExistingPage(Resource menuItem, OntModel displayModel) { + StmtIterator pageIt = displayModel.listStatements(menuItem, DisplayVocabulary.TO_PAGE, (RDFNode) null); + if(pageIt.hasNext()) { + return pageIt.nextStatement().getResource(); + } + return null; + } + + private Resource getExistingMenuItem(String menuItem, OntModel displayModel) { + return displayModel.getResource(menuItem); + } + + //What should page uri be? for now menuItem + page + private Resource createNewPage(Resource menuItem, OntModel displayModel) { + return ResourceFactory.createResource(menuItem.getURI() + "Page"); + } + + private Resource createNewMenuItem(String menuName, OntModel displayModel) { + return ResourceFactory.createResource(generateNewMenuItemUri(menuName, displayModel)); + } + + //Create connection + private void associateMenuItemToPage(Resource menuItemResource, Resource pageResource) { + menuItemResource.addProperty(DisplayVocabulary.TO_PAGE, pageResource); + } + + //Add to model + + + //TODO: Check if this is an appropriate mechanism for generating menu uri + private String generateNewMenuItemUri (String menuName, OntModel displayModel) { + String menuUriBase = DisplayVocabulary.DISPLAY_NS + menuName.replaceAll(" ", "") + "MenuItem"; + String menuUri = menuUriBase; + int counter = 0; + while(displayModel.getResource(menuUri) != null) { + menuUri = menuUriBase + counter; + counter++; + } + return menuUri; + } + + //This should be in write mode + //TODO: find better way of doing this + private OntModel getDisplayModel(VitroRequest vreq) { + if(vreq.getAttribute(vreq.SPECIAL_WRITE_MODEL) != null) { + return vreq.getWriteModel(); + } else { + return (OntModel) getServletContext().getAttribute("http://vitro.mannlib.cornell.edu/default/vitro-kb-displayMetadata"); + } + } + + Log log = LogFactory.getLog(MenuManagementEdit.class); +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/MenuManagementController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/MenuManagementController.java new file mode 100644 index 000000000..84117f285 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/MenuManagementController.java @@ -0,0 +1,356 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.controller.freemarker; + +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; +import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.usepages.ManageMenus; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; +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.dao.DisplayVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.ontology.Individual; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.ResourceFactory; +import com.hp.hpl.jena.rdf.model.Statement; +import com.hp.hpl.jena.rdf.model.StmtIterator; +import com.hp.hpl.jena.vocabulary.RDF; + +/* + * Custom controller for menu management. This will be replaced later once N3 Editing + * has been successfully refactored and integrated with menu management. + */ +public class MenuManagementController extends FreemarkerHttpServlet { + private static final Log log = LogFactory.getLog(MenuManagementController.class); + protected final static String SUBMIT_FORM = "/processEditDisplayModel"; + + protected final static String EDIT_FORM = "testMenuManagement.ftl"; + protected final static String CMD_PARAM = "cmd"; + protected final static String EDIT_PARAM_VALUE = "edit"; + protected final static String DELETE_PARAM_VALUE = "delete"; + protected final static String ADD_PARAM_VALUE = "add"; + //since forwarding from edit Request dispatch for now + + protected final static String ITEM_PARAM = "objectUri"; + + public final static Actions REQUIRED_ACTIONS = new Actions(new ManageMenus()); + + @Override + protected Actions requiredActions(VitroRequest vreq) { + return REQUIRED_ACTIONS; + } + + @Override + protected ResponseValues processRequest(VitroRequest vreq) { + //Parameters should include the menu item being edited/added/removed/reordered + Map data = new HashMap(); + + + //if no menu item passed, return empty data + //TODO: Check if exception needs to be thrown + + + String cmd = getCommand(vreq); + + if(cmd.equals(ADD_PARAM_VALUE)) { + data = processAddMenuItem(vreq); + } else if(cmd.equals(EDIT_PARAM_VALUE)) { + data = processEditMenuItem(vreq); + } else if(cmd.equals(DELETE_PARAM_VALUE)) { + data = processDeleteMenuItem(vreq); + } else { + //Throw some kind of error or do nothing + } + //Form url submission + data.put("formUrls", SUBMIT_FORM); + return new TemplateResponseValues(EDIT_FORM, data); + + } + + //Based on parameters, ascertain command + private String getCommand(VitroRequest vreq) { + String command = vreq.getParameter(CMD_PARAM); + if(command == null || command.isEmpty()) { + //Check if objectUri null, if exists then edit otherewise add + String objectUri = vreq.getParameter("objectUri"); + if(objectUri == null || objectUri.isEmpty()) { + command = ADD_PARAM_VALUE; + } else { + command = EDIT_PARAM_VALUE; + } + } + return command; + } + + private Map processDeleteMenuItem(VitroRequest vreq) { + String menuItem = getMenuItem(vreq); + Map data = new HashMap(); + data.put("menuAction", "Remove"); + this.getMenuItemData(vreq, menuItem, data); + this.getPageData(vreq, data); + return data; + } + + private Map processAddMenuItem(VitroRequest vreq) { + Map data = new HashMap(); + data.put("menuAction", "Add"); + //Generate empty values for fields + data.put("menuName", ""); + data.put("prettyUrl", ""); + data.put("classGroups", this.getClassGroups()); + data.put("selectedTemplateType", "default"); + //defaults to regular class group page + data.put("associatedPage", ""); + return data; + } + + private Map processEditMenuItem(VitroRequest vreq) { + Map data = new HashMap(); + if(!hasMenuItem(vreq)) { + return data; + } + //Get parameter for menu item + String menuItem = getMenuItem(vreq); + + + data.put("menuAction", "Edit"); + //Get All class groups + data.put("classGroups", this.getClassGroups()); + + + //Get data for menu item and associated page + this.getMenuItemData(vreq, menuItem, data); + this.getPageData(vreq, data); + return data; + } + + private String getMenuItem(VitroRequest vreq) { + return vreq.getParameter(ITEM_PARAM); + } + + private boolean hasMenuItem(VitroRequest vreq) { + return (getMenuItem(vreq) != null && !getMenuItem(vreq).isEmpty()); + } + + + /* + * Sparql queries and data + */ + + + + private void getMenuItemData(VitroRequest vreq, String menuItem, Map data) { + OntModel writeModel = vreq.getWriteModel(); + Individual item = writeModel.getIndividual(menuItem); + if(item != null) { + StmtIterator it = item.listProperties(DisplayVocabulary.LINK_TEXT); + + if(it.hasNext()) { + String linkText = it.nextStatement().getLiteral().getString(); + log.debug("Link text retrieved is " + linkText); + //stored as menu name + data.put("menuName", linkText); + } + StmtIterator pageIt = item.listProperties(DisplayVocabulary.TO_PAGE); + if(pageIt.hasNext()) { + Resource pageResource = pageIt.nextStatement().getResource(); + String pageUri = pageResource.getURI(); + log.debug("Page URI is " + pageUri); + data.put("page", pageUri); + } + } + + + } + + //pretty-url, also type + private void getPageData(VitroRequest vreq, Map data) { + String pageUri = (String) data.get("page"); + OntModel writeModel = vreq.getWriteModel(); + Individual page = writeModel.getIndividual(pageUri); + if(page != null) { + StmtIterator urlMappingIt = page.listProperties(DisplayVocabulary.URL_MAPPING); + + if(urlMappingIt.hasNext()) { + String urlMapping = urlMappingIt.nextStatement().getLiteral().getString(); + log.debug("URL Mapping retrieved is " + urlMapping); + data.put("prettyUrl", urlMapping); + } + //If home page, then specify? + this.checkHomePage(writeModel, page, data); + //Check if custom template required and if so save the info, + this.getCustomTemplate(writeModel, page, data); + //retrieve information for page based on the data getter, with class group and individuals for classes getting different information + //the browse page does not have a "data getter" + this.getPageDataGetterInfo(writeModel, page, data); + //This is an all statement iterator + log.debug("Debug statements: all statements in model for debugger"); + StmtIterator debugIt = writeModel.listStatements(page, null, (RDFNode) null); + while(debugIt.hasNext()) { + log.debug("Statement: " + debugIt.nextStatement().toString()); + } + } + } + + + private void checkHomePage(OntModel writeModel, Individual page, + Map data) { + StmtIterator homePageIt = writeModel.listStatements(page, RDF.type, ResourceFactory.createResource(DisplayVocabulary.HOME_PAGE_TYPE)); + if (homePageIt.hasNext()) { + data.put("isHomePage", true); + } + } + + //If custom template included, get that information + private void getCustomTemplate(OntModel writeModel, Individual page, + Map data) { + StmtIterator customTemplateIt = writeModel.listStatements(page, DisplayVocabulary.REQUIRES_BODY_TEMPLATE, (RDFNode) null); + if (customTemplateIt.hasNext()) { + String customTemplate = customTemplateIt.nextStatement().getLiteral().getString(); + data.put("selectedTemplateType", "custom"); + data.put("customTemplate", customTemplate); + } else { + data.put("selectedTemplateType", "default"); + } + } + + //Get data getter related info + //All items will have data getter except for Browse or Home page + //Home can be edited but not removed + private void getPageDataGetterInfo(OntModel writeModel, Resource page, Map data) { + //Alternative is to do this via sparql query + StmtIterator dataGetterIt = writeModel.listStatements(page, ResourceFactory.createProperty(DisplayVocabulary.HAS_DATA_GETTER), (RDFNode) null); + while(dataGetterIt.hasNext()) { + Statement dataGetterStmt = dataGetterIt.nextStatement(); + Resource dataGetter = dataGetterStmt.getResource(); + //Get types of data getter + StmtIterator dataGetterTypes = writeModel.listStatements(dataGetter, RDF.type, (RDFNode) null); + while(dataGetterTypes.hasNext()) { + String dataGetterType = dataGetterTypes.nextStatement().getResource().getURI(); + if(dataGetterType.equals(DisplayVocabulary.CLASSGROUP_PAGE_TYPE)) { + this.retrieveClassGroupPage(writeModel, dataGetter, data); + } else if(dataGetterType.equals(DisplayVocabulary.CLASSINDIVIDUALS_PAGE_TYPE)) { + this.retrieveIndividualsForClassesPage(writeModel, dataGetter, data); + } else { + //Not sure what to do here + } + } + } + + } + + private void retrieveIndividualsForClassesPage(OntModel writeModel, + Resource dataGetter, Map data) { + data.put("isIndividualsForClassesPage", true); + //Get the classes and put them here + this.getClassesForDataGetter(writeModel, dataGetter, data); + //Also save the class group for display + this.getClassGroupForDataGetter(writeModel, dataGetter, data); + + } + + private void retrieveClassGroupPage(OntModel writeModel, Resource dataGetter, + Map data) { + //This is a class group page so + data.put("isClassGroupPage", true); + data.put("includeAllClasses", true); + //Get the class group + this.getClassGroupForDataGetter(writeModel, dataGetter, data); + + } + + private void getClassesForDataGetter(OntModel writeModel, Resource dataGetter, + Map data) { + VClassGroupCache vcgc = VClassGroupCache.getVClassGroupCache(getServletContext()); + + StmtIterator classesIt = writeModel.listStatements(dataGetter, + ResourceFactory.createProperty(DisplayVocabulary.GETINDIVIDUALS_FOR_CLASS), + (RDFNode) null); + //TODO: Copied from IndividualsForClassesDataGetter, perhaps could reuse in separate method + VClassGroup classesGroup = new VClassGroup(); + classesGroup.setURI("displayClasses"); + List vClasses = new ArrayList(); + + while(classesIt.hasNext()) { + String classUri = classesIt.nextStatement().getResource().getURI(); + VClass vclass = vcgc.getCachedVClass(classUri); + if(vclass != null) { + + log.debug("VClass does exist for " + classUri + " and entity count is " + vclass.getEntityCount()); + vClasses.add(vclass); + } else { + log.debug("Vclass " + classUri + " does not exist in the cache"); + log.error("Error occurred, vclass does not exist for this uri " + classUri); + //Throw exception here + } + } + data.put("includeClasses", classesGroup); + //TODO: Check if classes included are equivalent to classes in class group, and set "includeAllClasses" to true if so + + } + + //TODO: Create method to get restricted classes + //Get restrict classes - specifically internal class + //VClassGroup restrictClassesGroup = new VClassGroup(); + //restrictClassesGroup.setURI("restrictClasses"); + //List restrictVClasses = new ArrayList(); + + //Get the class page + private void getClassGroupForDataGetter(OntModel writeModel, Resource dataGetter, + Map data) { + StmtIterator classGroupIt = writeModel.listStatements(dataGetter, + ResourceFactory.createProperty(DisplayVocabulary.FOR_CLASSGROUP), + (RDFNode) null); + //Assuming just one class group per page/item + if(classGroupIt.hasNext()) { + String classGroup = classGroupIt.nextStatement().getResource().getURI(); + VClassGroup vclassGroup = getClassGroup(classGroup); + data.put("classGroup", vclassGroup); + data.put("associatedPage", vclassGroup.getPublicName()); + data.put("associatedPageURI", vclassGroup.getURI()); + } + + } + + //Get classes in class group, useful in case of edit + private VClassGroup getClassGroup(String classGroupUri) { + VClassGroupCache vcgc = VClassGroupCache.getVClassGroupCache(getServletContext()); + VClassGroup group = vcgc.getGroup(classGroupUri); + return group; + } + + //Get All VClass Groups + private List> getClassGroups() { + //Wanted this to be + VClassGroupCache vcgc = VClassGroupCache.getVClassGroupCache(getServletContext()); + List vcgList = vcgc.getGroups(); + //For now encoding as hashmap with label and URI as trying to retrieve class group + //results in errors for some reason + //TODO: Check how to do this properly + List> classGroups = new ArrayList>(); + for(VClassGroup vcg: vcgList) { + HashMap hs = new HashMap(); + hs.put("publicName", vcg.getPublicName()); + hs.put("URI", vcg.getURI()); + classGroups.add(hs); + } + return classGroups; + } + + + + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java index b5087a758..8838cea93 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/DisplayVocabulary.java @@ -42,8 +42,9 @@ public class DisplayVocabulary { public static final String FOR_CLASSGROUP = NS + "forClassGroup"; public static final String CLASS_INTERSECTION = NS + "intersectsWithClass"; public static final String HAS_CLASS_INTERSECTION = NS + "hasClassIntersection"; - + public static final String ITEM_TO_PAGE = NS + "toPage"; /**Data Getter object properties **/ + public static final String HAS_DATA_GETTER = NS + "hasDataGetter"; public static final String GETINDIVIDUALS_FOR_CLASS = NS + "getIndividualsForClass"; public static final String RESTRICT_RESULTS_BY = NS + "restrictResultsByClass"; @@ -54,6 +55,7 @@ public class DisplayVocabulary { public static final DatatypeProperty REQUIRES_BODY_TEMPLATE = m_model.createDatatypeProperty(NS + "requiresBodyTemplate"); //bk392 for extracting properties beyond context nodes. public static final DatatypeProperty QUERY_FOR_EDUCATIONAL_TRAINING = m_model.createDatatypeProperty(NS + "queryForEducationalTraining"); + public static final DatatypeProperty LINK_TEXT = m_model.createDatatypeProperty(NS + "linkText"); /* URIs for storing menu.n3 */ public static final String MENU_TEXT_RES = NS + "MenuText"; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java index 69f329c0a..10759ce53 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationVTwo.java @@ -472,70 +472,6 @@ public class EditConfigurationVTwo { this.sparqlForExistingUris = sparqlForExistingUris; } - public static List JsonArrayToStringList(JSONArray jarray){ - ArrayList outv = new ArrayList(); - if( jarray != null ){ - for( int i = 0; i< jarray.length(); i++){ - try{ - outv.add(jarray.getString(i)); - }catch(JSONException je){} - } - } - return outv; - } - - public static Map JsonObjToMap(JSONObject jobj){ - HashMap outv = new HashMap(); - if( jobj != null ){ - Iterator keyIt = jobj.keys(); - while( keyIt.hasNext()){ - try{ - String key = (String)keyIt.next(); - outv.put(key,jobj.getString(key)); - }catch(JSONException je){ } - } - } - return outv; - } - - //Like above except returning Map with multiple values possible for key - //Are we doing this anymore? - public static Map> JsonObjToMultiValueMap(JSONObject jobj){ - HashMap> outv = new HashMap>(); - if( jobj != null ){ - Iterator keyIt = jobj.keys(); - while( keyIt.hasNext()){ - try{ - String key = (String)keyIt.next(); - JSONArray jsonArray = jobj.getJSONArray(key); - int len = jsonArray.length(); - List valueString = new ArrayList(); - for(int i = 0; i < len ; i++) { - valueString.add(jsonArray.get(i).toString()); - } - - outv.put(key,valueString); - }catch(JSONException je){ } - } - } - return outv; - } - public static Map JsonObjToMapOfFields(JSONObject jobj){ - HashMap outv = new HashMap(); - if( jobj != null ){ - Iterator keyIt = jobj.keys(); - while( keyIt.hasNext()){ - try{ - String key = (String)keyIt.next(); - JSONObject obj = jobj.getJSONObject(key); - FieldVTwo field = new FieldVTwo(obj, key); - outv.put(key, field); - }catch(JSONException je){ } - } - } - return outv; - } - public Map> getN3ForFields(){ return fieldsToMap( getFields() ); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/FieldVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/FieldVTwo.java index 7cd174494..6c6d1849e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/FieldVTwo.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/FieldVTwo.java @@ -119,64 +119,12 @@ public class FieldVTwo { private EditElementVTwo editElement=null;; /* *********************** Constructors ************************** */ - - public FieldVTwo(String config, String varName) { - name=varName; - JSONObject jsonObj = null; - try{ - jsonObj = new JSONObject(config); - }catch (JSONException je){ - throw new Error(je); - } - originalJson = config; - setValuesFromJson(jsonObj, varName); - } - - public FieldVTwo(JSONObject obj, String varName) { - setValuesFromJson(obj, varName); - } - + public FieldVTwo() {} private static String[] parameterNames = {"editElement","newResource","validators","optionsType","predicateUri","objectClassUri","rangeDatatypeUri","rangeLang","literalOptions","assertions"}; static{ Arrays.sort(parameterNames); } - private void setValuesFromJson(JSONObject obj, String fieldName){ - try{ - this.name = fieldName; - setNewResource(obj.getBoolean("newResource")); - validators = EditConfigurationVTwo.JsonArrayToStringList(obj.getJSONArray("validators")); - setOptionsType(obj.getString("optionsType")); - predicateUri = obj.getString("predicateUri"); - objectClassUri = obj.getString("objectClassUri"); - - rangeDatatypeUri = obj.getString("rangeDatatypeUri"); - if( rangeDatatypeUri != null && rangeDatatypeUri.trim().length() == 0) - rangeDatatypeUri = null; - - rangeLang = obj.getString("rangeLang"); - if( rangeLang != null && rangeLang.trim().length() == 0) - rangeLang = null; - - setLiteralOptions(obj.getJSONArray("literalOptions")); - setAssertions(EditConfigurationVTwo.JsonArrayToStringList(obj.getJSONArray("assertions"))); - - setEditElement( obj, fieldName); - - //check for odd parameters - JSONArray names = obj.names(); - int size = names.length(); - for(int i=0 ; i < size ; i++ ){ - String name = (String)names.optString(i); - if( Arrays.binarySearch(parameterNames, name) < 0 ) - log.debug("setValuesFromJson(): the field " + fieldName + " has the unrecognized parameter " + name); - } - - }catch(JSONException ex){ - throw new Error(ex); - } - } - public void setEditElement(EditElementVTwo editElement){ this.editElement = editElement; } @@ -386,11 +334,6 @@ public class FieldVTwo { this.rangeLang = rangeLang; } - - public FieldVTwo copy(){ - FieldVTwo copy = new FieldVTwo(this.originalJson, name); - return copy; - } public EditElementVTwo getEditElement(){ return editElement; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/SelectListGeneratorVTwo.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/SelectListGeneratorVTwo.java new file mode 100644 index 000000000..fda8fa5b4 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/SelectListGeneratorVTwo.java @@ -0,0 +1,485 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.vocabulary.OWL; + +import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; +import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; +import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao; +import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao; +import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; +import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; +import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener; + +public class SelectListGeneratorVTwo { + + static Log log = LogFactory.getLog(SelectListGeneratorVTwo.class); + + public static Map getOptions( + EditConfigurationVTwo editConfig, + String fieldName, + WebappDaoFactory wDaoFact){ + if( editConfig == null ){ + log.error( "fieldToSelectItemList() must be called with a non-null EditConfigurationVTwo "); + return Collections.EMPTY_MAP; + } + if( fieldName == null ){ + log.error( "fieldToSelectItemList() must be called with a non-null fieldName"); + return Collections.EMPTY_MAP; + } + + FieldVTwo field = editConfig.getField(fieldName); + if (field==null) { + log.error("no field \""+fieldName+"\" found from editConfig in SelectListGenerator.getOptions()"); + return Collections.EMPTY_MAP; + } + // now create an empty HashMap to populate and return + HashMap optionsMap = new LinkedHashMap(); + // for debugging, keep a count of the number of options populated + int optionsCount=0; + + FieldVTwo.OptionsType optionsType = field.getOptionsType(); + String vclassUri = null; + switch (optionsType){ + case HARDCODED_LITERALS: // not auto-sorted, and empty values not removed or replaced + List> hardcodedLiteralOptions = field.getLiteralOptions(); + if (hardcodedLiteralOptions==null) { + log.error("no literalOptions List found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType HARDCODED_LITERALS specified"); + return new HashMap (); + } + for(Object obj: ((Iterable)hardcodedLiteralOptions)){ + List literalPair = (List)obj; + String value=(String)literalPair.get(0); + if( value != null){ // allow empty string as a value + String label=(String)literalPair.get(1); + if (label!=null) { + optionsMap.put(value,label); + } else { + optionsMap.put(value, value); + } + ++optionsCount; + } + } + break; + case LITERALS: + List> literalOptions = field.getLiteralOptions(); + if (literalOptions==null) { + log.error("no literalOptions List found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType LITERALS specified"); + return new HashMap (); + } + for(Object obj: ((Iterable)literalOptions)){ + List literalPair = (List)obj; + String value=(String)literalPair.get(0); + if( value != null && value.trim().length() > 0){ + String label=(String)literalPair.get(1); + if (label!=null && label.trim().length() > 0) { + optionsMap.put(value,label); + } else { + optionsMap.put(value, value); + } + ++optionsCount; + } + } + break; + case STRINGS_VIA_DATATYPE_PROPERTY: + log.debug("processing Field \""+fieldName+"\" optionType as a datatype property predicateUri in SelectListGenerator.getOptions()"); + String dataPropUri = field.getPredicateUri(); + if (dataPropUri==null || dataPropUri.equals("")){ + log.error("no predicate dataPropUri found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType STRINGS_VIA_DATATYPE_PROPERTY specified"); + } else { + /* first test to see whether there's a default "leave blank" value specified with the literal options + String defaultOption=null; + if ((defaultOption=getDefaultOption(field))!=null) { + optionsMap.put(LEFT_BLANK, defaultOption); + } */ + // now populate the options + log.debug("finding all choices for data property \""+dataPropUri+"\" in SelectListGenerator.getOptions()"); + + if( wDaoFact == null ) log.error("incoming WebappDaoFactory from request is null in SelectListGenerator.getOptions()."); + + DataPropertyStatementDao dpsDao = wDaoFact.getDataPropertyStatementDao(); + DataPropertyDao dpDao = wDaoFact.getDataPropertyDao(); + DataProperty dp = dpDao.getDataPropertyByURI(dataPropUri); + for (Iterator i = dpsDao.getDataPropertyStatements(dp).iterator(); i.hasNext();) { + DataPropertyStatement dps = i.next(); + if( dps != null ){ + optionsMap.put(dps.getData().trim(),dps.getData().trim()); + ++optionsCount; + } + } + } + break; + case INDIVIDUALS_VIA_OBJECT_PROPERTY: + log.debug("processing Field \""+fieldName+"\" optionType as an object property predicateUri in SelectListGenerator.getOptions()"); + String subjectUri = editConfig.getSubjectUri(); + if (subjectUri==null || subjectUri.equals("")){ + log.error("no subjectUri found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType INDIVIDUALS_VIA_OBJECTPROPERTY specified"); + } else { + String predicateUri = field.getPredicateUri(); + if (predicateUri==null || predicateUri.equals("")){ + log.error("no predicateUri found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType INDIVIDUALS_VIA_OBJECTPROPERTY specified"); + } else { + // first test to see whether there's a default "leave blank" value specified with the literal options + String defaultOption=null; + if ((defaultOption=getDefaultOption(field))!=null) { + optionsMap.put(LEFT_BLANK, defaultOption); + } + // now populate the options + log.debug("finding range individuals for subject \""+subjectUri+"\" and object property \""+predicateUri+"\" in SelectListGenerator.getOptions()"); + + if( wDaoFact == null ) log.error("could not get WebappDaoFactory from request in SelectListGenerator.getOptions()."); + + Individual subject = wDaoFact.getIndividualDao().getIndividualByURI(subjectUri); + if( subject == null ) log.error("could not get individual for subject uri "+subjectUri+" in SelectListGenerator.getOptions()"); + + ObjectProperty objProp = wDaoFact.getObjectPropertyDao().getObjectPropertyByURI(predicateUri); + if( objProp == null ) + log.error("could not get object property for predicate "+predicateUri+" in SelectListGenerator.getOptions()"); + + List vclasses = new ArrayList(); + vclasses = wDaoFact.getVClassDao().getVClassesForProperty(subject.getVClassURI(),predicateUri); + if( vclasses == null ){ + log.error("no owl:Class found for predicate " + predicateUri ); + break; + } + if( vclasses.size() == 0 ) + log.error("no owl:Class found for predicate " + predicateUri ); + + List individuals = new ArrayList(); + HashSet uriSet = new HashSet(); + long startTime = System.currentTimeMillis(); + for ( VClass vclass : vclasses){ + for( Individual ind : wDaoFact.getIndividualDao().getIndividualsByVClassURI(vclass.getURI(),-1,-1)) { + if( !uriSet.contains(ind.getURI())) { + uriSet.add(ind.getURI()); + individuals.add(ind); + } + } + } + + List stmts = subject.getObjectPropertyStatements(); + if( stmts == null ) log.error("object properties for subject were null in SelectListGenerator.getOptions()"); + + individuals = removeIndividualsAlreadyInRange(individuals,stmts,predicateUri,editConfig.getObject()); + //Collections.sort(individuals,new compareIndividualsByName()); + + for( Individual ind : individuals ){ + String uri = ind.getURI(); + if( uri != null ){ + optionsMap.put(uri,ind.getName().trim()); + ++optionsCount; + } + } + + } + } + break; + case INDIVIDUALS_VIA_VCLASS: //so we have a vclass URI + vclassUri = field.getObjectClassUri(); + if (vclassUri==null || vclassUri.equals("")){ + log.error("no vclassUri found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType INDIVIDUALS_VIA_VCLASS specified"); + } else { + // first test to see whether there's a default "leave blank" value specified with the literal options + String defaultOption=null; + if ((defaultOption=getDefaultOption(field))!=null) { + optionsMap.put(LEFT_BLANK, defaultOption); + } + // now populate the options + if( wDaoFact == null ) log.error("could not get WebappDaoFactory from request in SelectListGenerator.getOptions()."); + + // if reasoning isn't available, we will also need to add + // individuals asserted in subclasses + boolean inferenceAvailable = false; + if (wDaoFact instanceof WebappDaoFactoryJena) { + PelletListener pl = ((WebappDaoFactoryJena) wDaoFact) + .getPelletListener(); + if (pl != null && pl.isConsistent() + && !pl.isInErrorState() + && !pl.isReasoning()) { + inferenceAvailable = true; + } + } + + VClass vclass = wDaoFact.getVClassDao().getVClassByURI( vclassUri ); + if( vclass == null ) { + log.error("Cannot find owl:Class " + vclassUri + " in the model" ); + optionsMap.put("", "Could not find class " + vclassUri); + }else{ + Map individualMap = new HashMap(); + + for (Individual ind : wDaoFact.getIndividualDao().getIndividualsByVClassURI(vclass.getURI(),-1,-1)) { + if (ind.getURI() != null) { + individualMap.put(ind.getURI(), ind); + } + } + + if (!inferenceAvailable) { + for (String subclassURI : wDaoFact.getVClassDao().getAllSubClassURIs(vclass.getURI())) { + for (Individual ind : wDaoFact.getIndividualDao().getIndividualsByVClassURI(subclassURI,-1,-1)) { + if (ind.getURI() != null) { + individualMap.put(ind.getURI(), ind); + } + } + } + } + + List individuals = new ArrayList(); + individuals.addAll(individualMap.values()); + Collections.sort(individuals); + + for (Individual ind : wDaoFact.getIndividualDao().getIndividualsByVClassURI(vclass.getURI(),-1,-1)) { + if (ind.getURI() != null) { + individualMap.put(ind.getURI(), ind); + } + } + + if (!inferenceAvailable) { + for (String subclassURI : wDaoFact.getVClassDao().getAllSubClassURIs(vclass.getURI())) { + for (Individual ind : wDaoFact.getIndividualDao().getIndividualsByVClassURI(subclassURI,-1,-1)) { + if (ind.getURI() != null) { + individualMap.put(ind.getURI(), ind); + } + } + } + } + + individuals.addAll(individualMap.values()); + Collections.sort(individuals); + + if (individuals.size()==0){ + log.error("No individuals of type "+vclass.getName()+" to add to pick list in SelectListGenerator.getOptions()"); + optionsMap.put("", "No " + vclass.getName() + " found"); + }else{ + for( Individual ind : individuals ) { + String uri = ind.getURI(); + if( uri != null ) { + optionsMap.put(uri,ind.getName().trim()); + ++optionsCount; + } + } + } + } + } + break; + case MONIKERS_VIA_VCLASS: //so we have a vclass URI + vclassUri = field.getObjectClassUri(); + if (vclassUri==null || vclassUri.equals("")){ + log.error("no vclassUri found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType MONIKERS_VIA_VCLASS specified"); + } else { + // first test to see whether there's a default "leave blank" value specified with the literal options + String defaultOption=null; + if ((defaultOption=getDefaultOption(field))!=null) { + optionsMap.put(LEFT_BLANK, defaultOption); + } + // now populate the options + if( wDaoFact == null ) log.error("could not get WebappDaoFactory from request in SelectListGenerator.getOptions()."); + + VClass vclass = wDaoFact.getVClassDao().getVClassByURI( vclassUri ); + if( vclass == null ) { + log.error("Cannot find owl:Class " + vclassUri + " in the model" ); + optionsMap.put("", "Could not find class " + vclassUri); + }else{ + List individuals = wDaoFact.getIndividualDao().getIndividualsByVClassURI(vclass.getURI(),-1,-1); + if (individuals.size()==0){ + log.error("No individuals of type "+vclass.getName()+" to add to pick list in SelectListGenerator.getOptions(); check portal visibility"); + optionsMap.put("", "No " + vclass.getName() + " found"); + } + } + } + break; + + case CHILD_VCLASSES: //so we have a vclass URI + vclassUri = field.getObjectClassUri(); + if (vclassUri==null || vclassUri.equals("")){ + log.error("no vclassUri found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType CHILD_VCLASSES specified"); + } else { + // first test to see whether there's a default "leave blank" value specified with the literal options + String defaultOption=null; + if ((defaultOption=getDefaultOption(field))!=null) { + optionsMap.put(LEFT_BLANK, defaultOption); + } + // now populate the options + if( wDaoFact == null ) log.error("could not get WebappDaoFactory from request in SelectListGenerator.getOptions()."); + + VClassDao vclassDao = wDaoFact.getVClassDao(); + List subClassList = vclassDao.getAllSubClassURIs(vclassUri); + if( subClassList == null || subClassList.size()==0 ) { + log.debug("No subclasses of " + vclassUri + " found in the model so only default value from field's literalOptions will be used" ); + } else { + for( String subClassUri : subClassList ) { + VClass subClass = vclassDao.getVClassByURI(subClassUri); + if( subClass != null && !OWL.Nothing.getURI().equals(subClassUri)) { + optionsMap.put(subClassUri,subClass.getName().trim()); + ++optionsCount; + } + } + } + } + break; + + case CHILD_VCLASSES_WITH_PARENT: //so we have a vclass URI + vclassUri = field.getObjectClassUri(); + if (vclassUri==null || vclassUri.equals("")){ + log.error("no vclassUri found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType CHILD_VCLASSES specified"); + } else { + // first test to see whether there's a default "leave blank" value specified with the literal options + String defaultOption=null; + if ((defaultOption=getDefaultOption(field))!=null) { + optionsMap.put(LEFT_BLANK, defaultOption); + } + // now populate the options + if( wDaoFact == null ) log.error("could not get WebappDaoFactory from request in SelectListGenerator.getOptions()."); + + VClassDao vclassDao = wDaoFact.getVClassDao(); + List subClassList = vclassDao.getAllSubClassURIs(vclassUri); + if( subClassList == null || subClassList.size()==0 ) { + log.debug("No subclasses of " + vclassUri + " found in the model so only default value from field's literalOptions will be used" ); + } else { + for( String subClassUri : subClassList ) { + VClass subClass = vclassDao.getVClassByURI(subClassUri); + if( subClass != null && !OWL.Nothing.getURI().equals(subClassUri)) { + optionsMap.put(subClassUri,subClass.getName().trim()); + ++optionsCount; + } + } + optionsMap.put(vclassUri, "Other"); + ++optionsCount; + } + } + break; + + case VCLASSGROUP: + + String classGroupUri = field.getObjectClassUri(); // we're overloading this property to specify the classgroup + if (classGroupUri==null || classGroupUri.equals("")){ + log.error("no classGroupUri found for field \""+fieldName+"\" in SelectListGenerator.getOptions() when OptionsType VCLASSGROUP specified"); + } else { + // first test to see whether there's a default "leave blank" value specified with the literal options + String defaultOption=null; + if ((defaultOption=getDefaultOption(field))!=null) { + optionsMap.put(LEFT_BLANK, defaultOption); + } + // now populate the options + if( wDaoFact == null ) log.error("could not get WebappDaoFactory from request in SelectListGenerator.getOptions()."); + + VClassGroupDao vcgd = wDaoFact.getVClassGroupDao(); + + // Need to call this method to populate the classgroups - otherwise the classgroup class list is empty + List vClassGroups = vcgd.getPublicGroupsWithVClasses(); + + if (vClassGroups == null) { + log.error("No class groups found, so only default value from field's literalOptions will be used."); + } else { + VClassGroup vClassGroup = null; + for (Object o : vClassGroups) { + VClassGroup vcg = (VClassGroup) o; + if (vcg.getURI().equals(classGroupUri)) { + vClassGroup = vcg; + break; + } + } + if (vClassGroup == null) { + log.error("No class group with uri " + classGroupUri + "found, so only default value from field's literalOptions will be used."); + } else { + List vClassList = vClassGroup.getVitroClassList(); + + if( vClassList == null || vClassList.size()==0 ) { + log.debug("No classes in class group " + classGroupUri + " found in the model, so only default value from field's literalOptions will be used" ); + } else { + for( VClass vClass : vClassList ) { + String vClassUri = vClass.getURI(); + if( vClass != null && !OWL.Nothing.getURI().equals(vClassUri)) { + optionsMap.put(vClassUri,vClass.getName().trim()); + ++optionsCount; + } + } + } + } + } + } + break; + + case UNDEFINED : + log.error("optionsType \"UNDEFINED\" for Field \""+fieldName+"\" in SelectListGenerator.getOptions()"); + break; + default: log.error("unknown optionsType "+optionsType.toString()+" for Field \""+fieldName+"\" in SelectListGenerator.getOptions()"); + } + log.debug("added "+optionsCount+" options for field \""+fieldName+"\" in SelectListGenerator.getOptions()"); + return optionsMap; + } + + /** + * The default option is used when a option list is being auto + * generated from a VClass or an ObjectProperty. If there is an + * item in the literals item list then the name of it will be used + * as the text to display for an empty string value option. + * + * Having an option with an empty string for a Field that expects + * a URI will cause the form processing to assume that the field + * was left blank. + * + * @param field + * @return + */ + private static String getDefaultOption(FieldVTwo field) { + List > defaultOptions = (List>) field.getLiteralOptions(); + if (defaultOptions!=null) { + for(Object obj: ((Iterable)defaultOptions)) { + List pair = (List)obj; + String value = pair.get(0); + String label = pair.get(1); + if( label != null && label.trim().length() > 0){ + return label; // don't want to return a value + } + } + } + return null; + } + + // copied from OptionsForPropertyTag.java in the thought that class may be deprecated + private static List removeIndividualsAlreadyInRange(List individuals, + List stmts, String predicateUri, String objectUriBeingEdited){ + log.debug("starting to check for duplicate range individuals in SelectListGenerator.removeIndividualsAlreadyInRange() ..."); + HashSet range = new HashSet(); + + for(ObjectPropertyStatement ops : stmts){ + if( ops.getPropertyURI().equals(predicateUri)) + range.add( ops.getObjectURI() ); + } + + int removeCount=0; + ListIterator it = individuals.listIterator(); + while(it.hasNext()){ + Individual ind = it.next(); + if( range.contains( ind.getURI()) && !(ind.getURI().equals(objectUriBeingEdited)) ) { + it.remove(); + ++removeCount; + } + } + log.debug("removed "+removeCount+" duplicate range individuals"); + return individuals; + } + + private static final String LEFT_BLANK = ""; +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/MenuEditingFormGenerator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/MenuEditingFormGenerator.java index 7e3a2836c..bc9bc3977 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/MenuEditingFormGenerator.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/configuration/generators/MenuEditingFormGenerator.java @@ -15,7 +15,10 @@ import org.apache.commons.logging.LogFactory; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Model; +import com.hp.hpl.jena.vocabulary.RDF; +import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; +import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.VClass; @@ -23,9 +26,10 @@ import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.Field; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.SelectListGenerator; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.FieldVTwo; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.SelectListGeneratorVTwo; import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch; +import edu.cornell.mannlib.vitro.webapp.web.MiscWebUtils; /** * Generates the edit configuration for a default property form. @@ -34,173 +38,363 @@ import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch; public class MenuEditingFormGenerator implements EditConfigurationGenerator { private Log log = LogFactory.getLog(DefaultObjectPropertyFormGenerator.class); + private String template = "testMenuEdit.ftl"; + //Set when processing + //private String subjectUriJson = null; + //private String predicateUriJson = null; + //private String objectUriJson = null; - @Override + //TODO: Check if above even needed or if we can process using regular uris + private String subjectUri = null; + private String predicateUri = null; + private String objectUri = null; + + + //whether or not this is an object or data prop + private boolean isObjectPropForm = false; + //from 'default data prop form' + private static HashMap defaultsForXSDtypes; + + static { + defaultsForXSDtypes = new HashMap(); + //defaultsForXSDtypes.put("http://www.w3.org/2001/XMLSchema#dateTime","2001-01-01T12:00:00"); + defaultsForXSDtypes.put("http://www.w3.org/2001/XMLSchema#dateTime","#Unparseable datetime defaults to now"); + } + + + @Override public EditConfigurationVTwo getEditConfiguration(VitroRequest vreq, HttpSession session) { //The actual N3 created here needs to include multiple levels from hasElement all the way down to the //actual pagej - - Individual subject = (Individual)vreq.getAttribute("subject"); - ObjectProperty prop = (ObjectProperty)vreq.getAttribute("predicate"); - - WebappDaoFactory wdf = vreq.getWebappDaoFactory(); - - String queryForInverse = "PREFIX owl: " - + " SELECT ?inverse_property " - + " WHERE { ?inverse_property owl:inverseOf ?predicate } "; - - - // retrieving attributes from the request object to build editjson string - String formUrl = (String)vreq.getAttribute("formUrl"); - String editKey = (String)vreq.getAttribute("editKey"); - - String subjectUriJson = (String)vreq.getAttribute("subjectUriJson"); - String predicateUriJson = (String)vreq.getAttribute("predicateUriJson"); - String objectUriJson = (String)vreq.getAttribute("objectUriJson"); - String objectUri = (String)vreq.getAttribute("objectUriJson"); - //Get actual object uri as not concerned with json escaped version - System.out.println("Object Uri is " + objectUri + " and json version is " + objectUriJson); - - - //building the editjson object - //TODO: There has to be a better way of doing this. - // Tried building a java object with Google Gson and then - // deserialize it to json, but the values in the string - // are sometimes lists, maps, literals. -/* String editjson = "{" + - " formUrl : " + formUrl + " ," + - " editKey : " + editKey + " ," + - " urlPatternToReturnTo : " + "/individual ," + - - " subject : [ subject , " + subjectUriJson + " ] , " + - " predicate : [ predicate , " + predicateUriJson + " ] ," + - " object : [ objectVar , " + objectUriJson + ", URI ] , " + - - " n3required : [ " + n3ForEdit + "] ," + - " n3optional : [ " + n3Inverse + "] ," + - " newResources : { } ," + - - " urisInScope : { } ," + - " literalsInScope: { } ," + - - " urisOnForm : [objectVar] ," + - " literalsOnForm : [ ] ," + - " filesOnForm : [ ] ," + - - "sparqlForLiterals : { } ," + - "sparqlForUris : { inverseProp : " + queryForInverse + " } ," + - - "sparqlForExistingLiterals : { } ," + - "sparqlForExistingUris : { } ," + - - "fields : { objectVar : { " + - " newResource : false ," + - " queryForExisting : { }, " + - " validators : [ nonempty ] ," + - " optionsType : INDIVIDUALS_VIA_OBJECT_PROPERTY , " + - " subjectUri : " + subjectUriJson + " ," + - " subjectClassUri : ," + - " predicateUri : " + predicateUriJson + " ," + - " objectClassUri : ," + - " rangeDatatypeUri : ," + - " rangeLang : , " + - " literalOptions : [ ] , " + - " assertions : [ " + n3ForEdit + " ," + n3Inverse + " ] " + - " } " + - " } " + - " } "; - -*/ - - //set the editjson attribute in the request - // vreq.setAttribute("editjson", editjson); - // log.debug(vreq.getAttribute("editjson")); - - //Alternative: Set - - + EditConfigurationVTwo editConfiguration = new EditConfigurationVTwo(); //Setting a custom test template for now //TODO: Where to get this custom template from? Should it be a predicate in display model somewhere? - editConfiguration.setTemplate("testMenuEdit.ftl"); + editConfiguration.setTemplate(this.template); + //process subject, predicate, object parameters + this.initProcessParameters(vreq, editConfiguration); - - editConfiguration.setFormUrl(formUrl); - editConfiguration.setEditKey(editKey); - - editConfiguration.setUrlPatternToReturnTo("/individual"); - - editConfiguration.setVarNameForSubject("subject"); - editConfiguration.setSubjectUri(subjectUriJson); - - editConfiguration.setVarNameForPredicate("predicate"); - editConfiguration.setPredicateUri(predicateUriJson); - - editConfiguration.setVarNameForObject("objectVar"); - editConfiguration.setObject(objectUriJson); - //Above, try regular Object uri if json does not work - //this needs to be set for the editing to be triggered properly, otherwise the 'prepare' method - //pretends this is a data property editing statement and throws an error - //"object" : [ "objectVar" , "${objectUriJson}" , "URI"], - if(objectUriJson != null) { - editConfiguration.setObjectResource(true); - } else { - //ObjectUriJson is null, so should include data prop info here - } - - - List n3ForEdit = new ArrayList(); - n3ForEdit.add("?subject"); - n3ForEdit.add("?predicate"); - n3ForEdit.add("?objectVar"); - editConfiguration.setN3Required(n3ForEdit); + //Assumes this is a simple case of subject predicate var + editConfiguration.setN3Required(this.generateN3Required(vreq)); - List n3Inverse = new ArrayList(); - n3Inverse.add("?objectVar"); - n3Inverse.add("?inverseProp"); - n3Inverse.add("?subject"); - editConfiguration.setN3Optional(n3Inverse); + //n3 optional + editConfiguration.setN3Optional(this.generateN3Optional()); + //Todo: what do new resources depend on here? + //In original form, these variables start off empty editConfiguration.setNewResources(new HashMap()); + //In scope + this.setUrisAndLiteralsInScope(editConfiguration); - editConfiguration.setUrisInScope(new HashMap>()); - - editConfiguration.setLiteralsInScope(new HashMap>()); - - List urisOnForm = new ArrayList(); - urisOnForm.add("objectVar"); - editConfiguration.setN3Optional(urisOnForm); - - editConfiguration.setLiteralsOnForm(new ArrayList()); + //on Form + this.setUrisAndLiteralsOnForm(editConfiguration); editConfiguration.setFilesOnForm(new ArrayList()); + //Sparql queries + this.setSparqlQueries(editConfiguration); + + //Set up fields + this.setUpFields(editConfiguration, vreq); + + //set submission url + editConfiguration.setSubmitToUrl("/edit/process"); + editConfiguration.putConfigInSession(editConfiguration, session); + + //Here, retrieve model from + //Model model = (Model) session.getServletContext().getAttribute("jenaOntModel"); + //Use special model instead + Individual subject = (Individual)vreq.getAttribute("subject"); + ObjectProperty prop = (ObjectProperty)vreq.getAttribute("predicate"); + + WebappDaoFactory wdf = vreq.getWebappDaoFactory(); + Model model = (Model) vreq.getWriteModel(); + + this.prepareForUpdate(vreq, editConfiguration, model, subject, prop, wdf); + this.associatePageData(vreq, editConfiguration, model); + //don't need this here exactly + //this.generateSelectForExisting(vreq, session, editConfiguration, subject, prop, wdf); + + return editConfiguration; + } + + private void associatePageData(VitroRequest vreq, + EditConfigurationVTwo editConfiguration, Model model) { + vreq.setAttribute("formTitle", "Edit Menu Item"); + // + } + + //Initialize setup: process parameters + private void initProcessParameters(VitroRequest vreq, EditConfigurationVTwo editConfiguration) { + String formUrl = (String)vreq.getAttribute("formUrl"); + String editKey = (String)vreq.getAttribute("editKey"); + System.out.println("Form url is " + formUrl + " and editKey is " + editKey); + //this.subjectUriJson = (String)vreq.getAttribute("subjectUriJson"); + //this.predicateUriJson = (String)vreq.getAttribute("predicateUriJson"); + //this.objectUriJson = (String)vreq.getAttribute("objectUriJson"); + //regular, non json version + this.subjectUri = (String)vreq.getAttribute("subjectUri"); + this.predicateUri = (String)vreq.getAttribute("predicateUri"); + this.objectUri = (String)vreq.getAttribute("objectUri"); + //Get actual object uri as not concerned with json escaped version + //System.out.println("Object Uri is " + objectUri + " and json version is " + objectUriJson); + + //Set up EditConfigurationVTwo object + + editConfiguration.setFormUrl(formUrl); + editConfiguration.setEditKey(editKey); + editConfiguration.setUrlPatternToReturnTo("/individual"); + + //subject, predicate, objectVar + editConfiguration.setVarNameForSubject("subject"); + editConfiguration.setSubjectUri(subjectUri); + + editConfiguration.setVarNameForPredicate("predicate"); + editConfiguration.setPredicateUri(predicateUri); + + + + //this needs to be set for the editing to be triggered properly, otherwise the 'prepare' method + //pretends this is a data property editing statement and throws an error + //"object" : [ "objectVar" , "${objectUriJson}" , "URI"], + //if(objectUri != null) { + //not concerned about remainder, can move into default obj prop form if required + this.isObjectPropForm = true; + this.processObjectPropForm(vreq, editConfiguration); + //} else { + // this.isObjectPropForm = false; + // this.processDataPropForm(vreq, editConfiguration); + //} + } + + private void processObjectPropForm(VitroRequest vreq, EditConfigurationVTwo editConfiguration) { + editConfiguration.setVarNameForObject("objectVar"); + editConfiguration.setObject(objectUri); + //For page + editConfiguration.setObjectResource(true); + } + + private void processDataPropForm(VitroRequest vreq, EditConfigurationVTwo editConfiguration) { + String datapropKeyStr = vreq.getParameter("datapropKey"); + int dataHash=0; + DataPropertyStatement dps = (DataPropertyStatement)vreq.getAttribute("dataprop"); + + //ObjectUriJson is null, so should include data prop info here + //Use dataprop key info here instead + DataProperty prop = (DataProperty)vreq.getAttribute("predicate"); + //if( prop == null ) return doHelp(vreq, "In DefaultDataPropertyFormGenerator, could not find predicate " + predicateUri); + //Why are we setting attributes here again? + vreq.setAttribute("propertyName",prop.getPublicName()); + Individual subject = (Individual)vreq.getAttribute("subject"); + //if( subject == null ) return doHelp(vreq,"In DefaultDataPropertyFormGenerator, could not find subject " + subjectUri); + vreq.setAttribute("subjectName",subject.getName()); + + String rangeDatatypeUri = vreq.getWebappDaoFactory().getDataPropertyDao().getRequiredDatatypeURI(subject, prop); + //String rangeDatatypeUri = prop.getRangeDatatypeURI(); + vreq.setAttribute("rangeDatatypeUriJson", MiscWebUtils.escape(rangeDatatypeUri)); + + + if( dps != null ){ + try { + dataHash = Integer.parseInt(datapropKeyStr); + log.debug("dataHash is " + dataHash); + } catch (NumberFormatException ex) { + log.debug("could not parse dataprop hash "+ + "but there was a dataproperty; hash: '"+datapropKeyStr+"'"); + } + + String rangeDatatype = dps.getDatatypeURI(); + if( rangeDatatype == null ){ + log.debug("no range datatype uri set on data property statement when property's range datatype is "+prop.getRangeDatatypeURI()+" in DefaultDataPropertyFormGenerator"); + vreq.setAttribute("rangeDatatypeUriJson",""); + } else { + log.debug("range datatype uri of ["+rangeDatatype+"] on data property statement in DefaultDataPropertyFormGenerator"); + vreq.setAttribute("rangeDatatypeUriJson",rangeDatatype); + } + String rangeLang = dps.getLanguage(); + if( rangeLang == null ) { + log.debug("no language attribute on data property statement in DefaultDataPropertyFormGenerator"); + vreq.setAttribute("rangeLangJson",""); + }else{ + log.debug("language attribute of ["+rangeLang+"] on data property statement in DefaultDataPropertyFormGenerator"); + vreq.setAttribute("rangeLangJson", rangeLang); + } + } else { + log.debug("No incoming dataproperty statement attribute for property "+prop.getPublicName()+"; adding a new statement"); + if(rangeDatatypeUri != null && rangeDatatypeUri.length() > 0) { + String defaultVal = defaultsForXSDtypes.get(rangeDatatypeUri); + if( defaultVal == null ) + vreq.setAttribute("rangeDefaultJson", ""); + else + vreq.setAttribute("rangeDefaultJson", '"' + MiscWebUtils.escape(defaultVal) + '"' ); + } + } + editConfiguration.setDatapropKey((datapropKeyStr==null)?"":datapropKeyStr); + + } + + + //Get N3 required specifically for menu management + //?Is it necessarily separate + private List generateN3Required(VitroRequest vreq) { + List n3ForEdit = new ArrayList(); + String n3String = "?subject ?predicate "; + //n3ForEdit.add("?subject"); + //n3ForEdit.add("?predicate"); + + //leaving check out for now + //if(this.isObjectPropForm) { + n3String += "?objectVar ."; + //n3ForEdit.add("?objectVar"); + //In this case, defaultMenu hasElement ?objectVar + //Now add Strings + //?objectVar hasPage ?page + n3ForEdit.add(n3String); + n3ForEdit.add("\n ?objectVar <" + DisplayVocabulary.ITEM_TO_PAGE + "> ?page ."); + n3ForEdit.add("\n ?page <" + DisplayVocabulary.DISPLAY_NS+ "title> ?title ."); + + +// } else { +// DataProperty prop = (DataProperty)vreq.getAttribute("predicate"); +// String localName = prop.getLocalName(); +// String dataLiteral = localName + "Edited"; +// n3String += "?"+dataLiteral; +// n3ForEdit.add(n3String); +// } + return n3ForEdit; + } + //Below: use to replace default obj prop form + //Handles both object and data property + /* + private List generateN3Required(VitroRequest vreq) { + List n3ForEdit = new ArrayList(); + n3ForEdit.add("?subject"); + n3ForEdit.add("?predicate"); + if(this.isObjectPropForm) { + n3ForEdit.add("?objectVar"); + } else { + DataProperty prop = (DataProperty)vreq.getAttribute("predicate"); + String localName = prop.getLocalName(); + String dataLiteral = localName + "Edited"; + n3ForEdit.add("?"+dataLiteral); + } + return n3ForEdit; + }*/ + + private List generateN3Optional() { + List n3Inverse = new ArrayList(); + n3Inverse.add("?objectVar ?inverseProp ?subject . \n"); + // n3Inverse.add("?page ?inversePage ?objectVar ."); + //n3Inverse.add("?objectVar"); + //n3Inverse.add("?inverseProp"); + //n3Inverse.add("?subject"); + return n3Inverse; + } + + //Set queries + private String retrieveQueryForInverse () { + String queryForInverse = "PREFIX owl: " + + " SELECT ?inverse_property " + + " WHERE { ?inverse_property owl:inverseOf ?predicate } "; + return queryForInverse; + } + + private void setUrisAndLiteralsInScope(EditConfigurationVTwo editConfiguration) { + editConfiguration.setUrisInScope(new HashMap>()); + editConfiguration.setLiteralsInScope(new HashMap>()); + } + + //n3 should look as follows + //?subject ?predicate ?objectVar . + //?objectVar display:linkText ?name . + //?objectVar display:toPage ?page . + //?page rdf:type ?type . //multiple types possible + //?page display:title ?title . + //?page display:urlMapping ?mapping . + + private void setUrisAndLiteralsOnForm(EditConfigurationVTwo editConfiguration) { + List urisOnForm = new ArrayList(); + urisOnForm.add("objectVar"); + //Also adding page + urisOnForm.add("page"); + editConfiguration.setUrisOnform(urisOnForm); + //let's just get title + List literalsOnForm = new ArrayList(); + literalsOnForm.add("title"); + editConfiguration.setLiteralsOnForm(literalsOnForm); + } + + //This is for various items + private void setSparqlQueries(EditConfigurationVTwo editConfiguration) { + //Sparql queries defining retrieval of literals etc. editConfiguration.setSparqlForAdditionalLiteralsInScope(new HashMap()); Map urisInScope = new HashMap(); - urisInScope.put("inverseProp", queryForInverse); + urisInScope.put("inverseProp", this.retrieveQueryForInverse()); editConfiguration.setSparqlForAdditionalUrisInScope(urisInScope); - editConfiguration.setSparqlForExistingLiterals(new HashMap()); - editConfiguration.setSparqlForExistingUris(new HashMap()); + editConfiguration.setSparqlForExistingLiterals(generateSparqlForExistingLiterals()); + editConfiguration.setSparqlForExistingUris(generateSparqlForExistingUris()); + } + + + //Get page uri for object + private HashMap generateSparqlForExistingUris() { + HashMap map = new HashMap(); + map.put("page", "SELECT ?page where {?objectVar <" + DisplayVocabulary.TO_PAGE + "> ?page . } "); + return map; + } + + private HashMap generateSparqlForExistingLiterals() { + HashMap map = new HashMap(); + map.put("title", "SELECT ?title where {?page <" + DisplayVocabulary.DISPLAY_NS + "title> ?title . } "); + //If this works then add below + //Title, URL Mapping, type + //map.put("type", "SELECT ?type where {?page <" + RDF.type.getURI() + "> ?type . } "); + //And then being able to generate the Class groups required + //Could just pass that back in + return map; + } + + //Get all properties for a page? + //Just get the properties? + + //Fields + private void setUpFields(EditConfigurationVTwo editConfiguration, VitroRequest vreq) { + Map fields = new HashMap(); - Map fields = new HashMap(); - Field field = new Field(); + //Field should be for page title and other associations (assuming this is what actually goes on the form) + FieldVTwo field = new FieldVTwo(); + field.setName("title"); + field.setNewResource(false); + List validators = new ArrayList(); + validators.add("nonempty"); + field.setValidators(validators); + field.setOptionsType("LITERALS"); + field.setPredicateUri(DisplayVocabulary.DISPLAY_NS + "title"); + List assertions = this.generateN3Required(vreq); + assertions.addAll(this.generateN3Optional()); + field.setAssertions(assertions); + fields.put("title", field); + //Object Var Field + //Won't need this in our case + /* + FieldVTwo field = new FieldVTwo(); field.setName("objectVar"); field.setNewResource(false); //queryForExisting is not being used anywhere in Field + //TODO: Check how validators will work List validators = new ArrayList(); validators.add("nonempty"); field.setValidators(validators); //subjectUri and subjectClassUri are not being used in Field - field.setOptionsType("INDIVIDUALS_VIA_OBJECT_PROPERTY"); - field.setPredicateUri(predicateUriJson); + field.setPredicateUri(this.predicateUri); field.setObjectClassUri(null); field.setRangeDatatypeUri(null); @@ -218,23 +412,19 @@ public class MenuEditingFormGenerator implements EditConfigurationGenerator { field.setAssertions(assertions); fields.put("objectVar", field); + */ + + //Fields for us will actually be page specific //TODO: Check why/how this method signature has changed - //editConfiguration.setFields(fields); - - editConfiguration.putConfigInSession(editConfiguration, session); - - editConfiguration.setTemplate("defaultPropertyForm.ftl"); - - + editConfiguration.setFields(fields); + } + + //Based on whether new or existing object prepare for update + //TODO: Update for data property editing as well + private void prepareForUpdate(VitroRequest vreq, EditConfigurationVTwo editConfiguration, Model model, Individual subject, ObjectProperty prop, WebappDaoFactory wdf) { String formTitle = " "; String submitLabel = " "; - - //Here, retrieve model from - //Model model = (Model) session.getServletContext().getAttribute("jenaOntModel"); - //Use special model instead - Model model = (Model) vreq.getWriteModel(); - //this block is for an edit of an existing object property statement if(vreq.getAttribute("object") != null) { editConfiguration.prepareForObjPropUpdate(model); @@ -272,31 +462,35 @@ public class MenuEditingFormGenerator implements EditConfigurationGenerator { submitLabel = "save entry"; } } - vreq.setAttribute("formTitle", formTitle); - -// if( prop.getSelectFromExisting() ){ -// // set ProhibitedFromSearch object so picklist doesn't show -// // individuals from classes that should be hidden from list views -// OntModel displayOntModel = -// (OntModel) session.getServletContext() -// .getAttribute("displayOntModel"); -// if (displayOntModel != null) { -// ProhibitedFromSearch pfs = new ProhibitedFromSearch( -// DisplayVocabulary.PRIMARY_LUCENE_INDEX_URI, displayOntModel); -// if( editConfiguration != null ) -// editConfiguration.setProhibitedFromSearch(pfs); -// } -// Map rangeOptions = SelectListGenerator.getOptions(editConfiguration, "objectVar" , wdf); -// if( rangeOptions != null && rangeOptions.size() > 0 ) { -// vreq.setAttribute("rangeOptionsExist", true); -// vreq.setAttribute("rangeOptions.objectVar", rangeOptions); -// } else { -// vreq.setAttribute("rangeOptionsExist",false); -// } -// } - - return editConfiguration; + vreq.setAttribute("submitLabel", submitLabel); } - + + //if existing object values, allow for selection from existing + private void generateSelectForExisting(VitroRequest vreq, HttpSession session, EditConfigurationVTwo editConfiguration, Individual subject, ObjectProperty prop, WebappDaoFactory wdf) { + if( prop.getSelectFromExisting() ){ + // set ProhibitedFromSearch object so picklist doesn't show + // individuals from classes that should be hidden from list views + OntModel displayOntModel = + (OntModel) session.getServletContext() + .getAttribute("displayOntModel"); + if (displayOntModel != null) { + ProhibitedFromSearch pfs = new ProhibitedFromSearch( + DisplayVocabulary.PRIMARY_LUCENE_INDEX_URI, displayOntModel); + if( editConfiguration != null ) + editConfiguration.setProhibitedFromSearch(pfs); + } + Map rangeOptions = SelectListGeneratorVTwo.getOptions(editConfiguration, "objectVar" , wdf); + if( rangeOptions != null && rangeOptions.size() > 0 ) { + vreq.setAttribute("rangeOptionsExist", true); + vreq.setAttribute("rangeOptions.objectVar", rangeOptions); + } else { + vreq.setAttribute("rangeOptionsExist",false); + } + } + } + + //Process additional data + //In this case + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java index 47fe65774..321ac0a84 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/controller/EditRequestDispatchController.java @@ -37,6 +37,8 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet { public static Log log = LogFactory.getLog(EditRequestDispatchController.class); final String DEFAULT_OBJ_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.DefaultObjectPropertyFormGenerator"; + final String DEFAULT_DATA_FORM = "edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.generators.DefaultDataPropertyFormGenerator"; + final String DEFAULT_ERROR_FORM = "error.jsp"; final String DEFAULT_ADD_INDIVIDUAL = "defaultAddMissingIndividualForm.jsp"; @Override @@ -219,7 +221,9 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet { //what goes in the map for templates? Map templateData = new HashMap(); templateData.put("editConfiguration", new EditConfigurationTemplateModel( editConfig, vreq)); - templateData.put("formTitle", formTitle); + //templateData.put("formTitle", formTitle); + //templateData.put("pageData", retrieveEditData(vreq)); + //retrieveEditData(vreq, templateData); return new TemplateResponseValues(template, templateData); }catch(Throwable th){ @@ -323,4 +327,8 @@ public class EditRequestDispatchController extends FreemarkerHttpServlet { HashMap map = new HashMap(); map.put("errorMessage", "help is not yet implemented"); return new TemplateResponseValues("error-message.ftl", map); } + + + + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java index e256860b8..a8d57e3fa 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/edit/EditConfigurationTemplateModel.java @@ -5,15 +5,23 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.edit; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.EditConfigurationVTwo; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.ArrayList; +import com.hp.hpl.jena.rdf.model.Literal; + public class EditConfigurationTemplateModel extends BaseTemplateModel { + EditConfigurationVTwo editConfig; + HashMap pageData = new HashMap(); + VitroRequest vreq; - final EditConfigurationVTwo editConfig; - final VitroRequest vreq; - - public EditConfigurationTemplateModel(EditConfigurationVTwo editConfig, VitroRequest vreq){ + public EditConfigurationTemplateModel( EditConfigurationVTwo editConfig, VitroRequest vreq){ this.editConfig = editConfig; this.vreq = vreq; + //get additional data that may be required to generate template + this.retrieveEditData(); } public String getEditKey(){ @@ -27,4 +35,51 @@ public class EditConfigurationTemplateModel extends BaseTemplateModel { public String getSubmitToUrl(){ return getUrl( editConfig.getSubmitToUrl() ); } + //TODO: Check whether to include additoinal data here or elsewhere + //For now, using attributes off of vitro request to add to template + //TODO: find better mechanism + private void retrieveEditData() { + //Get vitro request attributes for + pageData.put("formTitle", (String) vreq.getAttribute("formTitle")); + pageData.put("submitLabel", (String) vreq.getAttribute("submitLabel")); + + if(vreq.getAttribute("rangeOptionsExist") != null && (Boolean) vreq.getAttribute("rangeOptionsExist") == true) { + Map rangeOptions = (Map)vreq.getAttribute("rangeOptions.objectVar"); + pageData.put("rangeOptions", rangeOptions); + } + + + } + + //Get page data + public String getFormTitle() { + return (String) pageData.get("formTitle"); + } + + public String getSubmitLabel() { + return (String) pageData.get("submitLabel"); + } + + public Map getRangeOptions() { + return (Map) pageData.get("rangeOptions"); + } + + //Get literals in scope, i.e. variable names with values assigned + public Map> getLiteralValues() { + return editConfig.getLiteralsInScope(); + } + + //variables names with URIs assigned + public Map> getObjectUris() { + return editConfig.getUrisInScope(); + } + + public List getLiteralStringValue(String key) { + List ls = editConfig.getLiteralsInScope().get(key); + List literalValues = new ArrayList(); + for(Literal l: ls) { + literalValues.add(l.getString()); + } + return literalValues; + } } diff --git a/webapp/web/css/menupage/menupage.css b/webapp/web/css/menupage/menupage.css index 975f9a5e3..92e8bf123 100644 --- a/webapp/web/css/menupage/menupage.css +++ b/webapp/web/css/menupage/menupage.css @@ -293,4 +293,5 @@ p.no-individuals { -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; -} \ No newline at end of file +} + diff --git a/webapp/web/css/menupage/testmenupage.css b/webapp/web/css/menupage/testmenupage.css new file mode 100644 index 000000000..c531d2d0a --- /dev/null +++ b/webapp/web/css/menupage/testmenupage.css @@ -0,0 +1,4 @@ +/**Added by Huda for demonstration so feel free to edit/remove**/ +.hide { + display:none; +} \ No newline at end of file diff --git a/webapp/web/edit/editDatapropStmtRequestDispatch.jsp b/webapp/web/edit/editDatapropStmtRequestDispatch.jsp index aff82a9c5..004290d53 100644 --- a/webapp/web/edit/editDatapropStmtRequestDispatch.jsp +++ b/webapp/web/edit/editDatapropStmtRequestDispatch.jsp @@ -27,6 +27,13 @@ <% + //Check if special model, in which case forward + if(request.getParameter("switchToDisplayModel") != null) { + //forward to Edit Request Dispatch Controller + String queryString = request.getQueryString(); + response.sendRedirect("http://localhost:8080/vivo/editRequestDispatch?" + queryString); + } + // Decide which form to forward to, set subjectUri, subjectUriJson, predicateUri, predicateUriJson in request // Also get the Individual for the subjectUri and put it in the request scope // If a datapropKey is sent it as an http parameter, then set datapropKey and datapropKeyJson in request, and diff --git a/webapp/web/edit/editRequestDispatch.jsp b/webapp/web/edit/editRequestDispatch.jsp index e7c825106..e5d9dddaa 100644 --- a/webapp/web/edit/editRequestDispatch.jsp +++ b/webapp/web/edit/editRequestDispatch.jsp @@ -29,7 +29,9 @@ public static Log log = LogFactory.getLog("edu.cornell.mannlib.vitro.webapp.jsp. if(request.getParameter("switchToDisplayModel") != null) { //forward to Edit Request Dispatch Controller String queryString = request.getQueryString(); - response.sendRedirect("http://localhost:8080/vivo/editRequestDispatch?" + queryString); + //Instead of edit request which is what we'll do later, here we'll forward to Menu Management Controller + //response.sendRedirect("http://localhost:8080/vivo/editRequestDispatch?" + queryString); + response.sendRedirect("http://localhost:8080/vivo/editDisplayModel?" + queryString); } /* Decide which form to forward to, set subjectUri, subjectUriJson, predicateUri, and predicateUriJson in request. diff --git a/webapp/web/js/menupage/menumanagement_edit.js b/webapp/web/js/menupage/menumanagement_edit.js new file mode 100644 index 000000000..d7cee5337 --- /dev/null +++ b/webapp/web/js/menupage/menumanagement_edit.js @@ -0,0 +1,92 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +var menuManagementEdit = { + onLoad: function() { + this.initObjects(); + this.bindEventListeners(); + }, + initObjects: function() { + this.changeContentType = $('#changeContentType'); + this.selectContentType = $('#selectContentType'); + this.existingContentType = $('#existingContentType'); + this.selectClassGroupDropdown = $('#selectClassGroup'); + this.classesForClassGroup = $('#classesInSelectedGroup'); + this.selectedGroupForPage = $('#selectedContentTypeValue'); + this.selectClassesMessage = $('#selectClassesMessage'); + + }, + bindEventListeners: function() { + // Listeners for vClass switching + this.changeContentType.click(function() { + alert("change content type"); + menuManagementEdit.showClassGroups(); + return false; + }); + this.selectClassGroupDropdown.change(function() { + alert("select class group dropdown"); + chooseClassGroup(); + return false; + }); + }, + showClassGroups: function() { + if(!this.existingContentType.hasClass("hide")) { + this.existingContentType.addClass("hide"); + this.selectClassesMessage.addClass("hide"); + this.classesForClassGroup.addClass("hide"); + } + this.selectContentType.removeClass("hide"); + + }, + hideClassGroups: function() { + if(!this.selectContentType.hasClass("hide")) { + + this.selectContentType.addClass("hide"); + } + this.existingContentType.removeClass("hide"); + this.selectClassesMessage.removeClass("hide"); + this.classesForClassGroup.removeClass("hide"); + } + , + chooseClassGroup: function() { + + var uri = "/dataservice?getSolrIndividualsByVClass=1&vclassId="; + var vclassUri = this.selectClassGroupDropdown.val(); + uri += encodeURIComponent(vclassUri); + alert("URI for class group " + uri); + //Make ajax call to retrieve vclasses + $.getJSON(url, function(results) { + + if ( results.classes.length == 0 ) { + + } else { + //update existing content type with correct class group name and hide class group select again + this.hideClassGroups(); + + this.selectedGroupForPage.html(results.classGroupName); + //retrieve classes for class group and display with all selected + this.classesForClassGroup.empty(); + this.classesForClassGroup.append("
    "); + this.classesForClassGroup.append('
  • ' + + '' + + '' + + '
  • '); + $.each(results.classes, function(i, item) { + var thisClass = results.classes[i]; + var thisClassName = thisClass.name; + this.classesForClassGroup.append('
  • ' + + '' + + '' + + '
  • '); + }); + this.classesForClassGroup.append("
"); + + + } + + }); + } +}; + +$(document).ready(function() { + menuManagementEdit.onLoad(); +}); \ No newline at end of file diff --git a/webapp/web/templates/freemarker/edit/forms/menuManagementForm.ftl b/webapp/web/templates/freemarker/edit/forms/menuManagementForm.ftl index 4faa859e7..e8233a324 100644 --- a/webapp/web/templates/freemarker/edit/forms/menuManagementForm.ftl +++ b/webapp/web/templates/freemarker/edit/forms/menuManagementForm.ftl @@ -55,7 +55,7 @@ <#if selectedTemplateType = "custom"> - * + *

Select content type for the associated page

diff --git a/webapp/web/templates/freemarker/edit/forms/testMenuManagement.ftl b/webapp/web/templates/freemarker/edit/forms/testMenuManagement.ftl new file mode 100644 index 000000000..55166c913 --- /dev/null +++ b/webapp/web/templates/freemarker/edit/forms/testMenuManagement.ftl @@ -0,0 +1,101 @@ +<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> + +<#--Since we are going to use one template for adding and editing a menu item, + it will be necessary to provide a freemarker variable that lets us know if you are in edit or add mode. bThis is up + to you Huda the way you implement it. --> + +<#-- some additional processing here which shows or hides the class group selection and classes based on initial action--> +<#assign existingClassGroupStyle = " " /> +<#assign selectClassGroupStyle = 'class="hide"' /> +<#if menuAction = "Add"> + <#assign existingClassGroupStyle = 'class="hide"' /> + <#assign selectClassGroupStyle = " " /> + + +

${menuAction} menu item

+ +
+
+ + ${menuAction} menu item + + + + + + +

(Format: / - ie. /people)

+ + <#--Commented out for now --> + + +

Template *

+ + checked /> + + +
+ + checked /> + + + <#if selectedTemplateType = "custom"> + * + + +
+

Selected content type for the associated page

+

${associatedPage} Change content type

+
+ + +
+ + +
+ +

Select content to display

+
+ +
    + <#--Adding a default class for "ALL" in case all classes selected--> +
  • + checked + +
  • + <#list classGroup as classInClassGroup> +
  • + checked /> + + <#--sortable icon for dragging and dropping menu items--> +
  • + +
+
+ + or Cancel + +

* required fields

+
+
+ + +<#-- Add necessary css files associated with this page +${stylesheets.add('')}--> +${stylesheets.add('')} +${stylesheets.add('')} + +<#-- Add necessary javascript files associated with this page --> +${scripts.add('')}