Working on custom forms in freemarker.

This commit is contained in:
bdc34 2010-11-17 17:40:04 +00:00
parent aba71e6913
commit 0b2dc61fbe
8 changed files with 398 additions and 47 deletions

View file

@ -0,0 +1,88 @@
/* $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 javax.servlet.http.HttpSession;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.EditSubmission;
import freemarker.template.ObjectWrapper;
import freemarker.template.TemplateModelException;
/**
* This controller is intended to place N3 editing data into the
* FM data model and output the FM template for the form.
*/
public class N3EditFormController extends FreemarkerHttpServlet{
@Override
protected ResponseValues processRequest(VitroRequest vreq) {
try{
//get edit objects
HttpSession session = vreq.getSession(false);
if( session == null )
throw new Exception("Cannot get session");
EditConfiguration editConfig = EditConfiguration.getConfigFromSession(session, vreq);
if(editConfig == null )
throw new Exception("Cannot get EditConfiguration from session");
EditSubmission editSubmission = EditSubmission.getEditSubmissionFromSession(session, editConfig);
//add edit info to the template data model and call template
Map<String,Object> map = makeEditDataMap(editConfig, editSubmission);
//how do I add css or js?
//The jsp is adding css and js like this:
/*
List<String> customJs = new ArrayList<String>(Arrays.asList(JavaScript.JQUERY_UI.path(),
JavaScript.CUSTOM_FORM_UTILS.path(),
"/edit/forms/js/customFormWithAutocomplete.js"
));
request.setAttribute("customJs", customJs);
List<String> customCss = new ArrayList<String>(Arrays.asList(Css.JQUERY_UI.path(),
Css.CUSTOM_FORM.path(),
"/edit/forms/css/customFormWithAutocomplete.css"
));
request.setAttribute("customCss", customCss);
*/
//What needs to happen??
//map.put(???);
return new TemplateResponseValues(editConfig.getTemplate(), map);
}catch(Exception ex){
return new ExceptionResponseValues(ex);
}
}
/**
* This method get data out of the editConfig and editSubmission for the template.
* @throws TemplateModelException
*/
private Map<String, Object> makeEditDataMap(EditConfiguration editConfig,
EditSubmission editSubmission) throws TemplateModelException {
Map<String,Object> map = new HashMap<String,Object>();
//This dosen't seem to be the right thing:
map.put("editConfig", ObjectWrapper.BEANS_WRAPPER.wrap(editConfig));
//<@dump var="editConfig"/> outputs:
/*
* Template variable dump
Variable name: editConfig
Type: string
Value: edu.cornell.mannlib.vitro.webapp.edit.n3editing.EditConfiguration@1e60601
*/
if( editSubmission != null)
map.put("editSubmission", ObjectWrapper.BEANS_WRAPPER.wrap(editSubmission));
return map;
}
}

View file

