/*
* ChoiceLookupTransformer.java
*
* Version: $Revision: 3705 $
*
* Date: $Date: 2009-04-11 13:02:24 -0400 (Sat, 11 Apr 2009) $
*
* Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of the DSpace Foundation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package org.dspace.app.xmlui.aspect.general;
import java.io.IOException;
import java.io.Serializable;
import java.sql.SQLException;
import javax.servlet.http.HttpServletResponse;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.DCPersonName;
import org.dspace.core.ConfigurationManager;
import org.apache.cocoon.caching.CacheableProcessingComponent;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.http.HttpEnvironment;
import org.apache.cocoon.util.HashUtil;
import org.apache.excalibur.source.SourceValidity;
import org.apache.excalibur.source.impl.validity.NOPValidity;
import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingConstants;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.Body;
import org.dspace.app.xmlui.wing.element.Composite;
import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.app.xmlui.wing.element.Hidden;
import org.dspace.app.xmlui.wing.element.List;
import org.dspace.app.xmlui.wing.element.Item;
import org.dspace.app.xmlui.wing.element.Select;
import org.dspace.app.xmlui.wing.element.Text;
import org.dspace.app.xmlui.wing.element.Button;
import org.dspace.authorize.AuthorizeException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.apache.log4j.Logger;
/**
* Create the "lookup" popup window for Choice Control. It loads a selector
* via AJAX request, and transfers values (both text and authority/confidence)
* back to the indicated form fields in the window that launched it.
* Some necessary logic is in JavaScript, see choice-control.js.
*
* Expected Parameters:
* field - name of metadata field in "_" notation, eg: dc_contributor_author
* value - maybe-partial value of field
* formID - the @id of <form> tag in calling window containing the inputs we are to set.
* valueInput - @name of input field in DOM for value.
* authorityInput - @name of input field in DOM for authority value
* isRepeating - true if metadata value can be repeated
* isName - true if this is a name value (i.e. last/first boxes)
* start - starting index, default 0
* limit - maximum values to return, default 0 (none)
*
* Configuration Properties:
* xmlui.lookup.select.size = 12 (default, entries to show in SELECT widget.)
*
* For each FIELD, e.g. dc.contributor.author, these message properties
* will OVERRIDE the corresponding i18n message catalog entries:
* xmlui.lookup.field.FIELD.title = title of lookup page
* (e.g. xmlui.lookup.field.dc_contributor_author.title = Author..)
* xmlui.lookup.field.FIELD.nonauthority = template for "non-authority" label in options
* xmlui.lookup.field.FIELD.help = help message for single input
* (NOTE this is still required even for name inputs)
* xmlui.lookup.field.FIELD.help.last = help message for last name of Name-oriented input
* xmlui.lookup.field.FIELD.help.first = help message for first name of Name-oriented input
*
* @author Larry Stone
*/
public class ChoiceLookupTransformer extends AbstractDSpaceTransformer
{
/** log4j logger */
private static Logger log = Logger.getLogger(ChoiceLookupTransformer.class);
private static final String CONFIG_PREFIX = "xmlui.lookup.field.";
/** Language Strings */
private static final String MESSAGE_PREFIX = "xmlui.ChoiceLookupTransformer.";
private static final Message T_title = message(MESSAGE_PREFIX+"title");
private static final Message T_add = message(MESSAGE_PREFIX+"add");
private static final Message T_accept = message(MESSAGE_PREFIX+"accept");
private static final Message T_more = message(MESSAGE_PREFIX+"more");
private static final Message T_cancel = message(MESSAGE_PREFIX+"cancel");
private static final Message T_results = message(MESSAGE_PREFIX+"results");
private static final Message T_fail = message(MESSAGE_PREFIX+"fail");
public void addBody(Body body) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException
{
String field = null;
String value = null;
String formID = null;
String confIndicatorID = null;
boolean isName = false;
boolean isRepeating = false;
String valueInput = null;
String authorityInput = null;
int start = 0;
int limit = 0;
String collection = null;
// HTTP parameters:
try
{
field = parameters.getParameter("field");
value = parameters.getParameter("value");
formID = parameters.getParameter("formID");
confIndicatorID = parameters.getParameter("confIndicatorID");
isName = parameters.getParameterAsBoolean("isName", false);
isRepeating = parameters.getParameterAsBoolean("isRepeating", false);
valueInput = parameters.getParameter("valueInput");
authorityInput = parameters.getParameter("authorityInput");
String sStart = parameters.getParameter("start");
if (sStart != null)
start = atoi(sStart);
String sLimit = parameters.getParameter("limit");
if (sLimit != null)
limit = atoi(sLimit);
collection = parameters.getParameter("collection");
if (collection == null)
collection = "-1";
}
catch (org.apache.avalon.framework.parameters.ParameterException e)
{
throw new UIException("Missing a required parameter",e);
}
Division idiv = body.addInteractiveDivision("lookup", "", "get", "popup");
if (isFieldMessage(field, "title"))
idiv.setHead(getFieldMessage(field, "title"));
else
idiv.setHead(getFieldLabel(field, "title"));
List fl = idiv.addList("choicesList", "form", "choices-lookup");
fl.setHead(T_results);
// the <select> tag, and param values
Item selectItem = fl.addItem("select", "choices-lookup");
Select s = selectItem.addSelect("chooser", "choices-lookup");
s.setSize(ConfigurationManager.getIntProperty("xmlui.lookup.select.size", 12));
// parameters for javascript
Hidden h = selectItem.addHidden("paramField");
h.setValue(field);
h = selectItem.addHidden("paramValue");
h.setValue(value);
h = selectItem.addHidden("paramIsName");
h.setValue(String.valueOf(isName));
h = selectItem.addHidden("paramIsRepeating");
h.setValue(String.valueOf(isRepeating));
h = selectItem.addHidden("paramValueInput");
h.setValue(valueInput);
h = selectItem.addHidden("paramAuthorityInput");
h.setValue(authorityInput);
h = selectItem.addHidden("paramStart");
h.setValue(String.valueOf(start));
h = selectItem.addHidden("paramLimit");
h.setValue(String.valueOf(limit));
h = selectItem.addHidden("paramFormID");
h.setValue(formID);
h = selectItem.addHidden("paramConfIndicatorID");
h.setValue(confIndicatorID);
h = selectItem.addHidden("paramFail");
h.setValue(T_fail);
boolean isClosed = ChoiceAuthorityManager.getManager().isClosed(field);
h = selectItem.addHidden("paramIsClosed");
h.setValue(String.valueOf(isClosed));
h = selectItem.addHidden("paramCollection");
h.setValue(String.valueOf(collection));
if (!isClosed)
{
h = selectItem.addHidden("paramNonAuthority");
if (isFieldMessage(field, "nonauthority"))
h.setValue(getFieldMessage(field, "nonauthority"));
else
h.setValue(getFieldLabel(field, "nonauthority"));
}
h = selectItem.addHidden("contextPath");
h.setValue(contextPath);
// NOTE: the "spinner" indicator image gets added in the XSLT.
// the text input(s)
Item ti = fl.addItem("textFields", "choices-lookup");
Composite textItem = ti.addComposite("textFieldsComp", "choices-lookup");
Text t1 = textItem.addText("text1", "choices-lookup");
if (isName)
{
Text t2 = textItem.addText("text2", "choices-lookup");
DCPersonName dp = new DCPersonName(value);
t1.setValue(dp.getLastName());
t2.setValue(dp.getFirstNames());
if (isFieldMessage(field, "help.last"))
{
Message m = getFieldMessage(field, "help.last");
t1.setLabel(m);
t1.setHelp(m);
}
else
{
String m = getFieldLabel(field, "help.last");
t1.setLabel(m);
t1.setHelp(m);
}
if (isFieldMessage(field, "help.first"))
{
Message m = getFieldMessage(field, "help.first");
t2.setLabel(m);
t2.setHelp(m);
}
else
{
String m = getFieldLabel(field, "help.first");
t2.setLabel(m);
t2.setHelp(m);
}
}
else
{
t1.setValue(value);
if (isFieldMessage(field, "help"))
{
Message m = getFieldMessage(field, "help");
t1.setLabel(m);
t1.setHelp(m);
}
else
{
String m = getFieldLabel(field, "help");
t1.setLabel(m);
t1.setHelp(m);
}
}
// confirmation buttons
Item buttItem = fl.addItem("confirmation", "choices-lookup");
Button accept = buttItem.addButton("accept", "choices-lookup");
accept.setValue(isRepeating ? T_add : T_accept);
Button more = buttItem.addButton("more", "choices-lookup");
more.setDisabled();
more.setValue(T_more);
Button cancel = buttItem.addButton("cancel", "choices-lookup");
cancel.setValue(T_cancel);
}
public void addPageMeta(PageMeta pageMeta) throws SAXException,
WingException, UIException, SQLException, IOException,
AuthorizeException
{
// Set the page title
pageMeta.addMetadata("title").addContent(T_title);
// This invokes magic popup transformation in XSL - "framing.popup"
pageMeta.addMetadata("framing","popup").addContent("true");
}
/**
* Protocol to get custom and/or i18n strings:
* For label NAME,
* .. if config key xmlui.choices.FIELD.NAME is defined, and starts
* with "xmlui.", then it's a message key.
* .. if NO config key is defined, look for message
* xmlui.ChoiceLookupTransformer.field.FIELD.NAME
* .. otherwise take literal value from configuration
*/
// return true if configured (or lack thereof) value points to Message
private boolean isFieldMessage(String field, String name)
{
String cv = getFieldLabel(field, name);
return (cv == null || cv.startsWith("xmlui."));
}
// get field-specific label value
private String getFieldLabel(String field, String name)
{
return ConfigurationManager.getProperty(CONFIG_PREFIX+field+"."+name);
}
// get field-specific label value
private Message getFieldMessage(String field, String name)
{
String cv = getFieldLabel(field, name);
if (cv == null)
return message(MESSAGE_PREFIX+"field."+field+"."+name);
else
return message(cv);
}
private int atoi(String s)
{
try
{
return Integer.parseInt(s);
}
catch (Exception e) {}
return 0;
}
}