@ -9,6 +9,7 @@ import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.Field;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
@ -16,6 +17,12 @@ import freemarker.template.TemplateException;
public abstract class BaseEditElement implements EditElement {
private static final Log log = LogFactory.getLog(BaseEditElement.class);
protected Field field;
public BaseEditElement(Field field){
this.field = field;
}
/**
* Utility method for use in EditElements to merge a freemarker template.
*/

View file

@ -10,8 +10,9 @@ import edu.cornell.mannlib.vitro.webapp.edit.n3editing.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.EditSubmission;
import freemarker.template.Configuration;
/**
* All classes that implement this interface must have a public empty constructor that
* will be called with using reflection.
* All classes that implement this interface must have a public constructor that
* takes a edu.cornell.mannlib.vitro.webapp.edit.n3editing.Field. It will be
* called with using reflection.
*/
public interface EditElement {
/**
@ -36,5 +37,11 @@ public interface EditElement {
* This is a method to generate the HTML output for a form element. It should use a freemarker template
* to produce the output.
*/
public String draw(String fieldName, EditConfiguration editConfig, EditSubmission editSub, Configuration fmConfig);
public String draw(String fieldName, EditConfiguration editConfig, EditSubmission editSub, Configuration fmConfig);
/**
* We may need a method to get existing URIs and Literals for use in building retraction statements?
*/
// public Map<String,Literal> getExistingLiterals(?);
// public Map<String,Literal> getExistingURIs(?);
}

View file

@ -97,6 +97,12 @@ public class EditConfiguration {
private ProhibitedFromSearch prohibitedFromSearch;
/** Name of freemarker template to generate form. */
String template;
/** URL to submit form to. */
String submitToUrl;
/**
* If true, then any dependent resources that are unlinked should be
* removed using DependentResourceDelete.
@ -943,4 +949,20 @@ public class EditConfiguration {
public List<EditSubmissionPreprocessor> getEditSubmissionPreprocessors() {
return editSubmissionPreprocessors;
}
public void setTemplate(String template){
this.template = template;
}
public String getTemplate() {
return this.template;
}
public String getSubmitToUrl() {
return submitToUrl;
}
public void setSubmitToUrl(String submitToUrl) {
this.submitToUrl = submitToUrl;
}
}

View file

@ -123,6 +123,7 @@ public class Field {
/* *********************** Constructors ************************** */
public Field(String config, String varName) {
name=varName;
JSONObject jsonObj = null;
try{
jsonObj = new JSONObject(config);
@ -138,8 +139,8 @@ public class Field {
}
public Field() {}
private static String[] parameterNames = {"newResource","validators","optionsType","predicateUri","objectClassUri","rangeDatatypeUri","rangeLang","literalOptions","assertions"};
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){
@ -161,7 +162,8 @@ public class Field {
setLiteralOptions(obj.getJSONArray("literalOptions"));
setAssertions(EditConfiguration.JsonArrayToStringList(obj.getJSONArray("assertions")));
setEditElement( obj, fieldName);
//check for odd parameters
JSONArray names = obj.names();
@ -178,7 +180,56 @@ public class Field {
}
/**
* A field may specify a class for additional features.
*/
private void setEditElement(JSONObject fieldConfigObj, String fieldName) {
String className = fieldConfigObj.optString("editElement");
if( className == null || className.isEmpty() )
return;
setOptionsType(Field.OptionsType.UNDEFINED);
Class clz = null;
try {
clz = Class.forName(className);
} catch (ClassNotFoundException e) {
log.error("Java Class " + className + " not found for field " + name);
return;
} catch (SecurityException e) {
log.error("Problem with Java Class " + className + " for field " + name, e);
return;
} catch (IllegalArgumentException e) {
log.error("Problem with Java Class " +className + " for field " + name, e);
return;
}
Class[] types = new Class[]{ Field.class };
Constructor cons;
try {
cons = clz.getConstructor(types);
} catch (SecurityException e) {
log.error("Problem with Java Class " + className + " for field " + name, e);
return;
} catch (NoSuchMethodException e) {
log.error("Java Class " + className + " must have a constructor that takes a Field.", e);
return;
}
Object[] args = new Object[] { this };
Object obj;
try {
obj = cons.newInstance(args);
} catch (Exception e) {
log.error("Problem with Java Class " + className + " for field " + name, e);
return;
}
editElement = (EditElement)obj;
}
/* ****************** Getters and Setters ******************************* */
public String getName(){
return name;
}
public List<String> getRetractions() {
return retractions;
@ -217,62 +268,43 @@ public class Field {
optionsType = ot;
}
public void setOptionsType(String s) {
setOptionsType( getOptionForString(s));
}
public static OptionsType getOptionForString(String s){
if( s== null || s.isEmpty() )
return OptionsType.UNDEFINED;
if ("LITERALS".equals(s)) {
setOptionsType(Field.OptionsType.LITERALS);
return Field.OptionsType.LITERALS;
} else if ("HARDCODED_LITERALS".equals(s)) {
setOptionsType(Field.OptionsType.HARDCODED_LITERALS);
return Field.OptionsType.HARDCODED_LITERALS;
} else if ("STRINGS_VIA_DATATYPE_PROPERTY".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.STRINGS_VIA_DATATYPE_PROPERTY);
return Field.OptionsType.STRINGS_VIA_DATATYPE_PROPERTY;
} else if ("INDIVIDUALS_VIA_OBJECT_PROPERTY".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.INDIVIDUALS_VIA_OBJECT_PROPERTY);
return Field.OptionsType.INDIVIDUALS_VIA_OBJECT_PROPERTY;
} else if ("INDIVIDUALS_VIA_VCLASS".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.INDIVIDUALS_VIA_VCLASS);
return Field.OptionsType.INDIVIDUALS_VIA_VCLASS;
} else if ("MONIKERS_VIA_VCLASS".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.MONIKERS_VIA_VCLASS);
return Field.OptionsType.MONIKERS_VIA_VCLASS;
} else if ("DATETIME".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.DATETIME);
return Field.OptionsType.DATETIME;
} else if ("CHILD_VCLASSES".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.CHILD_VCLASSES);
return Field.OptionsType.CHILD_VCLASSES;
} else if ("CHILD_VCLASSES_WITH_PARENT".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.CHILD_VCLASSES_WITH_PARENT);
return Field.OptionsType.CHILD_VCLASSES_WITH_PARENT;
} else if ("VCLASSGROUP".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.VCLASSGROUP);
return Field.OptionsType.VCLASSGROUP;
} else if ("FILE".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.FILE);
return Field.OptionsType.FILE;
} else if ("DATE".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.DATE);
return Field.OptionsType.DATE;
} else if ("TIME".equalsIgnoreCase(s)) {
setOptionsType(Field.OptionsType.TIME);
} else if ("UNDEFINED".equalsIgnoreCase(s) || s == null || s.isEmpty()){
setOptionsType(Field.OptionsType.UNDEFINED);
return Field.OptionsType.TIME;
} else {
setSpecalOptionType(s);
}
return Field.OptionsType.UNDEFINED;
}
}
private void setSpecalOptionType(String s) {
try {
Class clz = Class.forName(s);
Object obj = clz.newInstance();
editElement = (EditElement)obj;
} catch (ClassNotFoundException e) {
log.error("Java Class " + s + " not found for field " + name);
setOptionsType(Field.OptionsType.UNDEFINED);
} catch (SecurityException e) {
log.error("Problem with Java Class " + s + " for field " + name, e);
setOptionsType(Field.OptionsType.UNDEFINED);
} catch (IllegalArgumentException e) {
log.error("Problem with Java Class " + s + " for field " + name, e);
setOptionsType(Field.OptionsType.UNDEFINED);
} catch (InstantiationException e) {
log.error("Problem with Java Class " + s + " for field " + name, e);
setOptionsType(Field.OptionsType.UNDEFINED);
} catch (IllegalAccessException e) {
log.error("Problem with Java Class " + s + " for field " + name, e);
setOptionsType(Field.OptionsType.UNDEFINED);
}
}
public String getPredicateUri() {
return predicateUri;
}
@ -364,5 +396,10 @@ public class Field {
public EditElement getEditElement(){
return editElement;
}
/* this is mainly for unit testing */
public void setName(String name){
this.name = name;
}
}

View file

@ -0,0 +1,59 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.widgets;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.SelectListGenerator;
import edu.cornell.mannlib.vitro.webapp.web.directives.WidgetDirective;
import freemarker.core.Environment;
import freemarker.template.SimpleScalar;
public class SelectListWidget extends Widget {
private static final Log log = LogFactory.getLog(SelectListWidget.class);
@Override
protected WidgetTemplateValues process(Environment env, Map params,
HttpServletRequest request, ServletContext context) {
Object obj = params.get("fieldName");
if( obj == null || !(obj instanceof SimpleScalar)){
log.error("SelectListWidget must have a parameter 'fieldName'");
throw new Error("SelectListWidget must have a parameter'fieldName'");
}
String fieldName = ((SimpleScalar)obj).getAsString();
if( fieldName.isEmpty() ){
log.error("SelectListWidget must have a parameter 'fieldName'");
throw new Error("SelectListWidget must have a parameter 'fieldName' of type String");
}
VitroRequest vreq = new VitroRequest(request);
HttpSession session = request.getSession(false);
EditConfiguration editConfig = EditConfiguration.getConfigFromSession(session,request);
WebappDaoFactory wdf;
if (editConfig != null) {
wdf = editConfig.getWdfSelectorForOptons().getWdf(vreq,context);
} else {
wdf = vreq.getWebappDaoFactory();
}
Map<String,String> selectOptions = SelectListGenerator.getOptions(editConfig, fieldName, wdf);
Map<String,Object> rmap = new HashMap<String,Object>();
rmap.put("selectList", selectOptions);
return new WidgetTemplateValues("markup", rmap);
}
}