[DS-236] Authority control for metadata fields and Choice Authority plugin framework

git-svn-id: http://scm.dspace.org/svn/repo/dspace/trunk@4365 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Larry Stone
2009-10-05 23:52:42 +00:00
parent fa86734005
commit bbe8a2a3d1
142 changed files with 16729 additions and 3390 deletions

View File

@@ -181,8 +181,8 @@
<artifactId>icu4j</artifactId> <artifactId>icu4j</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>oclc-harvester2</artifactId> <artifactId>oclc-harvester2</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
@@ -192,6 +192,10 @@
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-services-impl</artifactId> <artifactId>dspace-services-impl</artifactId>
</dependency> </dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -5,7 +5,8 @@
* *
* Date: $Date$ * Date: $Date$
* *
* Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved. * Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts
* Institute of Technology. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@@ -18,7 +19,8 @@
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* - Neither the name of the DSpace Foundation nor the names of its * - Neither the name of the Hewlett-Packard Company nor the name of the
* Massachusetts Institute of Technology nor the names of their
* contributors may be used to endorse or promote products derived from * contributors may be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
@@ -39,11 +41,10 @@
package org.dspace.app.util; package org.dspace.app.util;
import java.io.File; import java.io.File;
import java.util.List;
import java.util.Vector; import java.util.Vector;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator; import java.util.Iterator;
import java.lang.Exception;
import javax.servlet.ServletException;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import org.w3c.dom.*; import org.w3c.dom.*;
import javax.xml.parsers.*; import javax.xml.parsers.*;
@@ -134,48 +135,58 @@ public class DCInputsReader
*/ */
public DCInputsReader() public DCInputsReader()
throws ServletException throws DCInputsReaderException
{ {
buildInputs(defsFile); buildInputs(defsFile);
} }
public DCInputsReader(String fileName) public DCInputsReader(String fileName)
throws ServletException throws DCInputsReaderException
{ {
buildInputs(fileName); buildInputs(fileName);
} }
private void buildInputs(String fileName) private void buildInputs(String fileName)
throws ServletException throws DCInputsReaderException
{ {
whichForms = new HashMap(); whichForms = new HashMap();
formDefns = new HashMap(); formDefns = new HashMap();
valuePairs = new HashMap(); valuePairs = new HashMap();
String uri = "file:" + new File(fileName).getAbsolutePath(); String uri = "file:" + new File(fileName).getAbsolutePath();
try try
{ {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false); factory.setValidating(false);
factory.setIgnoringComments(true); factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true); factory.setIgnoringElementContentWhitespace(true);
DocumentBuilder db = factory.newDocumentBuilder(); DocumentBuilder db = factory.newDocumentBuilder();
Document doc = db.parse(uri); Document doc = db.parse(uri);
doNodes(doc); doNodes(doc);
checkValues(); checkValues();
} }
catch (FactoryConfigurationError fe) catch (FactoryConfigurationError fe)
{ {
throw new ServletException("Cannot create Submission form parser",fe); throw new DCInputsReaderException("Cannot create Submission form parser",fe);
} }
catch (Exception e) catch (Exception e)
{ {
throw new ServletException("Error creating submission forms: "+e); throw new DCInputsReaderException("Error creating submission forms: "+e);
} }
}
public Iterator getPairsNameIterator()
{
return valuePairs.keySet().iterator();
}
public List getPairs(String name)
{
return (Vector)valuePairs.get(name);
} }
/** /**
@@ -185,46 +196,46 @@ public class DCInputsReader
* @param collectionHandle * @param collectionHandle
* collection's unique Handle * collection's unique Handle
* @return DC input set * @return DC input set
* @throws ServletException * @throws DCInputsReaderException
* if no default set defined * if no default set defined
*/ */
public DCInputSet getInputs(String collectionHandle) public DCInputSet getInputs(String collectionHandle)
throws ServletException throws DCInputsReaderException
{ {
String formName = (String)whichForms.get(collectionHandle); String formName = (String)whichForms.get(collectionHandle);
if (formName == null) if (formName == null)
{ {
formName = (String)whichForms.get(DEFAULT_COLLECTION); formName = (String)whichForms.get(DEFAULT_COLLECTION);
} }
if (formName == null) if (formName == null)
{ {
throw new ServletException("No form designated as default"); throw new DCInputsReaderException("No form designated as default");
} }
// check mini-cache, and return if match // check mini-cache, and return if match
if ( lastInputSet != null && lastInputSet.getFormName().equals( formName ) ) if ( lastInputSet != null && lastInputSet.getFormName().equals( formName ) )
{ {
return lastInputSet; return lastInputSet;
} }
// cache miss - construct new DCInputSet // cache miss - construct new DCInputSet
Vector pages = (Vector)formDefns.get(formName); Vector pages = (Vector)formDefns.get(formName);
if ( pages == null ) if ( pages == null )
{ {
throw new ServletException("Missing the " + formName + " form"); throw new DCInputsReaderException("Missing the " + formName + " form");
} }
lastInputSet = new DCInputSet(formName, pages, valuePairs); lastInputSet = new DCInputSet(formName, pages, valuePairs);
return lastInputSet; return lastInputSet;
} }
/** /**
* Return the number of pages the inputs span for a desginated collection * Return the number of pages the inputs span for a desginated collection
* @param collectionHandle collection's unique Handle * @param collectionHandle collection's unique Handle
* @return number of pages of input * @return number of pages of input
* @throws ServletException if no default set defined * @throws DCInputsReaderException if no default set defined
*/ */
public int getNumberInputPages(String collectionHandle) public int getNumberInputPages(String collectionHandle)
throws ServletException throws DCInputsReaderException
{ {
return getInputs(collectionHandle).getNumberPages(); return getInputs(collectionHandle).getNumberPages();
} }
/** /**
@@ -233,48 +244,48 @@ public class DCInputsReader
* the display/storage word pairs. * the display/storage word pairs.
*/ */
private void doNodes(Node n) private void doNodes(Node n)
throws SAXException, ServletException throws SAXException, DCInputsReaderException
{ {
if (n == null) if (n == null)
{
return;
}
Node e = getElement(n);
NodeList nl = e.getChildNodes();
int len = nl.getLength();
boolean foundMap = false;
boolean foundDefs = false;
for (int i = 0; i < len; i++)
{
Node nd = nl.item(i);
if ((nd == null) || isEmptyTextNode(nd))
{
continue;
}
String tagName = nd.getNodeName();
if (tagName.equals("form-map"))
{
processMap(nd);
foundMap = true;
}
else if (tagName.equals("form-definitions"))
{
processDefinition(nd);
foundDefs = true;
}
else if (tagName.equals("form-value-pairs"))
{
processValuePairs(nd);
}
// Ignore unknown nodes
}
if (!foundMap)
{ {
throw new ServletException("No collection to form map found"); return;
} }
if (!foundDefs) Node e = getElement(n);
NodeList nl = e.getChildNodes();
int len = nl.getLength();
boolean foundMap = false;
boolean foundDefs = false;
for (int i = 0; i < len; i++)
{ {
throw new ServletException("No form definition found"); Node nd = nl.item(i);
if ((nd == null) || isEmptyTextNode(nd))
{
continue;
}
String tagName = nd.getNodeName();
if (tagName.equals("form-map"))
{
processMap(nd);
foundMap = true;
}
else if (tagName.equals("form-definitions"))
{
processDefinition(nd);
foundDefs = true;
}
else if (tagName.equals("form-value-pairs"))
{
processValuePairs(nd);
}
// Ignore unknown nodes
}
if (!foundMap)
{
throw new DCInputsReaderException("No collection to form map found");
}
if (!foundDefs)
{
throw new DCInputsReaderException("No form definition found");
} }
} }
@@ -288,31 +299,31 @@ public class DCInputsReader
private void processMap(Node e) private void processMap(Node e)
throws SAXException throws SAXException
{ {
NodeList nl = e.getChildNodes(); NodeList nl = e.getChildNodes();
int len = nl.getLength(); int len = nl.getLength();
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
Node nd = nl.item(i); Node nd = nl.item(i);
if (nd.getNodeName().equals("name-map")) if (nd.getNodeName().equals("name-map"))
{ {
String id = getAttribute(nd, "collection-handle"); String id = getAttribute(nd, "collection-handle");
String value = getAttribute(nd, "form-name"); String value = getAttribute(nd, "form-name");
String content = getValue(nd); String content = getValue(nd);
if (id == null) if (id == null)
{ {
throw new SAXException("name-map element is missing collection-handle attribute"); throw new SAXException("name-map element is missing collection-handle attribute");
} }
if (value == null) if (value == null)
{ {
throw new SAXException("name-map element is missing form-name attribute"); throw new SAXException("name-map element is missing form-name attribute");
} }
if (content != null && content.length() > 0) if (content != null && content.length() > 0)
{ {
throw new SAXException("name-map element has content, it should be empty."); throw new SAXException("name-map element has content, it should be empty.");
} }
whichForms.put(id, value); whichForms.put(id, value);
} // ignore any child node that isn't a "name-map" } // ignore any child node that isn't a "name-map"
} }
} }
/** /**
@@ -323,71 +334,71 @@ public class DCInputsReader
* required text, and repeatable flag. * required text, and repeatable flag.
*/ */
private void processDefinition(Node e) private void processDefinition(Node e)
throws SAXException, ServletException throws SAXException, DCInputsReaderException
{ {
int numForms = 0; int numForms = 0;
NodeList nl = e.getChildNodes(); NodeList nl = e.getChildNodes();
int len = nl.getLength(); int len = nl.getLength();
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
Node nd = nl.item(i); Node nd = nl.item(i);
// process each form definition // process each form definition
if (nd.getNodeName().equals("form")) if (nd.getNodeName().equals("form"))
{ {
numForms++; numForms++;
String formName = getAttribute(nd, "name"); String formName = getAttribute(nd, "name");
if (formName == null) if (formName == null)
{ {
throw new SAXException("form element has no name attribute"); throw new SAXException("form element has no name attribute");
} }
Vector pages = new Vector(); // the form contains pages Vector pages = new Vector(); // the form contains pages
formDefns.put(formName, pages); formDefns.put(formName, pages);
NodeList pl = nd.getChildNodes(); NodeList pl = nd.getChildNodes();
int lenpg = pl.getLength(); int lenpg = pl.getLength();
for (int j = 0; j < lenpg; j++) for (int j = 0; j < lenpg; j++)
{ {
Node npg = pl.item(j); Node npg = pl.item(j);
// process each page definition // process each page definition
if (npg.getNodeName().equals("page")) if (npg.getNodeName().equals("page"))
{ {
String pgNum = getAttribute(npg, "number"); String pgNum = getAttribute(npg, "number");
if (pgNum == null) if (pgNum == null)
{ {
throw new SAXException("Form " + formName + " has no identified pages"); throw new SAXException("Form " + formName + " has no identified pages");
} }
Vector page = new Vector(); Vector page = new Vector();
pages.add(page); pages.add(page);
NodeList flds = npg.getChildNodes(); NodeList flds = npg.getChildNodes();
int lenflds = flds.getLength(); int lenflds = flds.getLength();
for (int k = 0; k < lenflds; k++) for (int k = 0; k < lenflds; k++)
{ {
Node nfld = flds.item(k); Node nfld = flds.item(k);
if ( nfld.getNodeName().equals("field") ) if ( nfld.getNodeName().equals("field") )
{ {
// process each field definition // process each field definition
HashMap field = new HashMap(); HashMap field = new HashMap();
page.add(field); page.add(field);
processPageParts(formName, pgNum, nfld, field); processPageParts(formName, pgNum, nfld, field);
String error = checkForDups(formName, field, pages); String error = checkForDups(formName, field, pages);
if (error != null) if (error != null)
{ {
throw new SAXException(error); throw new SAXException(error);
} }
} }
} }
} // ignore any child that is not a 'page' } // ignore any child that is not a 'page'
} }
// sanity check number of pages // sanity check number of pages
if (pages.size() < 1) if (pages.size() < 1)
{ {
throw new ServletException("Form " + formName + " has no pages"); throw new DCInputsReaderException("Form " + formName + " has no pages");
} }
} }
} }
if (numForms == 0) if (numForms == 0)
{ {
throw new ServletException("No form definition found"); throw new DCInputsReaderException("No form definition found");
} }
} }
/** /**
@@ -399,78 +410,73 @@ public class DCInputsReader
private void processPageParts(String formName, String page, Node n, HashMap field) private void processPageParts(String formName, String page, Node n, HashMap field)
throws SAXException throws SAXException
{ {
NodeList nl = n.getChildNodes(); NodeList nl = n.getChildNodes();
int len = nl.getLength(); int len = nl.getLength();
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
Node nd = nl.item(i); Node nd = nl.item(i);
if ( ! isEmptyTextNode(nd) ) if ( ! isEmptyTextNode(nd) )
{ {
String tagName = nd.getNodeName(); String tagName = nd.getNodeName();
String value = getValue(nd); String value = getValue(nd);
field.put(tagName, value); field.put(tagName, value);
if (tagName.equals("input-type")) if (tagName.equals("input-type"))
{ {
if (value.equals("dropdown") if (value.equals("dropdown")
|| value.equals("qualdrop_value") || value.equals("qualdrop_value")
|| value.equals("list")) || value.equals("list"))
{ {
String pairTypeName = getAttribute(nd, PAIR_TYPE_NAME); String pairTypeName = getAttribute(nd, PAIR_TYPE_NAME);
if (pairTypeName == null) if (pairTypeName == null)
{ {
throw new SAXException("Form " + formName + ", field " + throw new SAXException("Form " + formName + ", field " +
field.get("dc-element") + field.get("dc-element") +
"." + field.get("dc-qualifier") + "." + field.get("dc-qualifier") +
" has no name attribute"); " has no name attribute");
} }
else else
{ {
field.put(PAIR_TYPE_NAME, pairTypeName); field.put(PAIR_TYPE_NAME, pairTypeName);
} }
} }
} }
else if (tagName.equals("vocabulary")) else if (tagName.equals("vocabulary"))
{ {
String closedVocabularyString = getAttribute(nd, "closed"); String closedVocabularyString = getAttribute(nd, "closed");
field.put("closedVocabulary", closedVocabularyString); field.put("closedVocabulary", closedVocabularyString);
} }
else if (tagName.equals("visibility")) }
{ }
String readOnlyString = getAttribute(nd, "otherwise"); String missing = null;
field.put("readonly", readOnlyString); if (field.get("dc-element") == null)
} {
} missing = "dc-element";
} }
String missing = null; if (field.get("label") == null)
if (field.get("dc-element") == null) {
{ missing = "label";
missing = "dc-element"; }
} if (field.get("input-type") == null)
if (field.get("label") == null) {
{ missing = "input-type";
missing = "label"; }
} if ( missing != null )
if (field.get("input-type") == null) {
{ String msg = "Required field " + missing + " missing on page " + page + " of form " + formName;
missing = "input-type"; throw new SAXException(msg);
} }
if ( missing != null ) String type = (String)field.get("input-type");
{ if (type.equals("twobox") || type.equals("qualdrop_value"))
String msg = "Required field " + missing + " missing on page " + page + " of form " + formName; {
throw new SAXException(msg); String rpt = (String)field.get("repeatable");
if ((rpt == null) ||
((!rpt.equalsIgnoreCase("yes")) &&
(!rpt.equalsIgnoreCase("true"))))
{
String msg = "The field \'"+field.get("label")+"\' must be repeatable";
throw new SAXException(msg);
}
} }
String type = (String)field.get("input-type");
if (type.equals("twobox") || type.equals("qualdrop_value"))
{
String rpt = (String)field.get("repeatable");
if ((rpt == null) ||
((!rpt.equalsIgnoreCase("yes")) &&
(!rpt.equalsIgnoreCase("true"))))
{
String msg = "The field \'"+field.get("label")+"\' must be repeatable";
throw new SAXException(msg);
}
}
} }
/** /**
@@ -548,64 +554,64 @@ public class DCInputsReader
* in the passed in hashmap. * in the passed in hashmap.
*/ */
private void processValuePairs(Node e) private void processValuePairs(Node e)
throws SAXException throws SAXException
{ {
NodeList nl = e.getChildNodes(); NodeList nl = e.getChildNodes();
int len = nl.getLength(); int len = nl.getLength();
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
Node nd = nl.item(i); Node nd = nl.item(i);
String tagName = nd.getNodeName(); String tagName = nd.getNodeName();
// process each value-pairs set // process each value-pairs set
if (tagName.equals("value-pairs")) if (tagName.equals("value-pairs"))
{ {
String pairsName = getAttribute(nd, PAIR_TYPE_NAME); String pairsName = getAttribute(nd, PAIR_TYPE_NAME);
String dcTerm = getAttribute(nd, "dc-term"); String dcTerm = getAttribute(nd, "dc-term");
if (pairsName == null) if (pairsName == null)
{ {
String errString = String errString =
"Missing name attribute for value-pairs for DC term " + dcTerm; "Missing name attribute for value-pairs for DC term " + dcTerm;
throw new SAXException(errString); throw new SAXException(errString);
} }
Vector pairs = new Vector(); Vector pairs = new Vector();
valuePairs.put(pairsName, pairs); valuePairs.put(pairsName, pairs);
NodeList cl = nd.getChildNodes(); NodeList cl = nd.getChildNodes();
int lench = cl.getLength(); int lench = cl.getLength();
for (int j = 0; j < lench; j++) for (int j = 0; j < lench; j++)
{ {
Node nch = cl.item(j); Node nch = cl.item(j);
String display = null; String display = null;
String storage = null; String storage = null;
if (nch.getNodeName().equals("pair")) if (nch.getNodeName().equals("pair"))
{ {
NodeList pl = nch.getChildNodes(); NodeList pl = nch.getChildNodes();
int plen = pl.getLength(); int plen = pl.getLength();
for (int k = 0; k < plen; k++) for (int k = 0; k < plen; k++)
{ {
Node vn= pl.item(k); Node vn= pl.item(k);
String vName = vn.getNodeName(); String vName = vn.getNodeName();
if (vName.equals("displayed-value")) if (vName.equals("displayed-value"))
{ {
display = getValue(vn); display = getValue(vn);
} }
else if (vName.equals("stored-value")) else if (vName.equals("stored-value"))
{ {
storage = getValue(vn); storage = getValue(vn);
if (storage == null) if (storage == null)
{ {
storage = ""; storage = "";
} }
} // ignore any children that aren't 'display' or 'storage' } // ignore any children that aren't 'display' or 'storage'
} }
pairs.add(display); pairs.add(display);
pairs.add(storage); pairs.add(storage);
} // ignore any children that aren't a 'pair' } // ignore any children that aren't a 'pair'
} }
} // ignore any children that aren't a 'value-pair' } // ignore any children that aren't a 'value-pair'
} }
} }
@@ -613,53 +619,53 @@ public class DCInputsReader
* Check that all referenced value-pairs are present * Check that all referenced value-pairs are present
* and field is consistent * and field is consistent
* *
* Throws ServletException if detects a missing value-pair. * Throws DCInputsReaderException if detects a missing value-pair.
*/ */
private void checkValues() private void checkValues()
throws ServletException throws DCInputsReaderException
{ {
// Step through every field of every page of every form // Step through every field of every page of every form
Iterator ki = formDefns.keySet().iterator(); Iterator ki = formDefns.keySet().iterator();
while (ki.hasNext()) while (ki.hasNext())
{ {
String idName = (String)ki.next(); String idName = (String)ki.next();
Vector pages = (Vector)formDefns.get(idName); Vector pages = (Vector)formDefns.get(idName);
for (int i = 0; i < pages.size(); i++) for (int i = 0; i < pages.size(); i++)
{ {
Vector page = (Vector)pages.get(i); Vector page = (Vector)pages.get(i);
for (int j = 0; j < page.size(); j++) for (int j = 0; j < page.size(); j++)
{ {
HashMap fld = (HashMap)page.get(j); HashMap fld = (HashMap)page.get(j);
// verify reference in certain input types // verify reference in certain input types
String type = (String)fld.get("input-type"); String type = (String)fld.get("input-type");
if (type.equals("dropdown") if (type.equals("dropdown")
|| type.equals("qualdrop_value") || type.equals("qualdrop_value")
|| type.equals("list")) || type.equals("list"))
{ {
String pairsName = (String)fld.get(PAIR_TYPE_NAME); String pairsName = (String)fld.get(PAIR_TYPE_NAME);
Vector v = (Vector)valuePairs.get(pairsName); Vector v = (Vector)valuePairs.get(pairsName);
if (v == null) if (v == null)
{ {
String errString = "Cannot find value pairs for " + pairsName; String errString = "Cannot find value pairs for " + pairsName;
throw new ServletException(errString); throw new DCInputsReaderException(errString);
} }
} }
// if visibility restricted, make sure field is not required // if visibility restricted, make sure field is not required
String visibility = (String)fld.get("visibility"); String visibility = (String)fld.get("visibility");
if (visibility != null && visibility.length() > 0 ) if (visibility != null && visibility.length() > 0 )
{ {
String required = (String)fld.get("required"); String required = (String)fld.get("required");
if (required != null && required.length() > 0) if (required != null && required.length() > 0)
{ {
String errString = "Field '" + (String)fld.get("label") + String errString = "Field '" + (String)fld.get("label") +
"' is required but invisible"; "' is required but invisible";
throw new ServletException(errString); throw new DCInputsReaderException(errString);
} }
} }
} }
} }
} }
} }
private Node getElement(Node nd) private Node getElement(Node nd)
@@ -668,10 +674,10 @@ public class DCInputsReader
int len = nl.getLength(); int len = nl.getLength();
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
Node n = nl.item(i); Node n = nl.item(i);
if (n.getNodeType() == Node.ELEMENT_NODE) if (n.getNodeType() == Node.ELEMENT_NODE)
{ {
return n; return n;
} }
} }
return null; return null;
@@ -679,16 +685,16 @@ public class DCInputsReader
private boolean isEmptyTextNode(Node nd) private boolean isEmptyTextNode(Node nd)
{ {
boolean isEmpty = false; boolean isEmpty = false;
if (nd.getNodeType() == Node.TEXT_NODE) if (nd.getNodeType() == Node.TEXT_NODE)
{ {
String text = nd.getNodeValue().trim(); String text = nd.getNodeValue().trim();
if (text.length() == 0) if (text.length() == 0)
{ {
isEmpty = true; isEmpty = true;
} }
} }
return isEmpty; return isEmpty;
} }
/** /**
@@ -696,22 +702,22 @@ public class DCInputsReader
*/ */
private String getAttribute(Node e, String name) private String getAttribute(Node e, String name)
{ {
NamedNodeMap attrs = e.getAttributes(); NamedNodeMap attrs = e.getAttributes();
int len = attrs.getLength(); int len = attrs.getLength();
if (len > 0) if (len > 0)
{ {
int i; int i;
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
{ {
Node attr = attrs.item(i); Node attr = attrs.item(i);
if (name.equals(attr.getNodeName())) if (name.equals(attr.getNodeName()))
{ {
return attr.getNodeValue().trim(); return attr.getNodeValue().trim();
} }
} }
} }
//no such attribute //no such attribute
return null; return null;
} }
/** /**
@@ -720,18 +726,18 @@ public class DCInputsReader
*/ */
private String getValue(Node nd) private String getValue(Node nd)
{ {
NodeList nl = nd.getChildNodes(); NodeList nl = nd.getChildNodes();
int len = nl.getLength(); int len = nl.getLength();
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++)
{ {
Node n = nl.item(i); Node n = nl.item(i);
short type = n.getNodeType(); short type = n.getNodeType();
if (type == Node.TEXT_NODE) if (type == Node.TEXT_NODE)
{ {
return n.getNodeValue().trim(); return n.getNodeValue().trim();
} }
} }
// Didn't find a text node // Didn't find a text node
return null; return null;
} }
} }

View File

@@ -0,0 +1,87 @@
/*
* DCInputsReaderException.java
*
* Version: $Revision: 3761 $
*
* Date: $Date: 2009-05-07 00:18:02 -0400 (Thu, 07 May 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.util;
/**
* This is a superclass for exceptions representing a failure when
* importing or exporting a package. E.g., unacceptable package format
* or contents. Implementations should throw one of the more specific
* exceptions. This class is intended for declarations and catch clauses.
*
* @author Larry Stone
* @version $Revision: 3761 $
*/
public class DCInputsReaderException extends Exception
{
/**
* No-args constructor.
*/
public DCInputsReaderException()
{
super();
}
/**
* Constructor for a given message.
* @param message diagnostic message.
*/
public DCInputsReaderException(String message)
{
super(message);
}
/**
* Constructor for a given cause.
* @param cause throwable that caused this exception
*/
public DCInputsReaderException(Throwable cause)
{
super(cause);
}
/**
* Constructor to create a new exception wrapping it around another exception.
* @param message diagnostic message.
* @param cause throwable that caused this exception
*/
public DCInputsReaderException(String message, Throwable cause)
{
super(message, cause);
}
}

View File

@@ -152,7 +152,7 @@ public interface BrowseCreateDAO
* @return the database id of the distinct record * @return the database id of the distinct record
* @throws BrowseException * @throws BrowseException
*/ */
public int getDistinctID(String table, String value, String sortValue) throws BrowseException; public int getDistinctID(String table, String value, String authority, String sortValue) throws BrowseException;
/** /**
* Insert the given value and sort value into the distinct index table. This * Insert the given value and sort value into the distinct index table. This
@@ -174,7 +174,7 @@ public interface BrowseCreateDAO
* @return the database id of the created record * @return the database id of the created record
* @throws BrowseException * @throws BrowseException
*/ */
public int insertDistinctRecord(String table, String value, String sortValue) throws BrowseException; public int insertDistinctRecord(String table, String value, String authority, String sortValue) throws BrowseException;
/** /**
* Update a mapping between an item id and a distinct metadata field such as an author, * Update a mapping between an item id and a distinct metadata field such as an author,

View File

@@ -322,6 +322,8 @@ public class BrowseCreateDAOOracle implements BrowseCreateDAO
{ {
String create = "CREATE TABLE " + table + " (" + String create = "CREATE TABLE " + table + " (" +
"id INTEGER PRIMARY KEY, " + "id INTEGER PRIMARY KEY, " +
"distinct_id INTEGER UNIQUE, " +
"authority VARCHAR2(100), " +
"value " + getValueColumnDefinition() + ", " + "value " + getValueColumnDefinition() + ", " +
"sort_value " + getSortColumnDefinition() + "sort_value " + getSortColumnDefinition() +
")"; ")";
@@ -507,19 +509,19 @@ public class BrowseCreateDAOOracle implements BrowseCreateDAO
/* (non-Javadoc) /* (non-Javadoc)
* @see org.dspace.browse.BrowseCreateDAO#getDistinctID(java.lang.String, java.lang.String, java.lang.String) * @see org.dspace.browse.BrowseCreateDAO#getDistinctID(java.lang.String, java.lang.String, java.lang.String)
*/ */
public int getDistinctID(String table, String value, String sortValue) throws BrowseException public int getDistinctID(String table, String value, String authority, String sortValue) throws BrowseException
{ {
TableRowIterator tri = null; TableRowIterator tri = null;
if (log.isDebugEnabled()) if (log.isDebugEnabled())
{ {
log.debug("getDistinctID: table=" + table + ",value=" + value + ",sortValue=" + sortValue); log.debug("getDistinctID: table=" + table + ",value=" + value + ",authority=" + authority + ",sortValue=" + sortValue);
} }
try try
{ {
Object[] params = { value }; Object[] params;
String select = "SELECT id FROM " + table; String select = "SELECT distinct_id FROM " + table;
if (ConfigurationManager.getBooleanProperty("webui.browse.metadata.case-insensitive", false)) if (ConfigurationManager.getBooleanProperty("webui.browse.metadata.case-insensitive", false))
{ {
@@ -536,15 +538,26 @@ public class BrowseCreateDAOOracle implements BrowseCreateDAO
select = select + " WHERE value=?"; select = select + " WHERE value=?";
} }
if (authority != null)
{
select += " AND authority = ?";
params = new Object[]{ value, authority };
}
else
{
select += " AND authority IS NULL";
params = new Object[]{ value };
}
tri = DatabaseManager.query(context, select, params); tri = DatabaseManager.query(context, select, params);
int distinctID = -1; int distinctID = -1;
if (!tri.hasNext()) if (!tri.hasNext())
{ {
distinctID = insertDistinctRecord(table, value, sortValue); distinctID = insertDistinctRecord(table, value, authority, sortValue);
} }
else else
{ {
distinctID = tri.next().getIntColumn("id"); distinctID = tri.next().getIntColumn("distinct_id");
} }
if (log.isDebugEnabled()) if (log.isDebugEnabled())
@@ -640,7 +653,7 @@ public class BrowseCreateDAOOracle implements BrowseCreateDAO
/* (non-Javadoc) /* (non-Javadoc)
* @see org.dspace.browse.BrowseCreateDAO#insertDistinctRecord(java.lang.String, java.lang.String, java.lang.String) * @see org.dspace.browse.BrowseCreateDAO#insertDistinctRecord(java.lang.String, java.lang.String, java.lang.String)
*/ */
public int insertDistinctRecord(String table, String value, String sortValue) throws BrowseException public int insertDistinctRecord(String table, String value, String authority, String sortValue) throws BrowseException
{ {
if (log.isDebugEnabled()) if (log.isDebugEnabled())
{ {
@@ -652,8 +665,14 @@ public class BrowseCreateDAOOracle implements BrowseCreateDAO
TableRow dr = DatabaseManager.create(context, table); TableRow dr = DatabaseManager.create(context, table);
dr.setColumn("value", utils.truncateValue(value)); dr.setColumn("value", utils.truncateValue(value));
dr.setColumn("sort_value", utils.truncateSortValue(sortValue)); dr.setColumn("sort_value", utils.truncateSortValue(sortValue));
DatabaseManager.update(context, dr); if (authority != null)
{
dr.setColumn("authority", utils.truncateValue(authority,100));
}
int distinctID = dr.getIntColumn("id"); int distinctID = dr.getIntColumn("id");
dr.setColumn("distinct_id", distinctID);
DatabaseManager.update(context, dr);
if (log.isDebugEnabled()) if (log.isDebugEnabled())
{ {

View File

@@ -223,7 +223,7 @@ public class BrowseCreateDAOPostgres implements BrowseCreateDAO
String create = "CREATE TABLE " + map + " (" + String create = "CREATE TABLE " + map + " (" +
"map_id integer primary key, " + "map_id integer primary key, " +
"item_id integer references item(item_id), " + "item_id integer references item(item_id), " +
"distinct_id integer references " + table + "(id)" + "distinct_id integer references " + table + "(distinct_id)" +
");"; ");";
if (execute) if (execute)
@@ -320,6 +320,8 @@ public class BrowseCreateDAOPostgres implements BrowseCreateDAO
{ {
String create = "CREATE TABLE " + table + " (" + String create = "CREATE TABLE " + table + " (" +
"id integer primary key, " + "id integer primary key, " +
"distinct_id integer UNIQUE, " +
"authority VARCHAR(100), " +
"value " + getValueColumnDefinition() + ", " + "value " + getValueColumnDefinition() + ", " +
"sort_value " + getSortColumnDefinition() + "sort_value " + getSortColumnDefinition() +
");"; ");";
@@ -510,7 +512,7 @@ public class BrowseCreateDAOPostgres implements BrowseCreateDAO
/* (non-Javadoc) /* (non-Javadoc)
* @see org.dspace.browse.BrowseCreateDAO#getDistinctID(java.lang.String, java.lang.String, java.lang.String) * @see org.dspace.browse.BrowseCreateDAO#getDistinctID(java.lang.String, java.lang.String, java.lang.String)
*/ */
public int getDistinctID(String table, String value, String sortValue) public int getDistinctID(String table, String value, String authority, String sortValue)
throws BrowseException throws BrowseException
{ {
TableRowIterator tri = null; TableRowIterator tri = null;
@@ -522,27 +524,50 @@ public class BrowseCreateDAOPostgres implements BrowseCreateDAO
try try
{ {
Object[] params = { value }; Object[] params;
String select = null; String select;
if (authority != null)
{
params = new Object[]{ value, authority };
}
else
{
params = new Object[]{ value };
}
if (ConfigurationManager.getBooleanProperty("webui.browse.metadata.case-insensitive", false)) if (ConfigurationManager.getBooleanProperty("webui.browse.metadata.case-insensitive", false))
{ {
select = "SELECT id FROM " + table + " WHERE UPPER(value) = UPPER(?)"; if (authority != null)
{
select = "SELECT distinct_id FROM " + table + " WHERE UPPER(value) = UPPER(?) and authority = ?";
}
else
{
select = "SELECT distinct_id FROM " + table + " WHERE UPPER(value) = UPPER(?) and authority IS NULL";
}
} }
else else
{ {
select = "SELECT id FROM " + table + " WHERE value = ?"; select = "SELECT id FROM " + table + " WHERE value = ?";
if (authority != null)
{
select = "SELECT distinct_id FROM " + table + " WHERE value = ? and authority = ?";
}
else
{
select = "SELECT distinct_id FROM " + table + " WHERE value = ? and authority IS NULL";
}
} }
tri = DatabaseManager.query(context, select, params); tri = DatabaseManager.query(context, select, params);
int distinctID = -1; int distinctID = -1;
if (!tri.hasNext()) if (!tri.hasNext())
{ {
distinctID = insertDistinctRecord(table, value, sortValue); distinctID = insertDistinctRecord(table, value, authority, sortValue);
} }
else else
{ {
distinctID = tri.next().getIntColumn("id"); distinctID = tri.next().getIntColumn("distinct_id");
} }
if (log.isDebugEnabled()) if (log.isDebugEnabled())
@@ -640,17 +665,22 @@ public class BrowseCreateDAOPostgres implements BrowseCreateDAO
/* (non-Javadoc) /* (non-Javadoc)
* @see org.dspace.browse.BrowseCreateDAO#insertDistinctRecord(java.lang.String, java.lang.String, java.lang.String) * @see org.dspace.browse.BrowseCreateDAO#insertDistinctRecord(java.lang.String, java.lang.String, java.lang.String)
*/ */
public int insertDistinctRecord(String table, String value, String sortValue) public int insertDistinctRecord(String table, String value, String authority, String sortValue)
throws BrowseException throws BrowseException
{ {
log.debug("insertDistinctRecord: table=" + table + ",value=" + value+ ",sortValue=" + sortValue); log.debug("insertDistinctRecord: table=" + table + ",value=" + value+ ",authority=" + authority+",sortValue=" + sortValue);
try try
{ {
TableRow dr = DatabaseManager.create(context, table); TableRow dr = DatabaseManager.create(context, table);
if (authority != null)
{
dr.setColumn("authority", utils.truncateValue(authority,100));
}
dr.setColumn("value", utils.truncateValue(value)); dr.setColumn("value", utils.truncateValue(value));
dr.setColumn("sort_value", utils.truncateSortValue(sortValue)); dr.setColumn("sort_value", utils.truncateSortValue(sortValue));
DatabaseManager.update(context, dr);
int distinctID = dr.getIntColumn("id"); int distinctID = dr.getIntColumn("id");
dr.setColumn("distinct_id", distinctID);
DatabaseManager.update(context, dr);
log.debug("insertDistinctRecord: return=" + distinctID); log.debug("insertDistinctRecord: return=" + distinctID);
return distinctID; return distinctID;

View File

@@ -412,4 +412,8 @@ public interface BrowseDAO
* @return the name of the table * @return the name of the table
*/ */
public String getContainerTable(); public String getContainerTable();
public void setAuthorityValue(String value);
public String getAuthorityValue();
} }

View File

@@ -97,6 +97,8 @@ public class BrowseDAOOracle implements BrowseDAO
/** value to restrict browse to (e.g. author name) */ /** value to restrict browse to (e.g. author name) */
private String value = null; private String value = null;
private String authority = null;
/** exact or partial matching of the value */ /** exact or partial matching of the value */
private boolean valuePartial = false; private boolean valuePartial = false;
@@ -427,8 +429,9 @@ public class BrowseDAOOracle implements BrowseDAO
while (tri.hasNext()) while (tri.hasNext())
{ {
TableRow row = tri.next(); TableRow row = tri.next();
String stringResult = row.getStringColumn("value"); String valueResult = row.getStringColumn("value");
results.add(stringResult); String authorityResult = row.getStringColumn("authority");
results.add(new String[]{valueResult,authorityResult});
} }
return results; return results;
@@ -906,35 +909,44 @@ public class BrowseDAOOracle implements BrowseDAO
{ {
if (tableMap != null && tableDis != null) if (tableMap != null && tableDis != null)
{ {
queryBuf.append(tableMap).append(".distinct_id=").append(tableDis).append(".id"); queryBuf.append(tableMap).append(".distinct_id=").append(tableDis).append(".distinct_id");
queryBuf.append(" AND "); queryBuf.append(" AND ");
queryBuf.append(tableDis).append(".sort_value"); if (authority == null)
if (valuePartial)
{ {
queryBuf.append(" LIKE ? "); queryBuf.append(tableDis).append(".authority IS NULL");
queryBuf.append(" AND ");
if (valueField.startsWith("sort_")) queryBuf.append(tableDis).append(".").append(valueField);
if (valuePartial)
{ {
params.add("%" + utils.truncateSortValue(value) + "%"); queryBuf.append(" LIKE ? ");
if (valueField.startsWith("sort_"))
{
params.add("%" + utils.truncateSortValue(value) + "%");
}
else
{
params.add("%" + utils.truncateValue(value) + "%");
}
} }
else else
{ {
params.add("%" + utils.truncateValue(value) + "%"); queryBuf.append("=? ");
if (valueField.startsWith("sort_"))
{
params.add(utils.truncateSortValue(value));
}
else
{
params.add(utils.truncateValue(value));
}
} }
} }
else else
{ {
queryBuf.append("=? "); queryBuf.append(tableDis).append(".authority=?");
params.add(utils.truncateValue(authority,100));
if (valueField.startsWith("sort_"))
{
params.add(utils.truncateSortValue(value));
}
else
{
params.add(utils.truncateValue(value));
}
} }
} }
@@ -1075,7 +1087,7 @@ public class BrowseDAOOracle implements BrowseDAO
queryBuf.append(table); queryBuf.append(table);
if (containerTable != null || (value != null && valueField != null && tableDis != null && tableMap != null)) if (containerTable != null || (value != null && valueField != null && tableDis != null && tableMap != null))
{ {
queryBuf.append(", (SELECT "); queryBuf.append(", (SELECT " + (containerTable != null ? "" : "DISTINCT "));
queryBuf.append(containerTable != null ? containerTable : tableMap).append(".item_id"); queryBuf.append(containerTable != null ? containerTable : tableMap).append(".item_id");
queryBuf.append(" FROM "); queryBuf.append(" FROM ");
buildFocusedSelectTables(queryBuf); buildFocusedSelectTables(queryBuf);
@@ -1379,4 +1391,12 @@ public class BrowseDAOOracle implements BrowseDAO
return queryParams.toArray(); return queryParams.toArray();
} }
public void setAuthorityValue(String value) {
authority = value;
}
public String getAuthorityValue() {
return authority;
}
} }

View File

@@ -97,6 +97,8 @@ public class BrowseDAOPostgres implements BrowseDAO
/** value to restrict browse to (e.g. author name) */ /** value to restrict browse to (e.g. author name) */
private String value = null; private String value = null;
private String authority = null;
/** exact or partial matching of the value */ /** exact or partial matching of the value */
private boolean valuePartial = false; private boolean valuePartial = false;
@@ -431,8 +433,9 @@ public class BrowseDAOPostgres implements BrowseDAO
while (tri.hasNext()) while (tri.hasNext())
{ {
TableRow row = tri.next(); TableRow row = tri.next();
String stringResult = row.getStringColumn("value"); String valueResult = row.getStringColumn("value");
results.add(stringResult); String authorityResult = row.getStringColumn("authority");
results.add(new String[]{valueResult,authorityResult});
} }
return results; return results;
@@ -909,9 +912,13 @@ public class BrowseDAOPostgres implements BrowseDAO
{ {
if (tableMap != null && tableDis != null) if (tableMap != null && tableDis != null)
{ {
queryBuf.append(tableMap).append(".distinct_id=").append(tableDis).append(".id"); queryBuf.append(tableMap).append(".distinct_id=").append(tableDis).append(".distinct_id");
queryBuf.append(" AND "); queryBuf.append(" AND ");
queryBuf.append(tableDis).append(".sort_value"); if (authority == null)
{
queryBuf.append(tableDis).append(".authority IS NULL");
queryBuf.append(" AND ");
queryBuf.append(tableDis).append(".").append(valueField);
if (valuePartial) if (valuePartial)
{ {
@@ -940,6 +947,12 @@ public class BrowseDAOPostgres implements BrowseDAO
} }
} }
} }
else
{
queryBuf.append(tableDis).append(".authority=?");
params.add(utils.truncateValue(authority,100));
}
}
if (containerTable != null && containerIDField != null && containerID != -1) if (containerTable != null && containerIDField != null && containerID != -1)
{ {
@@ -1084,7 +1097,7 @@ public class BrowseDAOPostgres implements BrowseDAO
queryBuf.append(table); queryBuf.append(table);
if (containerTable != null || (value != null && valueField != null && tableDis != null && tableMap != null)) if (containerTable != null || (value != null && valueField != null && tableDis != null && tableMap != null))
{ {
queryBuf.append(", (SELECT "); queryBuf.append(", (SELECT " + (containerTable != null ? "" : "DISTINCT "));
queryBuf.append(containerTable != null ? containerTable : tableMap).append(".item_id"); queryBuf.append(containerTable != null ? containerTable : tableMap).append(".item_id");
queryBuf.append(" FROM "); queryBuf.append(" FROM ");
buildFocusedSelectTables(queryBuf); buildFocusedSelectTables(queryBuf);
@@ -1383,4 +1396,12 @@ public class BrowseDAOPostgres implements BrowseDAO
return queryParams.toArray(); return queryParams.toArray();
} }
public void setAuthorityValue(String value) {
authority = value;
}
public String getAuthorityValue() {
return authority;
}
} }

View File

@@ -252,9 +252,19 @@ public class BrowseEngine
value = OrderFormat.makeSortString(value, scope.getFilterValueLang(), value = OrderFormat.makeSortString(value, scope.getFilterValueLang(),
scope.getBrowseIndex().getDataType()); scope.getBrowseIndex().getDataType());
dao.setAuthorityValue(scope.getAuthorityValue());
// set the values in the Browse Query // set the values in the Browse Query
dao.setFilterValueField("sort_value"); if (scope.isSecondLevel())
dao.setFilterValue(value); {
dao.setFilterValueField("value");
dao.setFilterValue(rawValue);
}
else
{
dao.setFilterValueField("sort_value");
dao.setFilterValue(value);
}
dao.setFilterValuePartial(scope.getFilterValuePartial()); dao.setFilterValuePartial(scope.getFilterValuePartial());
// to apply the filtering, we need the distinct and map tables for the index // to apply the filtering, we need the distinct and map tables for the index
@@ -381,6 +391,9 @@ public class BrowseEngine
// set the browse value if there is one // set the browse value if there is one
browseInfo.setValue(rawValue); browseInfo.setValue(rawValue);
// set the browse authority key if there is one
browseInfo.setAuthority(scope.getAuthorityValue());
// set the focus value if there is one // set the focus value if there is one
browseInfo.setFocus(rawFocusValue); browseInfo.setFocus(rawFocusValue);

View File

@@ -602,7 +602,17 @@ public class BrowseIndex
*/ */
public boolean isMetadataIndex() public boolean isMetadataIndex()
{ {
return "metadata".equals(displayType); return displayType != null && displayType.startsWith("metadata");
}
/**
* Is the browse index authority value?
*
* @return true if authority, false if not
*/
public boolean isAuthorityIndex()
{
return "metadataAuthority".equals(displayType);
} }
/** /**

View File

@@ -101,6 +101,9 @@ public class BrowseInfo
/** the value browsed upon */ /** the value browsed upon */
private String value; private String value;
/** the authority key browsed upon */
private String authority;
/** is this a "starts_with" browse? */ /** is this a "starts_with" browse? */
private boolean startsWith = false; private boolean startsWith = false;
@@ -232,6 +235,20 @@ public class BrowseInfo
return false; return false;
} }
/**
* Is there an authority key associated with this browse
*
* @return true if an authority key, false if not
*/
public boolean hasAuthority()
{
if (this.authority != null)
{
return true;
}
return false;
}
/** /**
* Are there results for this browse, or was the result set empty? * Are there results for this browse, or was the result set empty?
* *
@@ -434,6 +451,22 @@ public class BrowseInfo
this.value = value; this.value = value;
} }
/**
* @return Returns the authority key.
*/
public String getAuthority()
{
return authority;
}
/**
* @param value The authority key to set.
*/
public void setAuthority(String authority)
{
this.authority = authority;
}
/** /**
* is this a top level (0) browse? Examples of this are a full item * is this a top level (0) browse? Examples of this are a full item
* browse or a single browse. Other browse types are considered * browse or a single browse. Other browse types are considered
@@ -466,8 +499,9 @@ public class BrowseInfo
} }
/** /**
* The results of the Browse. Each member of the list is either a String * The results of the Browse. Each member of the list is either a String array
* (for the authors browse) or an {@link org.dspace.content.Item}(for the * (for the authors browse: first element the value, second element the authority key)
* or an {@link org.dspace.content.Item}(for the
* other browses). * other browses).
* *
* @return Result list. This list cannot be modified. * @return Result list. This list cannot be modified.
@@ -478,13 +512,14 @@ public class BrowseInfo
} }
/** /**
* Return the results of the Browse as a String array. * Return the results of the Browse as an array of String array.
* The first element (i.e. index 0) is the value, the second is the authority key
* *
* @return The results of the Browse as a String array. * @return The results of the Browse as a String array.
*/ */
public String[] getStringResults() public String[][] getStringResults()
{ {
return (String[]) results.toArray(new String[results.size()]); return (String[][]) results.toArray(new String[results.size()][2]);
} }
/** /**

View File

@@ -50,7 +50,8 @@ public class BrowseItemDAOOracle implements BrowseItemDAO
private String findAll = "SELECT item_id, in_archive, withdrawn FROM item WHERE in_archive = 1 OR withdrawn = 1"; private String findAll = "SELECT item_id, in_archive, withdrawn FROM item WHERE in_archive = 1 OR withdrawn = 1";
/** query to get the text value of a metadata element only (qualifier is NULL) */ /** query to get the text value of a metadata element only (qualifier is NULL) */
private String getByMetadataElement = "SELECT text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " + private String getByMetadataElement = "SELECT authority, confidence, text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " +
"WHERE metadatavalue.item_id = ? " + "WHERE metadatavalue.item_id = ? " +
" AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " + " AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " +
" AND metadatafieldregistry.element = ? " + " AND metadatafieldregistry.element = ? " +
@@ -60,7 +61,7 @@ public class BrowseItemDAOOracle implements BrowseItemDAO
" ORDER BY metadatavalue.metadata_field_id, metadatavalue.place"; " ORDER BY metadatavalue.metadata_field_id, metadatavalue.place";
/** query to get the text value of a metadata element and qualifier */ /** query to get the text value of a metadata element and qualifier */
private String getByMetadata = "SELECT text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " + private String getByMetadata = "SELECT authority, confidence, text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " +
"WHERE metadatavalue.item_id = ? " + "WHERE metadatavalue.item_id = ? " +
" AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " + " AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " +
" AND metadatafieldregistry.element = ? " + " AND metadatafieldregistry.element = ? " +
@@ -70,7 +71,7 @@ public class BrowseItemDAOOracle implements BrowseItemDAO
" ORDER BY metadatavalue.metadata_field_id, metadatavalue.place"; " ORDER BY metadatavalue.metadata_field_id, metadatavalue.place";
/** query to get the text value of a metadata element with the wildcard qualifier (*) */ /** query to get the text value of a metadata element with the wildcard qualifier (*) */
private String getByMetadataAnyQualifier = "SELECT text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " + private String getByMetadataAnyQualifier = "SELECT authority, confidence, text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " +
"WHERE metadatavalue.item_id = ? " + "WHERE metadatavalue.item_id = ? " +
" AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " + " AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " +
" AND metadatafieldregistry.element = ? " + " AND metadatafieldregistry.element = ? " +
@@ -151,6 +152,8 @@ public class BrowseItemDAOOracle implements BrowseItemDAO
dcv.qualifier = tr.getStringColumn("qualifier"); dcv.qualifier = tr.getStringColumn("qualifier");
dcv.language = tr.getStringColumn("text_lang"); dcv.language = tr.getStringColumn("text_lang");
dcv.value = tr.getStringColumn("text_value"); dcv.value = tr.getStringColumn("text_value");
dcv.authority = tr.getStringColumn("authority");
dcv.confidence = tr.getIntColumn("confidence");
values.add(dcv); values.add(dcv);
} }
} }

View File

@@ -50,7 +50,7 @@ public class BrowseItemDAOPostgres implements BrowseItemDAO
private String findAll = "SELECT item_id, in_archive, withdrawn FROM item WHERE in_archive = true OR withdrawn = true"; private String findAll = "SELECT item_id, in_archive, withdrawn FROM item WHERE in_archive = true OR withdrawn = true";
/** query to get the text value of a metadata element only (qualifier is NULL) */ /** query to get the text value of a metadata element only (qualifier is NULL) */
private String getByMetadataElement = "SELECT text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " + private String getByMetadataElement = "SELECT authority, confidence, text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " +
"WHERE metadatavalue.item_id = ? " + "WHERE metadatavalue.item_id = ? " +
" AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " + " AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " +
" AND metadatafieldregistry.element = ? " + " AND metadatafieldregistry.element = ? " +
@@ -60,7 +60,7 @@ public class BrowseItemDAOPostgres implements BrowseItemDAO
" ORDER BY metadatavalue.metadata_field_id, metadatavalue.place"; " ORDER BY metadatavalue.metadata_field_id, metadatavalue.place";
/** query to get the text value of a metadata element and qualifier */ /** query to get the text value of a metadata element and qualifier */
private String getByMetadata = "SELECT text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " + private String getByMetadata = "SELECT authority, confidence, text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " +
"WHERE metadatavalue.item_id = ? " + "WHERE metadatavalue.item_id = ? " +
" AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " + " AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " +
" AND metadatafieldregistry.element = ? " + " AND metadatafieldregistry.element = ? " +
@@ -70,7 +70,7 @@ public class BrowseItemDAOPostgres implements BrowseItemDAO
" ORDER BY metadatavalue.metadata_field_id, metadatavalue.place"; " ORDER BY metadatavalue.metadata_field_id, metadatavalue.place";
/** query to get the text value of a metadata element with the wildcard qualifier (*) */ /** query to get the text value of a metadata element with the wildcard qualifier (*) */
private String getByMetadataAnyQualifier = "SELECT text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " + private String getByMetadataAnyQualifier = "SELECT authority, confidence, text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " +
"WHERE metadatavalue.item_id = ? " + "WHERE metadatavalue.item_id = ? " +
" AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " + " AND metadatavalue.metadata_field_id = metadatafieldregistry.metadata_field_id " +
" AND metadatafieldregistry.element = ? " + " AND metadatafieldregistry.element = ? " +
@@ -151,6 +151,8 @@ public class BrowseItemDAOPostgres implements BrowseItemDAO
dcv.qualifier = tr.getStringColumn("qualifier"); dcv.qualifier = tr.getStringColumn("qualifier");
dcv.language = tr.getStringColumn("text_lang"); dcv.language = tr.getStringColumn("text_lang");
dcv.value = tr.getStringColumn("text_value"); dcv.value = tr.getStringColumn("text_value");
dcv.authority = tr.getStringColumn("authority");
dcv.confidence = tr.getIntColumn("confidence");
values.add(dcv); values.add(dcv);
} }
} }

View File

@@ -108,6 +108,8 @@ public class BrowserScope
/** the number of items to offset into the result ie. 0 = 1st record */ /** the number of items to offset into the result ie. 0 = 1st record */
private int offset = 0; private int offset = 0;
private String authority = null;
/** /**
* Construct a new BrowserScope using the given Context * Construct a new BrowserScope using the given Context
* *
@@ -643,4 +645,12 @@ public class BrowserScope
} }
return false; return false;
} }
public String getAuthorityValue() {
return authority;
}
public void setAuthorityValue(String value) {
authority = value;
}
} }

View File

@@ -54,6 +54,8 @@ import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.sort.SortOption; import org.dspace.sort.SortOption;
import org.dspace.sort.SortException; import org.dspace.sort.SortException;
@@ -437,14 +439,54 @@ public class IndexBrowse
} }
else else
{ {
if (bis[i].isAuthorityIndex() &&
(values[x].authority == null || values[x].confidence < MetadataAuthorityManager
.getManager().getMinConfidence(values[x].schema, values[x].element, values[x].qualifier)))
{
// if we have an authority index only authored metadata will go here!
break;
}
// is there any valid (with appropriate confidence) authority key?
if (values[x].authority != null
&& values[x].confidence >= MetadataAuthorityManager
.getManager().getMinConfidence(values[x].schema, values[x].element, values[x].qualifier))
{
boolean isValueVariants = false;
List<String> variants = ChoiceAuthorityManager.getManager()
.getVariants(values[x].schema, values[x].element, values[x].qualifier,
values[x].authority, values[x].language);
if (variants != null)
{
for (String var : variants)
{
String nVal = OrderFormat.makeSortString(var, values[x].language, bis[i].getDataType());
distIDSet.add(dao.getDistinctID(bis[i].getDistinctTableName(), var, values[x].authority, nVal));
if (var.equals(values[x].value))
{
isValueVariants = true;
}
}
}
if (!isValueVariants)
{
// get the normalised version of the value
String nVal = OrderFormat.makeSortString(values[x].value, values[x].language, bis[i].getDataType());
distIDSet.add(dao.getDistinctID(bis[i].getDistinctTableName(), values[x].value, values[x].authority, nVal));
}
}
else // put it in the browse index as if it hasn't have an authority key
{
// get the normalised version of the value // get the normalised version of the value
String nVal = OrderFormat.makeSortString(values[x].value, values[x].language, bis[i].getDataType()); String nVal = OrderFormat.makeSortString(values[x].value, values[x].language, bis[i].getDataType());
distIDSet.add(dao.getDistinctID(bis[i].getDistinctTableName(), values[x].value, nVal)); distIDSet.add(dao.getDistinctID(bis[i].getDistinctTableName(), values[x].value, null, nVal));
} }
} }
} }
} }
} }
}
// Do we have any mappings? // Do we have any mappings?
if (distIDSet.isEmpty()) if (distIDSet.isEmpty())

View File

@@ -37,6 +37,8 @@
*/ */
package org.dspace.content; package org.dspace.content;
import org.dspace.content.authority.Choices;
/** /**
* Simple data structure-like class representing a Dublin Core value. It has an * Simple data structure-like class representing a Dublin Core value. It has an
* element, qualifier, value and language. * element, qualifier, value and language.
@@ -62,4 +64,10 @@ public class DCValue
/** The schema name of the metadata element */ /** The schema name of the metadata element */
public String schema; public String schema;
/** Authority control key */
public String authority = null;
/** Authority control confidence */
public int confidence = Choices.CF_UNSET;
} }

View File

@@ -57,9 +57,13 @@ import org.dspace.authorize.AuthorizeManager;
import org.dspace.authorize.ResourcePolicy; import org.dspace.authorize.ResourcePolicy;
import org.dspace.browse.BrowseException; import org.dspace.browse.BrowseException;
import org.dspace.browse.IndexBrowse; import org.dspace.browse.IndexBrowse;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.LogManager; import org.dspace.core.LogManager;
import org.dspace.content.authority.Choices;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.event.Event; import org.dspace.event.Event;
import org.dspace.eperson.EPerson; import org.dspace.eperson.EPerson;
import org.dspace.eperson.Group; import org.dspace.eperson.Group;
@@ -171,6 +175,8 @@ public class Item extends DSpaceObject
dcv.language = resultRow.getStringColumn("text_lang"); dcv.language = resultRow.getStringColumn("text_lang");
//dcv.namespace = schema.getNamespace(); //dcv.namespace = schema.getNamespace();
dcv.schema = schema.getName(); dcv.schema = schema.getName();
dcv.authority = resultRow.getStringColumn("authority");
dcv.confidence = resultRow.getIntColumn("confidence");
// Add it to the list // Add it to the list
dublinCore.add(dcv); dublinCore.add(dcv);
@@ -329,14 +335,14 @@ public class Item extends DSpaceObject
public String getHandle() public String getHandle()
{ {
if(handle == null) { if(handle == null) {
try { try {
handle = HandleManager.findHandle(this.ourContext, this); handle = HandleManager.findHandle(this.ourContext, this);
} catch (SQLException e) { } catch (SQLException e) {
// TODO Auto-generated catch block // TODO Auto-generated catch block
//e.printStackTrace(); //e.printStackTrace();
} }
} }
return handle; return handle;
} }
/** /**
@@ -421,6 +427,12 @@ public class Item extends DSpaceObject
return myCollection; return myCollection;
} }
// just get the collection ID for internal use
private int getOwningCollectionID()
{
return itemRow.getIntColumn("owning_collection");
}
/** /**
* Get Dublin Core metadata for the item. * Get Dublin Core metadata for the item.
* Passing in a <code>null</code> value for <code>qualifier</code> * Passing in a <code>null</code> value for <code>qualifier</code>
@@ -531,7 +543,8 @@ public class Item extends DSpaceObject
copy.value = dcv.value; copy.value = dcv.value;
copy.language = dcv.language; copy.language = dcv.language;
copy.schema = dcv.schema; copy.schema = dcv.schema;
copy.authority = dcv.authority;
copy.confidence = dcv.confidence;
values.add(copy); values.add(copy);
} }
} }
@@ -634,6 +647,10 @@ public class Item extends DSpaceObject
* Add metadata fields. These are appended to existing values. * Add metadata fields. These are appended to existing values.
* Use <code>clearDC</code> to remove values. The ordering of values * Use <code>clearDC</code> to remove values. The ordering of values
* passed in is maintained. * passed in is maintained.
* <p>
* If metadata authority control is available, try to get authority
* values. The authority confidence depends on whether authority is
* <em>required</em> or not.
* @param schema * @param schema
* the schema for the metadata field. <em>Must</em> match * the schema for the metadata field. <em>Must</em> match
* the <code>name</code> of an existing metadata schema. * the <code>name</code> of an existing metadata schema.
@@ -652,6 +669,56 @@ public class Item extends DSpaceObject
public void addMetadata(String schema, String element, String qualifier, String lang, public void addMetadata(String schema, String element, String qualifier, String lang,
String[] values) String[] values)
{ {
MetadataAuthorityManager mam = MetadataAuthorityManager.getManager();
String fieldKey = MetadataAuthorityManager.makeFieldKey(schema, element, qualifier);
if (mam.isAuthorityControlled(fieldKey))
{
String authorities[] = new String[values.length];
int confidences[] = new int[values.length];
for (int i = 0; i < values.length; ++i)
{
Choices c = ChoiceAuthorityManager.getManager().getBestMatch(fieldKey, values[i], getOwningCollectionID(), null);
authorities[i] = c.values.length > 0 ? c.values[0].authority : null;
confidences[i] = c.confidence;
}
addMetadata(schema, element, qualifier, lang, values, authorities, confidences);
}
else
addMetadata(schema, element, qualifier, lang, values, null, null);
}
/**
* Add metadata fields. These are appended to existing values.
* Use <code>clearDC</code> to remove values. The ordering of values
* passed in is maintained.
* @param schema
* the schema for the metadata field. <em>Must</em> match
* the <code>name</code> of an existing metadata schema.
* @param element
* the metadata element name
* @param qualifier
* the metadata qualifer name, or <code>null</code> for
* unqualified
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. <code>null</code> means the
* value has no language (for example, a date).
* @param values
* the values to add.
* @param authority
* the external authority key for this value (or null)
* @param confidence
* the authority confidence (default 0)
*/
public void addMetadata(String schema, String element, String qualifier, String lang,
String[] values, String authorities[], int confidences[])
{
MetadataAuthorityManager mam = MetadataAuthorityManager.getManager();
ChoiceAuthorityManager cam = ChoiceAuthorityManager.getManager();
boolean authorityControlled = mam.isAuthorityControlled(schema, element, qualifier);
boolean authorityRequired = mam.isAuthorityRequired(schema, element, qualifier);
String fieldName = schema+"."+element+((qualifier==null)? "": "."+qualifier);
// We will not verify that they are valid entries in the registry // We will not verify that they are valid entries in the registry
// until update() is called. // until update() is called.
for (int i = 0; i < values.length; i++) for (int i = 0; i < values.length; i++)
@@ -661,6 +728,30 @@ public class Item extends DSpaceObject
dcv.element = element; dcv.element = element;
dcv.qualifier = qualifier; dcv.qualifier = qualifier;
dcv.language = lang; dcv.language = lang;
// Logic to set Authority and Confidence:
// - normalize an empty string for authority to NULL.
// - if authority key is present, use given confidence or NOVALUE if not given
// - otherwise, preserve confidence if meaningful value was given since it may document a failed authority lookup
// - CF_UNSET signifies no authority nor meaningful confidence.
// - it's possible to have empty authority & CF_ACCEPTED if e.g. user deletes authority key
if (authorityControlled)
{
if (authorities != null && authorities[i] != null && authorities[i].length() > 0)
{
dcv.authority = authorities[i];
dcv.confidence = confidences == null ? Choices.CF_NOVALUE : confidences[i];
}
else
{
dcv.authority = null;
dcv.confidence = confidences == null ? Choices.CF_UNSET : confidences[i];
}
// authority sanity check: if authority is required, was it supplied?
// XXX FIXME? can't throw a "real" exception here without changing all the callers to expect it, so use a runtime exception
if (authorityRequired && (dcv.authority == null || dcv.authority.length() == 0))
throw new IllegalArgumentException("The metadata field \""+fieldName+"\" requires an authority key but none was provided. Vaue=\""+dcv.value+"\"");
}
if (values[i] != null) if (values[i] != null)
{ {
// remove control unicode char // remove control unicode char
@@ -683,8 +774,7 @@ public class Item extends DSpaceObject
dcv.value = null; dcv.value = null;
} }
dublinCore.add(dcv); dublinCore.add(dcv);
addDetails(schema+"."+element+((qualifier==null)? "": "."+qualifier)); addDetails(fieldName);
} }
if (values.length > 0) if (values.length > 0)
@@ -721,6 +811,42 @@ public class Item extends DSpaceObject
addMetadata(schema, element, qualifier, lang, valArray); addMetadata(schema, element, qualifier, lang, valArray);
} }
/**
* Add a single metadata field. This is appended to existing
* values. Use <code>clearDC</code> to remove values.
*
* @param schema
* the schema for the metadata field. <em>Must</em> match
* the <code>name</code> of an existing metadata schema.
* @param element
* the metadata element name
* @param qualifier
* the metadata qualifer, or <code>null</code> for
* unqualified
* @param lang
* the ISO639 language code, optionally followed by an underscore
* and the ISO3166 country code. <code>null</code> means the
* value has no language (for example, a date).
* @param value
* the value to add.
* @param authority
* the external authority key for this value (or null)
* @param confidence
* the authority confidence (default 0)
*/
public void addMetadata(String schema, String element, String qualifier,
String lang, String value, String authority, int confidence)
{
String[] valArray = new String[1];
String[] authArray = new String[1];
int[] confArray = new int[1];
valArray[0] = value;
authArray[0] = authority;
confArray[0] = confidence;
addMetadata(schema, element, qualifier, lang, valArray, authArray, confArray);
}
/** /**
* Clear Dublin Core metadata values. As with <code>getDC</code> above, * Clear Dublin Core metadata values. As with <code>getDC</code> above,
* passing in <code>null</code> only matches fields where the qualifier or * passing in <code>null</code> only matches fields where the qualifier or
@@ -1023,14 +1149,14 @@ public class Item extends DSpaceObject
*/ */
public Bundle[] getBundles() throws SQLException public Bundle[] getBundles() throws SQLException
{ {
if (bundles == null) if (bundles == null)
{ {
bundles = new ArrayList<Bundle>(); bundles = new ArrayList<Bundle>();
// Get bundles // Get bundles
TableRowIterator tri = DatabaseManager.queryTable(ourContext, "bundle", TableRowIterator tri = DatabaseManager.queryTable(ourContext, "bundle",
"SELECT bundle.* FROM bundle, item2bundle WHERE " + "SELECT bundle.* FROM bundle, item2bundle WHERE " +
"item2bundle.bundle_id=bundle.bundle_id AND " + "item2bundle.bundle_id=bundle.bundle_id AND " +
"item2bundle.item_id= ? ", "item2bundle.item_id= ? ",
itemRow.getIntColumn("item_id")); itemRow.getIntColumn("item_id"));
try try
@@ -1059,7 +1185,7 @@ public class Item extends DSpaceObject
if (tri != null) if (tri != null)
tri.close(); tri.close();
} }
} }
Bundle[] bundleArray = new Bundle[bundles.size()]; Bundle[] bundleArray = new Bundle[bundles.size()];
bundleArray = (Bundle[]) bundles.toArray(bundleArray); bundleArray = (Bundle[]) bundles.toArray(bundleArray);
@@ -1608,6 +1734,17 @@ public class Item extends DSpaceObject
matched = false; matched = false;
} }
// check that authority and confidence match
if (matched)
{
String auth = tr.getStringColumn("authority");
int conf = tr.getIntColumn("confidence");
if (!((dcv.authority == null && auth == null) ||
(dcv.authority != null && auth != null && dcv.authority.equals(auth))
&& dcv.confidence == conf))
matched = false;
}
// If the db record is identical to the in memory values // If the db record is identical to the in memory values
if (matched) if (matched)
{ {
@@ -1649,6 +1786,8 @@ public class Item extends DSpaceObject
metadata.setValue(dcv.value); metadata.setValue(dcv.value);
metadata.setLanguage(dcv.language); metadata.setLanguage(dcv.language);
metadata.setPlace(placeNum[dcIdx]); metadata.setPlace(placeNum[dcIdx]);
metadata.setAuthority(dcv.authority);
metadata.setConfidence(dcv.confidence);
metadata.create(ourContext); metadata.create(ourContext);
} }
} }
@@ -1836,10 +1975,10 @@ public class Item extends DSpaceObject
** non-archived items may still be tracked in some browse tables ** non-archived items may still be tracked in some browse tables
** for administrative purposes, and these need to be removed. ** for administrative purposes, and these need to be removed.
**/ **/
// FIXME: there is an exception handling problem here // FIXME: there is an exception handling problem here
try try
{ {
// Remove from indicies // Remove from indicies
IndexBrowse ib = new IndexBrowse(ourContext); IndexBrowse ib = new IndexBrowse(ourContext);
ib.itemRemoved(this); ib.itemRemoved(this);
} }
@@ -1887,21 +2026,21 @@ public class Item extends DSpaceObject
ourContext.removeCached(this, getID()); ourContext.removeCached(this, getID());
if (submitter != null) if (submitter != null)
{ {
ourContext.removeCached(submitter, submitter.getID()); ourContext.removeCached(submitter, submitter.getID());
} }
// Remove bundles & bitstreams from cache if they have been loaded // Remove bundles & bitstreams from cache if they have been loaded
if (bundles != null) if (bundles != null)
{ {
Bundle[] bunds = getBundles(); Bundle[] bunds = getBundles();
for (int i = 0; i < bunds.length; i++) for (int i = 0; i < bunds.length; i++)
{ {
ourContext.removeCached(bunds[i], bunds[i].getID()); ourContext.removeCached(bunds[i], bunds[i].getID());
Bitstream[] bitstreams = bunds[i].getBitstreams(); Bitstream[] bitstreams = bunds[i].getBitstreams();
for (int j = 0; j < bitstreams.length; j++) for (int j = 0; j < bitstreams.length; j++)
{ {
ourContext.removeCached(bitstreams[j], bitstreams[j].getID()); ourContext.removeCached(bitstreams[j], bitstreams[j].getID());
} }
} }
} }
} }
@@ -2131,12 +2270,12 @@ public class Item extends DSpaceObject
// If we are moving from the owning collection, update that too // If we are moving from the owning collection, update that too
if (isOwningCollection(from)) if (isOwningCollection(from))
{ {
setOwningCollection(to); setOwningCollection(to);
ourContext.turnOffAuthorisationSystem(); ourContext.turnOffAuthorisationSystem();
update(); update();
ourContext.restoreAuthSystemState(); ourContext.restoreAuthSystemState();
} }
else else
{ {
// Although we haven't actually updated anything within the item // Although we haven't actually updated anything within the item
@@ -2187,37 +2326,37 @@ public class Item extends DSpaceObject
*/ */
public Collection[] getCollectionsNotLinked() throws SQLException public Collection[] getCollectionsNotLinked() throws SQLException
{ {
Collection[] allCollections = Collection.findAll(ourContext); Collection[] allCollections = Collection.findAll(ourContext);
Collection[] linkedCollections = getCollections(); Collection[] linkedCollections = getCollections();
Collection[] notLinkedCollections = new Collection[allCollections.length - linkedCollections.length]; Collection[] notLinkedCollections = new Collection[allCollections.length - linkedCollections.length];
if ((allCollections.length - linkedCollections.length) == 0) if ((allCollections.length - linkedCollections.length) == 0)
{
return notLinkedCollections;
}
int i = 0;
for (Collection collection : allCollections)
{ {
boolean alreadyLinked = false; return notLinkedCollections;
for (Collection linkedCommunity : linkedCollections)
{
if (collection.getID() == linkedCommunity.getID())
{
alreadyLinked = true;
break;
}
}
if (!alreadyLinked)
{
notLinkedCollections[i++] = collection;
}
} }
return notLinkedCollections; int i = 0;
for (Collection collection : allCollections)
{
boolean alreadyLinked = false;
for (Collection linkedCommunity : linkedCollections)
{
if (collection.getID() == linkedCommunity.getID())
{
alreadyLinked = true;
break;
}
}
if (!alreadyLinked)
{
notLinkedCollections[i++] = collection;
}
}
return notLinkedCollections;
} }
/** /**
@@ -2270,7 +2409,7 @@ public class Item extends DSpaceObject
* *
*/ */
public static ItemIterator findByMetadataField(Context context, public static ItemIterator findByMetadataField(Context context,
String schema, String element, String qualifier, String value) String schema, String element, String qualifier, String value)
throws SQLException, AuthorizeException, IOException throws SQLException, AuthorizeException, IOException
{ {
MetadataSchema mds = MetadataSchema.find(context, schema); MetadataSchema mds = MetadataSchema.find(context, schema);
@@ -2286,12 +2425,12 @@ public class Item extends DSpaceObject
TableRowIterator rows = null; TableRowIterator rows = null;
if (Item.ANY.equals(value)) if (Item.ANY.equals(value))
{ {
rows = DatabaseManager.queryTable(context, "item", query, mdf.getFieldID()); rows = DatabaseManager.queryTable(context, "item", query, mdf.getFieldID());
} }
else else
{ {
query += " AND metadatavalue.text_value = ?"; query += " AND metadatavalue.text_value = ?";
rows = DatabaseManager.queryTable(context, "item", query, mdf.getFieldID(), value); rows = DatabaseManager.queryTable(context, "item", query, mdf.getFieldID(), value);
} }
return new ItemIterator(context, rows); return new ItemIterator(context, rows);
} }
@@ -2431,4 +2570,34 @@ public class Item extends DSpaceObject
return null; return null;
} }
} }
/**
* Find all the items in the archive with a given authority key value
* in the indicated metadata field.
*
* @param context DSpace context object
* @param schema metdata field schema
* @param element metdata field element
* @param qualifier metdata field qualifier
* @param value the value of authority key to look for
* @return an iterator over the items matching that authority value
* @throws SQLException, AuthorizeException, IOException
*/
public static ItemIterator findByAuthorityValue(Context context,
String schema, String element, String qualifier, String value)
throws SQLException, AuthorizeException, IOException
{
MetadataSchema mds = MetadataSchema.find(context, schema);
if (mds == null)
throw new IllegalArgumentException("No such metadata schema: "+schema);
MetadataField mdf = MetadataField.findByElement(context, mds.getSchemaID(), element, qualifier);
if (mdf == null)
throw new IllegalArgumentException("No such metadata field: schema="+schema+", element="+element+", qualifier="+qualifier);
TableRowIterator rows = DatabaseManager.queryTable(context, "item",
"SELECT item.* FROM metadatavalue,item WHERE item.in_archive='1' "+
"AND item.item_id = metadatavalue.item_id AND metadata_field_id = ? AND authority = ?",
mdf.getFieldID(), value);
return new ItemIterator(context, rows);
}
} }

View File

@@ -79,6 +79,12 @@ public class MetadataValue
/** The position of the record. */ /** The position of the record. */
public int place = 1; public int place = 1;
/** Authority key, if any */
public String authority = null;
/** Authority confidence value -- see Choices class for values */
public int confidence = 0;
/** log4j logger */ /** log4j logger */
private static Logger log = Logger.getLogger(MetadataValue.class); private static Logger log = Logger.getLogger(MetadataValue.class);
@@ -100,6 +106,8 @@ public class MetadataValue
value = row.getStringColumn("text_value"); value = row.getStringColumn("text_value");
language = row.getStringColumn("text_lang"); language = row.getStringColumn("text_lang");
place = row.getIntColumn("place"); place = row.getIntColumn("place");
authority = row.getStringColumn("authority");
confidence = row.getIntColumn("confidence");
this.row = row; this.row = row;
} }
} }
@@ -231,6 +239,46 @@ public class MetadataValue
this.value = value; this.value = value;
} }
/**
* Get the metadata authority
*
* @return metadata authority
*/
public String getAuthority ()
{
return authority ;
}
/**
* Set the metadata authority
*
* @param value new metadata authority
*/
public void setAuthority (String value)
{
this.authority = value;
}
/**
* Get the metadata confidence
*
* @return metadata confidence
*/
public int getConfidence()
{
return confidence;
}
/**
* Set the metadata confidence
*
* @param value new metadata confidence
*/
public void setConfidence(int value)
{
this.confidence = value;
}
/** /**
* Creates a new metadata value. * Creates a new metadata value.
* *
@@ -248,6 +296,8 @@ public class MetadataValue
row.setColumn("text_value", value); row.setColumn("text_value", value);
row.setColumn("text_lang", language); row.setColumn("text_lang", language);
row.setColumn("place", place); row.setColumn("place", place);
row.setColumn("authority", authority);
row.setColumn("confidence", confidence);
DatabaseManager.insert(context, row); DatabaseManager.insert(context, row);
// Remember the new row number // Remember the new row number
@@ -352,6 +402,8 @@ public class MetadataValue
row.setColumn("text_value", value); row.setColumn("text_value", value);
row.setColumn("text_lang", language); row.setColumn("text_lang", language);
row.setColumn("place", place); row.setColumn("place", place);
row.setColumn("authority", authority);
row.setColumn("confidence", confidence);
DatabaseManager.update(context, row); DatabaseManager.update(context, row);
log.info(LogManager.getHeader(context, "update_metadatavalue", log.info(LogManager.getHeader(context, "update_metadatavalue",

View File

@@ -0,0 +1,16 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package org.dspace.content.authority;
import java.util.List;
/**
*
* @author bollini
*/
public interface AuthorityVariantsSupport {
public List<String> getVariants(String key, String locale);
}

View File

@@ -0,0 +1,68 @@
/*
* Choice.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.content.authority;
/**
* Record class to hold the data describing one option, or choice, for an
* authority-controlled metadata value.
*
* @author Larry Stone
* @see Choices
*/
public class Choice
{
/** Authority key for this value */
public String authority = null;
/** Label to display for this value (e.g. to present in UI menu) */
public String label = null;
/** The canonical text value to insert into MetadataValue's text field */
public String value = null;
public Choice()
{
}
public Choice(String authority, String value, String label)
{
this.authority = authority;
this.value = value;
this.label = label;
}
}

View File

@@ -0,0 +1,101 @@
/*
* ChoiceAuthority.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.content.authority;
/**
* Plugin interface that supplies an authority control mechanism for
* one metadata field.
*
* @author Larry Stone
* @see ChoiceAuthorityManager, MetadataAuthorityManager
*/
public interface ChoiceAuthority
{
/**
* Get all values from the authority that match the proferred value.
* Note that the offering was entered by the user and may contain
* mixed/incorrect case, whitespace, etc so the plugin should be careful
* to clean up user data before making comparisons.
*
* Value of a "Name" field will be in canonical DSpace person name format,
* which is "Lastname, Firstname(s)", e.g. "Smith, John Q.".
*
* Some authorities with a small set of values may simply return the whole
* set for any sample value, although it's a good idea to set the
* defaultSelected index in the Choices instance to the choice, if any,
* that matches the value.
*
* @param text user's value to match
* @param collection database ID of Collection for context (owner of Item)
* @param start choice at which to start, 0 is first.
* @param limit maximum number of choices to return, 0 for no limit.
* @param locale explicit localization key if available, or null
* @return a Choices object (never null).
*/
public Choices getMatches(String text, int collection, int start, int limit, String locale);
/**
* Get the single "best" match (if any) of a value in the authority
* to the given user value. The "confidence" element of Choices is
* expected to be set to a meaningful value about the circumstances of
* this match.
*
* This call is typically used in non-interactive metadata ingest
* where there is no interactive agent to choose from among options.
*
* @param text user's value to match
* @param collection database ID of Collection for context (owner of Item)
* @param locale explicit localization key if available, or null
* @return a Choices object (never null) with 1 or 0 values.
*/
public Choices getBestMatch(String text, int collection, String locale);
/**
* Get the canonical user-visible "label" (i.e. short descriptive text)
* for a key in the authority. Can be localized given the implicit
* or explicit locale specification.
*
* This may get called many times while populating a Web page so it should
* be implemented as efficiently as possible.
*
* @param key authority key known to this authority.
* @param locale explicit localization key if available, or null
* @return descriptive label - should always return something, never null.
*/
public String getLabel(String key, String locale);
}

View File

@@ -0,0 +1,326 @@
/*
* ChoiceAuthorityManager.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.content.authority;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Enumeration;
import org.apache.log4j.Logger;
import org.dspace.content.MetadataField;
import org.dspace.content.Collection;
import org.dspace.content.ItemIterator;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.PluginManager;
/**
* Broker for ChoiceAuthority plugins, and for other information configured
* about the choice aspect of authority control for a metadata field.
*
* Configuration keys, per metadata field (e.g. "dc.contributer.author")
*
* # names the ChoiceAuthority plugin called for this field
* choices.plugin.<FIELD> = name-of-plugin
*
* # mode of UI presentation desired in submission UI:
* # "select" is dropdown menu, "lookup" is popup with selector, "suggest" is autocomplete/suggest
* choices.presentation.<FIELD> = "select" | "suggest"
*
* # is value "closed" to the set of these choices or are non-authority values permitted?
* choices.closed.<FIELD> = true | false
*
* @author Larry Stone
* @see ChoiceAuthority
*/
public class ChoiceAuthorityManager
{
private static Logger log = Logger.getLogger(ChoiceAuthorityManager.class);
private static ChoiceAuthorityManager cached = null;
// map of field key to authority plugin
private Map<String,ChoiceAuthority> controller = new HashMap<String,ChoiceAuthority>();
// map of field key to presentation type
private Map<String,String> presentation = new HashMap<String,String>();
// map of field key to closed value
private Map<String,Boolean> closed = new HashMap<String,Boolean>();
private ChoiceAuthorityManager()
{
Enumeration pn = ConfigurationManager.propertyNames();
final String choicesPrefix = "choices.";
final String choicesPlugin = "choices.plugin.";
final String choicesPresentation = "choices.presentation.";
final String choicesClosed = "choices.closed.";
property:
while (pn.hasMoreElements())
{
String key = (String)pn.nextElement();
if (key.startsWith(choicesPrefix))
{
if (key.startsWith(choicesPlugin))
{
String fkey = config2fkey(key.substring(choicesPlugin.length()));
if (fkey == null)
{
log.warn("Skipping invalid ChoiceAuthority configuration property: "+key+": does not have schema.element.qualifier");
continue property;
}
// XXX FIXME maybe add sanity check, call
// MetadataField.findByElement to maek sure it's a real field.
ChoiceAuthority ma = (ChoiceAuthority)
PluginManager.getNamedPlugin(ChoiceAuthority.class, ConfigurationManager.getProperty(key));
if (ma == null)
{
log.warn("Skipping invalid configuration for "+key+" because named plugin not found: "+ConfigurationManager.getProperty(key));
continue property;
}
controller.put(fkey, ma);
log.debug("Choice Control: For field="+fkey+", Plugin="+ma);
}
else if (key.startsWith(choicesPresentation))
{
String fkey = config2fkey(key.substring(choicesPresentation.length()));
if (fkey == null)
{
log.warn("Skipping invalid ChoiceAuthority configuration property: "+key+": does not have schema.element.qualifier");
continue property;
}
presentation.put(fkey, ConfigurationManager.getProperty(key));
}
else if (key.startsWith(choicesClosed))
{
String fkey = config2fkey(key.substring(choicesClosed.length()));
if (fkey == null)
{
log.warn("Skipping invalid ChoiceAuthority configuration property: "+key+": does not have schema.element.qualifier");
continue property;
}
closed.put(fkey, new Boolean(ConfigurationManager.getBooleanProperty(key)));
}
else
log.error("Illegal configuration property: "+key);
}
}
}
/** Factory method */
public static ChoiceAuthorityManager getManager()
{
if (cached == null)
{
cached = new ChoiceAuthorityManager();
}
return cached;
}
// translate tail of configuration key (supposed to be schema.element.qual)
// into field key
private String config2fkey(String field)
{
// field is expected to be "schema.element.qualifier"
int dot = field.indexOf(".");
if (dot < 0)
return null;
String schema = field.substring(0, dot);
String element = field.substring(dot+1);
String qualifier = null;
dot = element.indexOf(".");
if (dot >= 0)
{
qualifier = element.substring(dot+1);
element = element.substring(0, dot);
}
return makeFieldKey(schema, element, qualifier);
}
/**
* Wrapper that calls getMatches method of the plugin corresponding to
* the metadata field defined by schema,element,qualifier.
*
* @see ChoiceAuthority.getMatches
* @param schema schema of metadata field
* @param element element of metadata field
* @param qualifier qualifier of metadata field
* @param text user's value to match
* @param collection database ID of Collection for context (owner of Item)
* @param start choice at which to start, 0 is first.
* @param limit maximum number of choices to return, 0 for no limit.
* @param locale explicit localization key if available, or null
* @return a Choices object (never null).
*/
public Choices getMatches(String schema, String element, String qualifier,
String query, int collection, int start, int limit, String locale)
{
return getMatches(makeFieldKey(schema, element, qualifier), query, collection, start, limit, locale);
}
/**
* Wrapper calls getMatches method of the plugin corresponding to
* the metadata field defined by single field key.
*
* @see ChoiceAuthority.getMatches
* @param fieldKey single string identifying metadata field
* @param text user's value to match
* @param collection database ID of Collection for context (owner of Item)
* @param start choice at which to start, 0 is first.
* @param limit maximum number of choices to return, 0 for no limit.
* @param locale explicit localization key if available, or null
* @return a Choices object (never null).
*/
public Choices getMatches(String fieldKey, String query, int collection, int start, int limit, String locale)
{
ChoiceAuthority ma = controller.get(fieldKey);
if (ma == null)
throw new IllegalArgumentException("No choices plugin was configured for field \""+fieldKey+"\".");
return ma.getMatches(query, collection, start, limit, locale);
}
/**
* Wrapper that calls getBestMatch method of the plugin corresponding to
* the metadata field defined by single field key.
*
* @see ChoiceAuthority.getBestMatch
* @param fieldKey single string identifying metadata field
* @param text user's value to match
* @param collection database ID of Collection for context (owner of Item)
* @param locale explicit localization key if available, or null
* @return a Choices object (never null) with 1 or 0 values.
*/
public Choices getBestMatch(String fieldKey, String query, int collection, String locale)
{
ChoiceAuthority ma = controller.get(fieldKey);
if (ma == null)
throw new IllegalArgumentException("No choices plugin was configured for field \""+fieldKey+"\".");
return ma.getBestMatch(query, collection, locale);
}
/**
* Wrapper that calls getLabel method of the plugin corresponding to
* the metadata field defined by schema,element,qualifier.
*/
public String getLabel(String schema, String element, String qualifier,
String authKey, String locale)
{
return getLabel(makeFieldKey(schema, element, qualifier), authKey, locale);
}
/**
* Wrapper that calls getLabel method of the plugin corresponding to
* the metadata field defined by single field key.
*/
public String getLabel(String fieldKey, String authKey, String locale)
{
ChoiceAuthority ma = controller.get(fieldKey);
if (ma == null)
throw new IllegalArgumentException("No choices plugin was configured for field \""+fieldKey+"\".");
return ma.getLabel(authKey, locale);
}
/**
* Predicate, is there a Choices configuration of any kind for the
* given metadata field?
* @return true if choices are configured for this field.
*/
public boolean isChoicesConfigured(String fieldKey)
{
return controller.containsKey(fieldKey);
}
/**
* Get the presentation keyword (should be "lookup", "select" or "suggest", but this
* is an informal convention so it can be easily extended) for this field.
*
* @return configured presentation type for this field, or null if none found
*/
public String getPresentation(String fieldKey)
{
return presentation.get(fieldKey);
}
/**
* Get the configured "closed" value for this field.
*
* @return true if choices are closed for this field.
*/
public boolean isClosed(String fieldKey)
{
return closed.containsKey(fieldKey) ? closed.get(fieldKey).booleanValue() : false;
}
/**
* Construct a single key from the tuple of schema/element/qualifier
* that describes a metadata field. Punt to the function we use for
* submission UI input forms, for now.
*/
public static String makeFieldKey(String schema, String element, String qualifier)
{
return MetadataField.formKey(schema, element, qualifier);
}
/**
* Construct a single key from the "dot" notation e.g. "dc.rights"
*/
public static String makeFieldKey(String dotty)
{
return dotty.replace(".", "_");
}
/**
* Wrapper to call plugin's getVariants().
*/
public List<String> getVariants(String schema, String element, String qualifier,
String authorityKey, String language)
{
ChoiceAuthority ma = controller.get(makeFieldKey(schema, element, qualifier));
if (ma instanceof AuthorityVariantsSupport)
{
AuthorityVariantsSupport avs = (AuthorityVariantsSupport) ma;
return avs.getVariants(authorityKey, language);
}
return null;
}
}

View File

@@ -0,0 +1,216 @@
/*
* Choices.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.content.authority;
/**
* Record class to hold a set of Choices returned by an authority in response
* to a search.
*
* @author Larry Stone
* @see Choice
*/
public class Choices
{
/** -------------- Class fields ----------------- **/
/** Canonical values of the confidence metric. Higher is better. */
/** This authority value has been confirmed as accurate by an
interactive user or authoritative policy */
public static final int CF_ACCEPTED = 600;
/** Value is singular and valid but has not been seen and accepted
by a human, so its provenance is uncertain. */
public static final int CF_UNCERTAIN = 500;
/** There are multiple matching authority values of equal validity. */
public static final int CF_AMBIGUOUS = 400;
/** There are no matching answers from the authority. */
public static final int CF_NOTFOUND = 300;
/** The authority encountered an internal failure - this preserves a
record in the metadata of why there is no value. */
public static final int CF_FAILED = 200;
/** The authority recommends this submission be rejected. */
public static final int CF_REJECTED = 100;
/** No reasonable confidence value is available */
public static final int CF_NOVALUE = 0;
/** Value has not been set (DB default). */
public static final int CF_UNSET = -1;
/** descriptive labels for confidence values */
private static final int confidenceValue[] = {
CF_UNSET,
CF_NOVALUE,
CF_REJECTED,
CF_FAILED,
CF_NOTFOUND,
CF_AMBIGUOUS,
CF_UNCERTAIN,
CF_ACCEPTED,
};
private static final String confidenceText[] = {
"UNSET",
"NOVALUE",
"REJECTED",
"FAILED",
"NOTFOUND",
"AMBIGUOUS",
"UNCERTAIN",
"ACCEPTED"
};
/** -------------- Instance fields ----------------- **/
/** The set of values returned by the authority */
public Choice values[] = null;
/** The confidence level that applies to all values in this result set */
public int confidence = CF_NOVALUE;
/** Index of start of this result wrt. all results; 0 is start of
complete result. Note that length is implicit in values.length. */
public int start = 0;
/** Count of total results available */
public int total = 0;
/** Index of value to be selected by default, if any. -1 means none selected. */
public int defaultSelected = -1;
/** true when there are more values to be sent after this result. */
public boolean more = false;
/** -------------- Methods ----------------- **/
/**
* Constructor for general purpose
*/
public Choices(Choice values[], int start, int total, int confidence, boolean more)
{
super();
this.values = values;
this.start = start;
this.total = total;
this.confidence = confidence;
this.more = more;
}
/**
* Constructor for general purpose
*/
public Choices(Choice values[], int start, int total, int confidence, boolean more, int defaultSelected)
{
super();
this.values = values;
this.start = start;
this.total = total;
this.confidence = confidence;
this.more = more;
this.defaultSelected = defaultSelected;
}
/**
* Constructor for error results
*/
public Choices(int confidence)
{
this.values = new Choice[0];
this.confidence = confidence;
}
/**
* Constructor for simple empty or error results
*/
public Choices(boolean isError)
{
this.values = new Choice[0];
this.confidence = isError ? CF_FAILED : CF_NOVALUE;
}
/**
* Predicate, did this result encounter an error?
* @return true if this Choices result encountered an error
*/
public boolean isError()
{
return confidence == CF_FAILED || confidence == CF_REJECTED;
}
/**
* Get the symbolic name corresponding to a confidence value, or CF_NOVALUE's
* name if the value is unknown.
*
* @param cv confidence value
* @return String with symbolic name corresponding to value (never null)
*/
public static String getConfidenceText(int cv)
{
String novalue = null;
for (int i = 0; i < confidenceValue.length; ++i)
{
if (confidenceValue[i] == cv)
return confidenceText[i];
else if (confidenceValue[i] == CF_NOVALUE)
novalue = confidenceText[i];
}
return novalue;
}
/**
* Get the value corresponding to a symbolic name of a confidence
* value, or CF_NOVALUE if the symbol is unknown.
*
* @param ct symbolic name in String
* @return corresponding value or CF_NOVALUE if not found
*/
public static int getConfidenceValue(String ct)
{
for (int i = 0; i < confidenceText.length; ++i)
{
if (confidenceText[i].equalsIgnoreCase(ct))
return confidenceValue[i];
}
return CF_NOVALUE;
}
}

View File

@@ -0,0 +1,143 @@
/*
* ChoicesXMLGenerator.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.content.authority;
import org.dspace.content.authority.Choices;
import org.dspace.content.authority.Choice;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
/**
* Record class to hold a set of Choices returned by an authority in response
* to a search.
*
* @author Larry Stone
* @see Choice
*/
public class ChoicesXMLGenerator
{
// use the XHTML NS, even though this is a fragment.
private static final String NS_URI = "http://www.w3.org/1999/xhtml";
private static final String NS_NAME = "";
public static void generate(Choices result, String format, ContentHandler contentHandler)
throws SAXException
{
Attributes noAtts = new AttributesImpl();
AttributesImpl resultAtts = new AttributesImpl();
if (result.more)
resultAtts.addAttribute("", "more", "more", "boolean", "true");
if (result.isError())
resultAtts.addAttribute("", "error", "error", "boolean", "true");
resultAtts.addAttribute("", "start", "start", "int", String.valueOf(result.start));
resultAtts.addAttribute("", "total", "total", "int", String.valueOf(result.total));
contentHandler.startDocument();
// "select" HTML format for DSpace popup
if (format != null && format.equalsIgnoreCase("select"))
{
contentHandler.startElement(NS_URI, NS_NAME, "select", resultAtts);
for (int i = 0; i < result.values.length; ++i)
{
Choice mdav = result.values[i];
AttributesImpl va = new AttributesImpl();
va.addAttribute("", "authority", "authority", "string", mdav.authority == null ? "":mdav.authority);
va.addAttribute("", "value", "value", "string", mdav.value);
if (result.defaultSelected == i)
va.addAttribute("", "selected", "selected", "boolean", "");
contentHandler.startElement(NS_URI, NS_NAME, "option", va);
contentHandler.characters(mdav.label.toCharArray(), 0, mdav.label.length());
contentHandler.endElement(NS_URI, NS_NAME, "option");
}
contentHandler.endElement(NS_URI, NS_NAME, "select");
}
// "ul" HTML format (required by Scriptactulous autocomplete)
else if (format != null && format.equalsIgnoreCase("ul"))
{
AttributesImpl classLabel = new AttributesImpl();
classLabel.addAttribute("", "class", "class", "string", "label");
AttributesImpl classValue = new AttributesImpl();
classValue.addAttribute("", "class", "class", "string", "value");
contentHandler.startElement(NS_URI, NS_NAME, "ul", resultAtts);
for (int i = 0; i < result.values.length; ++i)
{
Choice mdav = result.values[i];
AttributesImpl va = new AttributesImpl();
va.addAttribute("", "authority", "authority", "string", mdav.authority == null ? "":mdav.authority);
if (result.defaultSelected == i)
va.addAttribute("", "selected", "selected", "boolean", "");
contentHandler.startElement(NS_URI, NS_NAME, "li", va);
contentHandler.startElement(NS_URI, NS_NAME, "span", classLabel);
contentHandler.characters(mdav.label.toCharArray(), 0, mdav.label.length());
contentHandler.endElement(NS_URI, NS_NAME, "span");
contentHandler.startElement(NS_URI, NS_NAME, "span", classValue);
contentHandler.characters(mdav.value.toCharArray(), 0, mdav.value.length());
contentHandler.endElement(NS_URI, NS_NAME, "span");
contentHandler.endElement(NS_URI, NS_NAME, "li");
}
contentHandler.endElement(NS_URI, NS_NAME, "ul");
}
// default is XML format, Choices/Choice
else
{
contentHandler.startElement(NS_URI, NS_NAME, "Choices", resultAtts);
for (int i = 0; i < result.values.length; ++i)
{
Choice mdav = result.values[i];
AttributesImpl va = new AttributesImpl();
va.addAttribute("", "authority", "authority", "string", mdav.authority == null ? "":mdav.authority);
va.addAttribute("", "value", "value", "string", mdav.value);
if (result.defaultSelected == i)
va.addAttribute("", "selected", "selected", "boolean", "");
contentHandler.startElement(NS_URI, NS_NAME, "Choice", va);
contentHandler.characters(mdav.label.toCharArray(), 0, mdav.label.length());
contentHandler.endElement(NS_URI, NS_NAME, "Choice");
}
contentHandler.endElement(NS_URI, NS_NAME, "Choices");
}
contentHandler.endDocument();
}
}

View File

@@ -0,0 +1,167 @@
/*
* DCInputAuthority.java
*
* Version: $Revision: 1.1 $
*
* Date: $Date: 2009/07/23 05:07:01 $
*
* 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.content.authority;
import java.util.Iterator;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.dspace.app.util.DCInputsReader;
import org.dspace.app.util.DCInputsReaderException;
import org.dspace.core.SelfNamedPlugin;
/**
* ChoiceAuthority source that reads the same input-forms which drive
* configurable submission.
*
* Configuration:
* This MUST be configured aas a self-named plugin, e.g.:
* plugin.selfnamed.org.dspace.content.authority.ChoiceAuthority = \
* org.dspace.content.authority.DCInputAuthority
*
* It AUTOMATICALLY configures a plugin instance for each <value-pairs>
* element (within <form-value-pairs>) of the input-forms.xml. The name
* of the instance is the "value-pairs-name" attribute, e.g.
* the element: <value-pairs value-pairs-name="common_types" dc-term="type">
* defines a plugin instance "common_types".
*
* IMPORTANT NOTE: Since these value-pairs do NOT include authority keys,
* the choice lists derived from them do not include authority values.
* So you should not use them as the choice source for authority-controlled
* fields.
*/
public class DCInputAuthority extends SelfNamedPlugin implements ChoiceAuthority
{
private static Logger log = Logger.getLogger(DCInputAuthority.class);
private String values[] = null;
private String labels[] = null;
private static DCInputsReader dci = null;
private static String pluginNames[] = null;
public DCInputAuthority()
{
super();
}
public static String[] getPluginNames()
{
if (pluginNames == null)
{
try
{
if (dci == null)
dci = new DCInputsReader();
}
catch (DCInputsReaderException e)
{
log.error("Failed reading DCInputs initialization: ",e);
}
List<String> names = new ArrayList<String>();
Iterator pi = dci.getPairsNameIterator();
while (pi.hasNext())
names.add((String)pi.next());
pluginNames = names.toArray(new String[names.size()]);
log.debug("Got plugin names = "+Arrays.deepToString(pluginNames));
}
return pluginNames;
}
// once-only load of values and labels
private void init()
{
if (values == null)
{
String pname = this.getPluginInstanceName();
List<String> pairs = (List<String>)dci.getPairs(pname);
if (pairs != null)
{
values = new String[pairs.size()/2];
labels = new String[pairs.size()/2];
for (int i = 0; i < pairs.size(); i += 2)
{
labels[i/2] = pairs.get(i);
values[i/2] = pairs.get(i+1);
}
log.debug("Found pairs for name="+pname);
}
else
log.error("Failed to find any pairs for name="+pname, new IllegalStateException());
}
}
public Choices getMatches(String query, int collection, int start, int limit, String locale)
{
init();
int dflt = -1;
Choice v[] = new Choice[values.length];
for (int i = 0; i < values.length; ++i)
{
v[i] = new Choice(values[i], values[i], labels[i]);
if (values[i].equalsIgnoreCase(query))
dflt = i;
}
return new Choices(v, 0, v.length, Choices.CF_AMBIGUOUS, false, dflt);
}
public Choices getBestMatch(String text, int collection, String locale)
{
init();
for (int i = 0; i < values.length; ++i)
{
if (text.equalsIgnoreCase(values[i]))
{
Choice v[] = new Choice[1];
v[0] = new Choice(String.valueOf(i), values[i], labels[i]);
return new Choices(v, 0, v.length, Choices.CF_UNCERTAIN, false, 0);
}
}
return new Choices(Choices.CF_NOTFOUND);
}
public String getLabel(String key, String locale)
{
init();
return labels[Integer.parseInt(key)];
}
}

View File

@@ -0,0 +1,374 @@
/*
* LCNameAuthority.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.content.authority;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.FileReader;
import java.io.BufferedReader;
import java.util.Enumeration;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;
import org.apache.log4j.Logger;
import org.dspace.core.ConfigurationManager;
import org.dspace.content.DCPersonName;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.util.EncodingUtil;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.HttpException;
/**
* Sample personal name authority based on Library of Congress Name Authority
* Also serves as an example of an SRU client as authority.
*
* This is tuned for the data in the LC Name Authority test instance, see
* http://alcme.oclc.org/srw/search/lcnaf
*
* WARNING: This is just a proof-of-concept implementation. It would need
* WARNING: lots of refinement to be used in production, because it is very
* WARNING: sloppy about digging through the MARC/XML results. No doubt
* WARNING: it is losing a lot of valid results and information.
* WARNING: Could also do a better job including more info (title, life dates
* WARNING: etc) in the label instead of just the name.
*
* Reads these DSpace Config properties:
*
* lcname.url = http://alcme.oclc.org/srw/search/lcnaf
*
* TODO: make # of results to ask for (and return) configurable.
*
* @author Larry Stone
* @version $Revision $
*/
public class LCNameAuthority implements ChoiceAuthority
{
private static Logger log = Logger.getLogger(LCNameAuthority.class);
// get these from configuration
private static String url = null;
// NS URI for SRU respones
private static final String NS_SRU = "http://www.loc.gov/zing/srw/";
// NS URI for MARC/XML
private static final String NS_MX = "http://www.loc.gov/MARC21/slim";
// constructor does static init too..
public LCNameAuthority()
{
if (url == null)
{
url = ConfigurationManager.getProperty("lcname.url");
// sanity check
if (url == null)
throw new IllegalStateException("Missing DSpace configuration keys for LCName Query");
}
}
// punt! this is a poor implementation..
public Choices getBestMatch(String text, int collection, String locale)
{
return getMatches(text, collection, 0, 2, locale);
}
/**
* Match a proposed value against name authority records
* Value is assumed to be in "Lastname, Firstname" format.
*/
public Choices getMatches(String text, int collection, int start, int limit, String locale)
{
boolean error = false;
Choices result = queryPerson(text, start, limit);
if (result == null)
result = new Choices(true);
return result;
}
// punt; supposed to get the canonical display form of a metadata authority key
// XXX FIXME implement this with a query on the authority key, cache results
public String getLabel(String key, String locale)
{
return key;
}
/**
* Guts of the implementation, returns a complete Choices result, or
* null for a failure.
*/
private Choices queryPerson(String text, int start, int limit)
{
// punt if there is no query text
if (text == null || text.trim().length() == 0)
return new Choices(true);
// 1. build CQL query
DCPersonName pn = new DCPersonName(text);
StringBuilder query = new StringBuilder();
query.append("local.FirstName = \"").append(pn.getFirstNames()).
append("\" and local.FamilyName = \"").append(pn.getLastName()).
append("\"");
// XXX arbitrary default limit - should be configurable?
if (limit == 0)
limit = 50;
NameValuePair args[] = new NameValuePair[6];
args[0] = new NameValuePair("operation", "searchRetrieve");
args[1] = new NameValuePair("version", "1.1");
args[2] = new NameValuePair("recordSchema", "info:srw/schema/1/marcxml-v1.1");
args[3] = new NameValuePair("query", query.toString());
args[4] = new NameValuePair("maximumRecords", String.valueOf(limit));
args[5] = new NameValuePair("startRecord", String.valueOf(start+1));
HttpClient hc = new HttpClient();
String srUrl = url + "?" + EncodingUtil.formUrlEncode(args, "UTF8");
GetMethod get = new GetMethod(srUrl);
log.debug("Trying SRU query, URL="+srUrl);
// 2. web request
try
{
int status = hc.executeMethod(get);
if (status == 200)
{
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
SRUHandler handler = new SRUHandler();
// XXX FIXME: should turn off validation here explicitly, but
// it seems to be off by default.
xr.setFeature("http://xml.org/sax/features/namespaces", true);
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
xr.parse(new InputSource(get.getResponseBodyAsStream()));
// this probably just means more results available..
if (handler.hits != handler.result.size())
log.warn("Discrepency in results, result.length="+handler.result.size()+
", yet expected results="+handler.hits);
boolean more = handler.hits > (start + handler.result.size());
// XXX add non-auth option; perhaps the UI should do this?
// XXX it's really a policy matter if they allow unauth result.
// XXX good, stop it.
// handler.result.add(new Choice("", text, "Non-Authority: \""+text+"\""));
int confidence;
if (handler.hits == 0)
confidence = Choices.CF_NOTFOUND;
else if (handler.hits == 1)
confidence = Choices.CF_UNCERTAIN;
else
confidence = Choices.CF_AMBIGUOUS;
return new Choices(handler.result.toArray(new Choice[handler.result.size()]),
start, handler.hits, confidence, more);
}
}
catch (HttpException e)
{
log.error("SRU query failed: ", e);
return new Choices(true);
}
catch (IOException e)
{
log.error("SRU query failed: ", e);
return new Choices(true);
}
catch (ParserConfigurationException e)
{
log.warn("Failed parsing SRU result: ", e);
return new Choices(true);
}
catch (SAXException e)
{
log.warn("Failed parsing SRU result: ", e);
return new Choices(true);
}
finally
{
get.releaseConnection();
}
return new Choices(true);
}
/**
* XXX FIXME TODO: Very sloppy MARC/XML parser.
* This only reads subfields 010.a (for LCCN, to use as key)
* and 100.a (for "established personal name")
* Maybe look at Indicator on 100 too.
* Should probably read other 100 subfields to build a more detailed label.
*/
private static class SRUHandler
extends DefaultHandler
{
private List<Choice> result = new ArrayList<Choice>();
private int hits = -1;
private String textValue = null;
private String name = null;
private String lccn = null;
private String lastTag = null;
private String lastCode = null;
// NOTE: text value MAY be presented in multiple calls, even if
// it all one word, so be ready to splice it together.
// BEWARE: subclass's startElement method should call super()
// to null out 'value'. (Don't you miss the method combination
// options of a real object system like CLOS?)
public void characters(char[] ch, int start, int length)
throws SAXException
{
String newValue = new String(ch, start, length);
if (newValue.length() > 0)
{
if (textValue == null)
textValue = newValue;
else
textValue += newValue;
}
}
public void endElement(String namespaceURI, String localName,
String qName)
throws SAXException
{
if (localName.equals("numberOfRecords") &&
namespaceURI.equals(NS_SRU))
{
hits = Integer.parseInt(textValue.trim());
if (hits > 0)
{
name = null;
lccn = null;
log.debug("Expecting "+hits+" records in results.");
}
}
// after record get next hit ready
else if (localName.equals("record") &&
namespaceURI.equals(NS_SRU))
{
if (name != null && lccn != null)
{
// HACK: many LC name entries end with ',' ...trim it.
if (name.endsWith(","))
name = name.substring(0, name.length()-1);
// XXX DEBUG
// log.debug("Got result, name="+name+", lccn="+lccn);
result.add(new Choice(lccn, name, name));
}
else
log.warn("Got anomalous result, at least one of these null: lccn="+lccn+", name="+name);
name = null;
lccn = null;
}
else if (localName.equals("subfield") &&
namespaceURI.equals(NS_MX))
{
if (lastTag != null && lastCode != null)
{
// 010.a is lccn, "authority code"
if (lastTag.equals("010") && lastCode.equals("a"))
lccn = textValue;
// 100.a is the personal name
else if (lastTag.equals("100") && lastCode.equals("a"))
name = textValue;
}
}
}
// subclass overriding this MUST call it with super()
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts)
throws SAXException
{
textValue = null;
if (localName.equals("datafield") &&
namespaceURI.equals(NS_MX))
{
lastTag = atts.getValue("tag");
if (lastTag == null)
log.warn("MARC datafield without tag attribute!");
}
else if (localName.equals("subfield") &&
namespaceURI.equals(NS_MX))
{
lastCode = atts.getValue("code");
if (lastCode == null)
log.warn("MARC subfield without code attribute!");
}
}
public void error(SAXParseException exception)
throws SAXException
{
throw new SAXException(exception);
}
public void fatalError(SAXParseException exception)
throws SAXException
{
throw new SAXException(exception);
}
}
}

View File

@@ -0,0 +1,205 @@
/*
* MetadataAuthorityManager.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.content.authority;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Enumeration;
import org.apache.log4j.Logger;
import org.dspace.content.MetadataField;
import org.dspace.content.Collection;
import org.dspace.content.ItemIterator;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.PluginManager;
/**
* Broker for metadata authority settings configured for each metadata field.
*
* Configuration keys, per metadata field (e.g. "dc.contributer.author")
*
* # is field authority controlled (i.e. store authority, confidence values)?
* authority.controlled.<FIELD> = true
*
* # is field required to have an authority value, or may it be empty?
* # default is false.
* authority.required.<FIELD> = true | false
*
* NOTE: There is *expected* to be a "choices" (see ChoiceAuthorityManager)
* configuration for each authority-controlled field.
*
* @see ChoiceAuthorityManager
* @author Larry Stone
*/
public class MetadataAuthorityManager
{
private static Logger log = Logger.getLogger(MetadataAuthorityManager.class);
private static MetadataAuthorityManager cached = null;
// map of field key to authority plugin
private Map<String,Boolean> controlled = new HashMap<String,Boolean>();
// map of field key to answer of whether field is required to be controlled
private Map<String,Boolean> isAuthorityRequired = new HashMap<String,Boolean>();
/**
* map of field key to answer of which is the min acceptable confidence
* value for a field with authority
*/
private Map<String, Integer> minConfidence = new HashMap<String, Integer>();
private MetadataAuthorityManager()
{
Enumeration pn = ConfigurationManager.propertyNames();
final String authPrefix = "authority.controlled.";
property:
while (pn.hasMoreElements())
{
String key = (String)pn.nextElement();
if (key.startsWith(authPrefix))
{
// field is expected to be "schema.element.qualifier"
String field = key.substring(authPrefix.length());
int dot = field.indexOf(".");
if (dot < 0)
{
log.warn("Skipping invalid MetadataAuthority configuration property: "+key+": does not have schema.element.qualifier");
continue property;
}
String schema = field.substring(0, dot);
String element = field.substring(dot+1);
String qualifier = null;
dot = element.indexOf(".");
if (dot >= 0)
{
qualifier = element.substring(dot+1);
element = element.substring(0, dot);
}
String fkey = makeFieldKey(schema, element, qualifier);
boolean ctl = ConfigurationManager.getBooleanProperty(key, true);
boolean req = ConfigurationManager.getBooleanProperty("authority.required."+field, false);
controlled.put(fkey, Boolean.valueOf(ctl));
isAuthorityRequired.put(fkey, Boolean.valueOf(req));
if (ConfigurationManager.getProperty("authority.minconfidence."+field) != null)
{
minConfidence.put(fkey, ConfigurationManager.getIntProperty("authority.minconfidence." + field));
}
log.debug("Authority Control: For schema="+schema+", elt="+element+", qual="+qualifier+", controlled="+ctl+", required="+req);
}
}
}
// factory method
public static MetadataAuthorityManager getManager()
{
if (cached == null)
{
cached = new MetadataAuthorityManager();
}
return cached;
}
/** Predicate - is field authority-controlled? */
public boolean isAuthorityControlled(String schema, String element, String qualifier)
{
return isAuthorityControlled(makeFieldKey(schema, element, qualifier));
}
/** Predicate - is field authority-controlled? */
public boolean isAuthorityControlled(String fieldKey)
{
return controlled.containsKey(fieldKey) && controlled.get(fieldKey).booleanValue();
}
/** Predicate - is authority value required for field? */
public boolean isAuthorityRequired(String schema, String element, String qualifier)
{
return isAuthorityRequired(makeFieldKey(schema, element, qualifier));
}
/** Predicate - is authority value required for field? */
public boolean isAuthorityRequired(String fieldKey)
{
Boolean result = isAuthorityRequired.get(fieldKey);
return (result == null) ? false : result.booleanValue();
}
/**
* Construct a single key from the tuple of schema/element/qualifier
* that describes a metadata field. Punt to the function we use for
* submission UI input forms, for now.
*/
public static String makeFieldKey(String schema, String element, String qualifier)
{
return MetadataField.formKey(schema, element, qualifier);
}
/**
* Give the minimal level of confidence required to consider valid an authority value
* for the given metadata.
* @return the minimal valid level of confidence for the given metadata
*/
public int getMinConfidence(String schema, String element, String qualifier) {
Integer result = minConfidence.get(makeFieldKey(schema, element, qualifier));
return result == null?Choices.CF_ACCEPTED:result.intValue();
}
/**
* Return the list of metadata field with authority control. The strings
* are in the form <code>schema.element[.qualifier]</code>
*
* @return the list of metadata field with authority control
*/
public List<String> getAuthorityMetadata() {
List<String> copy = new ArrayList<String>();
for (String s : controlled.keySet())
{
copy.add(s.replaceAll("_","."));
}
return copy;
}
}

View File

@@ -0,0 +1,115 @@
/*
* SHERPARoMEOJournalTitle.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.content.authority;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.FileReader;
import java.io.BufferedReader;
import java.util.Enumeration;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;
import org.apache.log4j.Logger;
import org.dspace.core.ConfigurationManager;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.util.EncodingUtil;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.HttpException;
/**
* Sample Journal-name authority based on SHERPA/RoMEO
*
* WARNING: This is a very crude and incomplete implementation, done mainly
* as a proof-of-concept. Any site that actually wants to use it will
* probably have to refine it (and give patches back to dspace.org).
*
* @see SHERPARoMEOProtocol
* @author Larry Stone
* @version $Revision $
*/
public class SHERPARoMEOJournalTitle extends SHERPARoMEOProtocol
{
private static final String RESULT = "journal";
private static final String LABEL = "jtitle";
private static final String AUTHORITY = "issn";
public SHERPARoMEOJournalTitle()
{
super();
}
public Choices getMatches(String text, int collection, int start, int limit, String locale)
{
// punt if there is no query text
if (text == null || text.trim().length() == 0)
return new Choices(true);
// query args to add to SHERPA/RoMEO request URL
NameValuePair args[] = new NameValuePair[2];
args[0] = new NameValuePair("jtitle", text);
args[1] = new NameValuePair("qtype","contains"); // OR: starts, exact
Choices result = query(RESULT, LABEL, AUTHORITY, args, start, limit);
if (result == null)
{
result = new Choices(true);
}
return result;
}
}

View File

@@ -0,0 +1,297 @@
/*
* SHERPARoMEOProtocol.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.content.authority;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.FileReader;
import java.io.BufferedReader;
import java.util.Enumeration;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;
import org.apache.log4j.Logger;
import org.dspace.core.ConfigurationManager;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.util.EncodingUtil;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.HttpException;
/**
* Choice Authority based on SHERPA/RoMEO - for Publishers and Journals
* See the subclasses SHERPARoMEOPublisher and SHERPARoMEOJournalTitle
* for actual choice plugin implementations. This is a superclass
* containing all the common prototcol logic.
*
* Reads these DSpace Config properties:
*
* # contact URL for server
* sherpa.romeo.url = http://www.sherpa.ac.uk/romeoapi11.php
*
* WARNING: This is a very crude and incomplete implementation, done mainly
* as a proof-of-concept. Any site that actually wants to use it will
* probably have to refine it (and give patches back to dspace.org).
*
* @see SHERPARoMEOPublisher, SHERPARoMEOJournalTitle
* @author Larry Stone
* @version $Revision $
*/
public abstract class SHERPARoMEOProtocol implements ChoiceAuthority
{
private static Logger log = Logger.getLogger(SHERPARoMEOProtocol.class);
// contact URL from configuration
private static String url = null;
public SHERPARoMEOProtocol()
{
if (url == null)
{
url = ConfigurationManager.getProperty("sherpa.romeo.url");
// sanity check
if (url == null)
throw new IllegalStateException("Missing DSpace configuration keys for SHERPA/RoMEO Query");
}
}
// this implements the specific RoMEO API args and XML tag naming
public abstract Choices getMatches(String text, int collection, int start, int limit, String locale);
public Choices getBestMatch(String text, int collection, String locale)
{
return getMatches(text, collection, 0, 2, locale);
}
// XXX FIXME just punt, returning value, never got around to
// implementing a reverse query.
public String getLabel(String key, String locale)
{
return key;
}
// NOTE - ignore limit and start for now
protected Choices query(String result, String label, String authority,
NameValuePair[] args, int start, int limit)
{
HttpClient hc = new HttpClient();
String srUrl = url + "?" + EncodingUtil.formUrlEncode(args, "UTF8");
GetMethod get = new GetMethod(srUrl);
log.debug("Trying SHERPA/RoMEO Query, URL="+srUrl);
try
{
int status = hc.executeMethod(get);
if (status == 200)
{
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
SRHandler handler = new SRHandler(result, label, authority);
// XXX FIXME: should turn off validation here explicitly, but
// it seems to be off by default.
xr.setFeature("http://xml.org/sax/features/namespaces", true);
xr.setContentHandler(handler);
xr.setErrorHandler(handler);
xr.parse(new InputSource(get.getResponseBodyAsStream()));
int confidence;
if (handler.total == 0)
confidence = Choices.CF_NOTFOUND;
else if (handler.total == 1)
confidence = Choices.CF_UNCERTAIN;
else
confidence = Choices.CF_AMBIGUOUS;
return new Choices(handler.result, start, handler.total, confidence, false);
}
}
catch (HttpException e)
{
log.error("SHERPA/RoMEO query failed: ", e);
return null;
}
catch (IOException e)
{
log.error("SHERPA/RoMEO query failed: ", e);
return null;
}
catch (ParserConfigurationException e)
{
log.warn("Failed parsing SHERPA/RoMEO result: ", e);
return null;
}
catch (SAXException e)
{
log.warn("Failed parsing SHERPA/RoMEO result: ", e);
return null;
}
finally
{
get.releaseConnection();
}
return null;
}
// SAX handler to grab SHERPA/RoMEO (and eventually other details) from result
private static class SRHandler
extends DefaultHandler
{
private Choice result[] = null;
int rindex = 0; // result index
int total = 0;
// name of element containing a result, e.g. <journal>
private String resultElement = null;
// name of element containing the label e.g. <name>
private String labelElement = null;
// name of element containing the authority value e.g. <issn>
private String authorityElement = null;
protected String textValue = null;
public SRHandler(String result, String label, String authority)
{
super();
resultElement = result;
labelElement = label;
authorityElement = authority;
}
// NOTE: text value MAY be presented in multiple calls, even if
// it all one word, so be ready to splice it together.
// BEWARE: subclass's startElement method should call super()
// to null out 'value'. (Don't you miss the method combination
// options of a real object system like CLOS?)
public void characters(char[] ch, int start, int length)
throws SAXException
{
String newValue = new String(ch, start, length);
if (newValue.length() > 0)
{
if (textValue == null)
textValue = newValue;
else
textValue += newValue;
}
}
// if this was the FIRST "numhits" element, it's size of results:
public void endElement(String namespaceURI, String localName,
String qName)
throws SAXException
{
if (localName.equals("numhits"))
{
String stotal = textValue.trim();
if (stotal.length() > 0)
{
total = Integer.parseInt(stotal);
result = new Choice[total];
if (total > 0)
{
result[0] = new Choice();
log.debug("Got "+total+" records in results.");
}
}
}
// after start of result element, get next hit ready
else if (localName.equals(resultElement))
{
if (++rindex < result.length)
result[rindex] = new Choice();
}
// plug in label value
else if (localName.equals(labelElement) && textValue != null)
result[rindex].value =
result[rindex].label = textValue.trim();
// plug in authority value
else if (authorityElement != null &&
localName.equals(authorityElement) && textValue != null)
result[rindex].authority = textValue.trim();
// error message
else if (localName.equals("message") && textValue != null)
log.warn("SHERPA/RoMEO response error message: "+textValue.trim());
}
// subclass overriding this MUST call it with super()
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts)
throws SAXException
{
textValue = null;
}
public void error(SAXParseException exception)
throws SAXException
{
throw new SAXException(exception);
}
public void fatalError(SAXParseException exception)
throws SAXException
{
throw new SAXException(exception);
}
}
}

View File

@@ -0,0 +1,116 @@
/*
* SHERPARoMEOPublisher.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.content.authority;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.FileReader;
import java.io.BufferedReader;
import java.util.Enumeration;
import java.util.List;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;
import org.apache.log4j.Logger;
import org.dspace.core.ConfigurationManager;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.util.EncodingUtil;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.HttpException;
/**
* Sample Publisher name authority based on SHERPA/RoMEO
*
*
* WARNING: This is a very crude and incomplete implementation, done mainly
* as a proof-of-concept. Any site that actually wants to use it will
* probably have to refine it (and give patches back to dspace.org).
*
* @see SHERPARoMEOProtocol
* @author Larry Stone
* @version $Revision $
*/
public class SHERPARoMEOPublisher extends SHERPARoMEOProtocol
{
private static final String RESULT = "publisher";
private static final String LABEL = "name";
// note: the publisher records have nothing we can use as authority code.
private static final String AUTHORITY = null;
public SHERPARoMEOPublisher()
{
super();
}
public Choices getMatches(String text, int collection, int start, int limit, String locale)
{
// punt if there is no query text
if (text == null || text.trim().length() == 0)
return new Choices(true);
// query args to add to SHERPA/RoMEO request URL
NameValuePair args[] = new NameValuePair[2];
args[0] = new NameValuePair("pub", text);
args[1] = new NameValuePair("qtype","all"); // OR: starts, exact
Choices result = query(RESULT, LABEL, AUTHORITY, args, start, limit);
if (result == null)
{
result = new Choices(true);
}
return result;
}
}

View File

@@ -0,0 +1,99 @@
/*
* SampleAuthority.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.content.authority;
import java.util.List;
/**
* This is a *very* stupid test fixture for authority control, and also
* serves as a trivial example of an authority plugin implementation.
*/
public class SampleAuthority implements ChoiceAuthority
{
private static String values[] = {
"sun",
"mon",
"tue",
"wed",
"thu",
"fri",
"sat"
};
private static String labels[] = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
};
public Choices getMatches(String query, int collection, int start, int limit, String locale)
{
int dflt = -1;
Choice v[] = new Choice[values.length];
for (int i = 0; i < values.length; ++i)
{
v[i] = new Choice(String.valueOf(i), values[i], labels[i]);
if (values[i].equalsIgnoreCase(query))
dflt = i;
}
return new Choices(v, 0, v.length, Choices.CF_AMBIGUOUS, false, dflt);
}
public Choices getBestMatch(String text, int collection, String locale)
{
for (int i = 0; i < values.length; ++i)
{
if (text.equalsIgnoreCase(values[i]))
{
Choice v[] = new Choice[1];
v[0] = new Choice(String.valueOf(i), values[i], labels[i]);
return new Choices(v, 0, v.length, Choices.CF_UNCERTAIN, false, 0);
}
}
return new Choices(Choices.CF_NOTFOUND);
}
public String getLabel(String key, String locale)
{
return labels[Integer.parseInt(key)];
}
}

View File

@@ -49,6 +49,7 @@ import org.dspace.authorize.AuthorizeException;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.authority.Choices;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.jdom.Document; import org.jdom.Document;
@@ -252,6 +253,11 @@ public class XSLTDisseminationCrosswalk
field.setAttribute("lang", dc[i].language); field.setAttribute("lang", dc[i].language);
if (dc[i].value != null) if (dc[i].value != null)
field.setText(dc[i].value); field.setText(dc[i].value);
if (dc[i].authority != null)
{
field.setAttribute("authority", dc[i].authority);
field.setAttribute("confidence", Choices.getConfidenceText(dc[i].confidence));
}
dim.addContent(field); dim.addContent(field);
} }
return dim; return dim;

View File

@@ -50,6 +50,8 @@ import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataField; import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema; import org.dspace.content.MetadataSchema;
import org.dspace.content.MetadataValue;
import org.dspace.content.authority.Choices;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.PluginManager; import org.dspace.core.PluginManager;
@@ -116,8 +118,20 @@ public class XSLTIngestionCrosswalk
String element = field.getAttributeValue("element"); String element = field.getAttributeValue("element");
String qualifier = field.getAttributeValue("qualifier"); String qualifier = field.getAttributeValue("qualifier");
String lang = field.getAttributeValue("lang"); String lang = field.getAttributeValue("lang");
String authority = field.getAttributeValue("authority");
String sconf = field.getAttributeValue("confidence");
item.addMetadata(schema, element, qualifier, lang, field.getText()); if ((authority != null && authority.length() > 0) ||
(sconf != null && sconf.length() > 0))
{
int confidence = (sconf != null && sconf.length() > 0) ?
Choices.getConfidenceValue(sconf) : Choices.CF_UNSET;
item.addMetadata(schema, element, qualifier, lang, field.getText(), authority, confidence);
}
else
{
item.addMetadata(schema, element, qualifier, lang, field.getText());
}
} }
/** /**

View File

@@ -55,6 +55,7 @@ import java.util.Vector;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.text.ParseException; import java.text.ParseException;
import java.util.List;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder; import org.apache.commons.cli.OptionBuilder;
@@ -79,6 +80,8 @@ import org.dspace.content.DCValue;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.ItemIterator; import org.dspace.content.ItemIterator;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
@@ -999,11 +1002,61 @@ public class DSIndexer
} }
else else
{ {
// TODO: use a delegate to allow custom 'types' to be used to reformat the field List<String> variants = null;
doc.add( new Field(indexConfigArr[i].indexName, if (mydc[j].authority != null && mydc[j].confidence >= MetadataAuthorityManager.getManager()
mydc[j].value, .getMinConfidence(mydc[j].schema, mydc[j].element, mydc[j].qualifier))
Field.Store.NO, {
Field.Index.TOKENIZED)); variants = ChoiceAuthorityManager.getManager()
.getVariants(mydc[j].schema, mydc[j].element, mydc[j].qualifier,
mydc[j].authority, mydc[j].language);
doc.add( new Field(indexConfigArr[i].indexName+"_authority",
mydc[j].authority,
Field.Store.NO,
Field.Index.UN_TOKENIZED));
boolean valueAlreadyIndexed = false;
if (variants != null)
{
for (String var : variants)
{
// TODO: use a delegate to allow custom 'types' to be used to reformat the field
doc.add( new Field(indexConfigArr[i].indexName,
var,
Field.Store.NO,
Field.Index.TOKENIZED));
if (var.equals(mydc[j].value))
{
valueAlreadyIndexed = true;
}
else
{ // add to default index too...
// (only variants, main value is already take)
doc.add( new Field("default",
var,
Field.Store.NO,
Field.Index.TOKENIZED));
}
}
}
if (!valueAlreadyIndexed)
{
// TODO: use a delegate to allow custom 'types' to be used to reformat the field
doc.add( new Field(indexConfigArr[i].indexName,
mydc[j].value,
Field.Store.NO,
Field.Index.TOKENIZED));
}
}
else
{
// TODO: use a delegate to allow custom 'types' to be used to reformat the field
doc.add( new Field(indexConfigArr[i].indexName,
mydc[j].value,
Field.Store.NO,
Field.Index.TOKENIZED));
}
} }
doc.add( new Field("default", mydc[j].value, Field.Store.NO, Field.Index.TOKENIZED)); doc.add( new Field("default", mydc[j].value, Field.Store.NO, Field.Index.TOKENIZED));

View File

@@ -49,6 +49,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.app.util.DCInputsReader; import org.dspace.app.util.DCInputsReader;
import org.dspace.app.util.DCInputsReaderException;
import org.dspace.app.util.DCInput; import org.dspace.app.util.DCInput;
import org.dspace.app.util.SubmissionInfo; import org.dspace.app.util.SubmissionInfo;
import org.dspace.app.util.Util; import org.dspace.app.util.Util;
@@ -60,6 +61,9 @@ import org.dspace.content.DCSeriesNumber;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataField; import org.dspace.content.MetadataField;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.Choices;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.submit.AbstractProcessingStep; import org.dspace.submit.AbstractProcessingStep;
@@ -87,7 +91,7 @@ public class DescribeStep extends AbstractProcessingStep
private static Logger log = Logger.getLogger(DescribeStep.class); private static Logger log = Logger.getLogger(DescribeStep.class);
/** hash of all submission forms details */ /** hash of all submission forms details */
private static DCInputsReader inputsReader; private static DCInputsReader inputsReader = null;
/*************************************************************************** /***************************************************************************
* STATUS / ERROR FLAGS (returned by doProcessing() if an error occurs or * STATUS / ERROR FLAGS (returned by doProcessing() if an error occurs or
@@ -151,10 +155,18 @@ public class DescribeStep extends AbstractProcessingStep
// lookup applicable inputs // lookup applicable inputs
Collection c = subInfo.getSubmissionItem().getCollection(); Collection c = subInfo.getSubmissionItem().getCollection();
DCInput[] inputs = inputsReader.getInputs(c.getHandle()).getPageRows( DCInput[] inputs = null;
currentPage - 1, try
subInfo.getSubmissionItem().hasMultipleTitles(), {
subInfo.getSubmissionItem().isPublishedBefore()); inputs = inputsReader.getInputs(c.getHandle()).getPageRows(
currentPage - 1,
subInfo.getSubmissionItem().hasMultipleTitles(),
subInfo.getSubmissionItem().isPublishedBefore());
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
// Step 1: // Step 1:
// clear out all item metadata defined on this page // clear out all item metadata defined on this page
@@ -176,6 +188,10 @@ public class DescribeStep extends AbstractProcessingStep
qualifier, Item.ANY); qualifier, Item.ANY);
} }
// Clear required-field errors first since missing authority
// values can add them too.
clearErrorFields(request);
// Step 2: // Step 2:
// now update the item metadata. // now update the item metadata.
String fieldName; String fieldName;
@@ -200,6 +216,8 @@ public class DescribeStep extends AbstractProcessingStep
fieldName = schema + "_" + element; fieldName = schema + "_" + element;
} }
String fieldKey = MetadataAuthorityManager.makeFieldKey(schema, element, qualifier);
ChoiceAuthorityManager cmgr = ChoiceAuthorityManager.getManager();
String inputType = inputs[j].getInputType(); String inputType = inputs[j].getInputType();
if (inputType.equals("name")) if (inputType.equals("name"))
{ {
@@ -210,6 +228,25 @@ public class DescribeStep extends AbstractProcessingStep
{ {
readDate(request, item, schema, element, qualifier); readDate(request, item, schema, element, qualifier);
} }
// choice-controlled input with "select" presentation type is
// always rendered as a dropdown menu
else if (inputType.equals("dropdown") || inputType.equals("list") ||
(cmgr.isChoicesConfigured(fieldKey) &&
"select".equals(cmgr.getPresentation(fieldKey))))
{
String[] vals = request.getParameterValues(fieldName);
if (vals != null)
{
for (int z = 0; z < vals.length; z++)
{
if (!vals[z].equals(""))
{
item.addMetadata(schema, element, qualifier, LANGUAGE_QUALIFIER,
vals[z]);
}
}
}
}
else if (inputType.equals("series")) else if (inputType.equals("series"))
{ {
readSeriesNumbers(request, item, schema, element, qualifier, readSeriesNumbers(request, item, schema, element, qualifier,
@@ -238,21 +275,6 @@ public class DescribeStep extends AbstractProcessingStep
} }
} }
} }
else if (inputType.equals("dropdown") || inputType.equals("list"))
{
String[] vals = request.getParameterValues(fieldName);
if (vals != null)
{
for (int z = 0; z < vals.length; z++)
{
if (!vals[z].equals(""))
{
item.addMetadata(schema, element, qualifier, LANGUAGE_QUALIFIER,
vals[z]);
}
}
}
}
else if ((inputType.equals("onebox")) else if ((inputType.equals("onebox"))
|| (inputType.equals("twobox")) || (inputType.equals("twobox"))
|| (inputType.equals("textarea"))) || (inputType.equals("textarea")))
@@ -289,7 +311,6 @@ public class DescribeStep extends AbstractProcessingStep
|| buttonPressed.equals(PREVIOUS_BUTTON) || buttonPressed.equals(PREVIOUS_BUTTON)
|| buttonPressed.equals(CANCEL_BUTTON)) || buttonPressed.equals(CANCEL_BUTTON))
{ {
clearErrorFields(request);
for (int i = 0; i < inputs.length; i++) for (int i = 0; i < inputs.length; i++)
{ {
DCValue[] values = item.getMetadata(inputs[i].getSchema(), DCValue[] values = item.getMetadata(inputs[i].getSchema(),
@@ -352,12 +373,6 @@ public class DescribeStep extends AbstractProcessingStep
public int getNumberOfPages(HttpServletRequest request, public int getNumberOfPages(HttpServletRequest request,
SubmissionInfo subInfo) throws ServletException SubmissionInfo subInfo) throws ServletException
{ {
if (inputsReader == null)
{
// read configurable submissions forms data
inputsReader = new DCInputsReader();
}
// by default, use the "default" collection handle // by default, use the "default" collection handle
String collectionHandle = DCInputsReader.DEFAULT_COLLECTION; String collectionHandle = DCInputsReader.DEFAULT_COLLECTION;
@@ -368,7 +383,14 @@ public class DescribeStep extends AbstractProcessingStep
} }
// get number of input pages (i.e. "Describe" pages) // get number of input pages (i.e. "Describe" pages)
return inputsReader.getNumberInputPages(collectionHandle); try
{
return getInputsReader().getNumberInputPages(collectionHandle);
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
} }
/** /**
@@ -381,7 +403,14 @@ public class DescribeStep extends AbstractProcessingStep
if (inputsReader == null) if (inputsReader == null)
{ {
// read configurable submissions forms data // read configurable submissions forms data
inputsReader = new DCInputsReader(); try
{
inputsReader = new DCInputsReader();
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
} }
return inputsReader; return inputsReader;
@@ -394,7 +423,14 @@ public class DescribeStep extends AbstractProcessingStep
*/ */
public static DCInputsReader getInputsReader(String filename) throws ServletException public static DCInputsReader getInputsReader(String filename) throws ServletException
{ {
inputsReader = new DCInputsReader(filename); try
{
inputsReader = new DCInputsReader(filename);
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
return inputsReader; return inputsReader;
} }
@@ -465,9 +501,14 @@ public class DescribeStep extends AbstractProcessingStep
String metadataField = MetadataField String metadataField = MetadataField
.formKey(schema, element, qualifier); .formKey(schema, element, qualifier);
String fieldKey = MetadataAuthorityManager.makeFieldKey(schema, element, qualifier);
boolean isAuthorityControlled = MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey);
// Names to add // Names to add
List firsts = new LinkedList(); List firsts = new LinkedList();
List lasts = new LinkedList(); List lasts = new LinkedList();
List auths = new LinkedList();
List confs = new LinkedList();
if (repeated) if (repeated)
{ {
@@ -475,6 +516,10 @@ public class DescribeStep extends AbstractProcessingStep
+ "_first"); + "_first");
lasts = getRepeatedParameter(request, metadataField, metadataField lasts = getRepeatedParameter(request, metadataField, metadataField
+ "_last"); + "_last");
auths = getRepeatedParameter(request, metadataField, metadataField
+ "_authority");
confs = getRepeatedParameter(request, metadataField, metadataField
+ "_confidence");
// Find out if the relevant "remove" button was pressed // Find out if the relevant "remove" button was pressed
// TODO: These separate remove buttons are only relevant // TODO: These separate remove buttons are only relevant
@@ -490,6 +535,8 @@ public class DescribeStep extends AbstractProcessingStep
firsts.remove(valToRemove); firsts.remove(valToRemove);
lasts.remove(valToRemove); lasts.remove(valToRemove);
auths.remove(valToRemove);
confs.remove(valToRemove);
} }
} }
else else
@@ -497,11 +544,15 @@ public class DescribeStep extends AbstractProcessingStep
// Just a single name // Just a single name
String lastName = request.getParameter(metadataField + "_last"); String lastName = request.getParameter(metadataField + "_last");
String firstNames = request.getParameter(metadataField + "_first"); String firstNames = request.getParameter(metadataField + "_first");
String authority = request.getParameter(metadataField + "_authority");
String confidence = request.getParameter(metadataField + "_confidence");
if (lastName != null) if (lastName != null)
lasts.add(lastName); lasts.add(lastName);
if (firstNames != null) if (firstNames != null)
firsts.add(firstNames); firsts.add(firstNames);
auths.add(authority == null ? "" : authority);
confs.add(confidence == null ? "" : confidence);
} }
// Remove existing values, already done in doProcessing see also bug DS-203 // Remove existing values, already done in doProcessing see also bug DS-203
@@ -539,8 +590,25 @@ public class DescribeStep extends AbstractProcessingStep
} }
} }
// Add to the database // Add to the database -- unless required authority is missing
item.addMetadata(schema, element, qualifier, null, if (isAuthorityControlled)
{
String authKey = auths.size() > i ? (String)auths.get(i) : null;
String sconf = (authKey != null && confs.size() > i) ? (String)confs.get(i) : null;
if (MetadataAuthorityManager.getManager().isAuthorityRequired(fieldKey) &&
(authKey == null || authKey.length() == 0))
{
log.warn("Skipping value of "+metadataField+" because the required Authority key is missing or empty.");
addErrorField(request, metadataField);
}
else
item.addMetadata(schema, element, qualifier, null,
new DCPersonName(l, f).toString(), authKey,
(sconf != null && sconf.length() > 0) ?
Choices.getConfidenceValue(sconf) : Choices.CF_ACCEPTED);
}
else
item.addMetadata(schema, element, qualifier, null,
new DCPersonName(l, f).toString()); new DCPersonName(l, f).toString());
} }
} }
@@ -586,12 +654,22 @@ public class DescribeStep extends AbstractProcessingStep
String metadataField = MetadataField String metadataField = MetadataField
.formKey(schema, element, qualifier); .formKey(schema, element, qualifier);
String fieldKey = MetadataAuthorityManager.makeFieldKey(schema, element, qualifier);
boolean isAuthorityControlled = MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey);
// Values to add // Values to add
List vals = new LinkedList(); List vals = null;
List auths = null;
List confs = null;
if (repeated) if (repeated)
{ {
vals = getRepeatedParameter(request, metadataField, metadataField); vals = getRepeatedParameter(request, metadataField, metadataField);
if (isAuthorityControlled)
{
auths = getRepeatedParameter(request, metadataField, metadataField+"_authority");
confs = getRepeatedParameter(request, metadataField, metadataField+"_confidence");
}
// Find out if the relevant "remove" button was pressed // Find out if the relevant "remove" button was pressed
// TODO: These separate remove buttons are only relevant // TODO: These separate remove buttons are only relevant
@@ -611,10 +689,19 @@ public class DescribeStep extends AbstractProcessingStep
else else
{ {
// Just a single name // Just a single name
vals = new LinkedList();
String value = request.getParameter(metadataField); String value = request.getParameter(metadataField);
if (value != null) if (value != null)
vals.add(value.trim()); vals.add(value.trim());
if (isAuthorityControlled)
{
auths = new LinkedList();
confs = new LinkedList();
String av = request.getParameter(metadataField+"_authority");
String cv = request.getParameter(metadataField+"_confidence");
auths.add(av == null ? "":av.trim());
confs.add(cv == null ? "":cv.trim());
}
} }
// Remove existing values, already done in doProcessing see also bug DS-203 // Remove existing values, already done in doProcessing see also bug DS-203
@@ -625,10 +712,25 @@ public class DescribeStep extends AbstractProcessingStep
{ {
// Add to the database if non-empty // Add to the database if non-empty
String s = (String) vals.get(i); String s = (String) vals.get(i);
if ((s != null) && !s.equals("")) if ((s != null) && !s.equals(""))
{ {
item.addMetadata(schema, element, qualifier, lang, s); if (isAuthorityControlled)
{
String authKey = auths.size() > i ? (String)auths.get(i) : null;
String sconf = (authKey != null && confs.size() > i) ? (String)confs.get(i) : null;
if (MetadataAuthorityManager.getManager().isAuthorityRequired(fieldKey) &&
(authKey == null || authKey.length() == 0))
{
log.warn("Skipping value of "+metadataField+" because the required Authority key is missing or empty.");
addErrorField(request, metadataField);
}
else
item.addMetadata(schema, element, qualifier, lang, s,
authKey, (sconf != null && sconf.length() > 0) ?
Choices.getConfidenceValue(sconf) : Choices.CF_ACCEPTED);
}
else
item.addMetadata(schema, element, qualifier, lang, s);
} }
} }
} }
@@ -806,9 +908,6 @@ public class DescribeStep extends AbstractProcessingStep
int i = 1; //start index at the first of the previously entered values int i = 1; //start index at the first of the previously entered values
boolean foundLast = false; boolean foundLast = false;
log.debug("getRepeatedParameter: metadataField=" + metadataField
+ " param=" + metadataField);
// Iterate through the values in the form. // Iterate through the values in the form.
while (!foundLast) while (!foundLast)
{ {
@@ -857,6 +956,9 @@ public class DescribeStep extends AbstractProcessingStep
i++; i++;
} }
log.debug("getRepeatedParameter: metadataField=" + metadataField
+ " param=" + metadataField + ", return count = "+vals.size());
return vals; return vals;
} }

View File

@@ -53,7 +53,7 @@ browse.order.desc = Descending
help.collection-admin = /help/collection-admin.html help.collection-admin = /help/collection-admin.html
help.index = /help/index.html help.index = /help/index.html
help.site-admin = /help/site-admin.html help.site-admin = /help/site-admin.html
help.formats = /help/formats.jsp help.formats = /help/formats.jsp
itemlist.dc.contributor.* = Author(s) itemlist.dc.contributor.* = Author(s)
itemlist.dc.contributor.author = Author(s) itemlist.dc.contributor.author = Author(s)
@@ -514,9 +514,9 @@ jsp.general.searchfor = <strong>Search
jsp.general.subjects.button = Subjects jsp.general.subjects.button = Subjects
jsp.general.titles.button = Titles jsp.general.titles.button = Titles
jsp.general.untitled = Untitled jsp.general.untitled = Untitled
jsp.general.update = Update jsp.general.update = Update
jsp.general.without-contributor = Anonymous jsp.general.without-contributor = Anonymous
jsp.general.without-date = No date given jsp.general.without-date = No date given
jsp.help = Help... jsp.help = Help...
jsp.help.formats.contact1 = Please contact your jsp.help.formats.contact1 = Please contact your
jsp.help.formats.contact2 = DSpace Administrator jsp.help.formats.contact2 = DSpace Administrator
@@ -786,9 +786,9 @@ jsp.search.advanced.type.series = Series
jsp.search.advanced.type.sponsor = Sponsor jsp.search.advanced.type.sponsor = Sponsor
jsp.search.advanced.type.subject = Subject jsp.search.advanced.type.subject = Subject
jsp.search.advanced.type.title = Title jsp.search.advanced.type.title = Title
jsp.search.error.invalid-search-string = Invalid search string jsp.search.error.invalid-search-string = Invalid search string
jsp.search.error.number-format-exception = Number format exception jsp.search.error.number-format-exception = Number format exception
jsp.search.error.query-too-broad = Your query was too broad. Try a narrower query. jsp.search.error.query-too-broad = Your query was too broad. Try a narrower query.
jsp.search.general.next = next jsp.search.general.next = next
jsp.search.general.noresults = Search produced no results. jsp.search.general.noresults = Search produced no results.
jsp.search.general.previous = previous jsp.search.general.previous = previous
@@ -827,7 +827,7 @@ jsp.submit.choose-file.info6 = Please also no
jsp.submit.choose-file.info7 = Information about file types and levels of support for each are available. jsp.submit.choose-file.info7 = Information about file types and levels of support for each are available.
jsp.submit.choose-file.info9 = Please give a brief description of the contents of this file, for example "Main article", or "Experiment data readings". jsp.submit.choose-file.info9 = Please give a brief description of the contents of this file, for example "Main article", or "Experiment data readings".
jsp.submit.choose-file.title = Upload a File jsp.submit.choose-file.title = Upload a File
jsp.submit.choose-file.skip = Skip file upload &gt; jsp.submit.choose-file.skip = Skip file upload &gt;
jsp.submit.complete.heading = Submit: Submission Complete! jsp.submit.complete.heading = Submit: Submission Complete!
jsp.submit.complete.info = Your submission will now go through the workflow process designated for the collection to which you are submitting. You will receive e-mail notification as soon as your submission has become a part of the collection, or if for some reason there is a problem with your submission. You can also check on the status of your submission by going to the My DSpace page. jsp.submit.complete.info = Your submission will now go through the workflow process designated for the collection to which you are submitting. You will receive e-mail notification as soon as your submission has become a part of the collection, or if for some reason there is a problem with your submission. You can also check on the status of your submission by going to the My DSpace page.
jsp.submit.complete.link = Go to My DSpace jsp.submit.complete.link = Go to My DSpace
@@ -932,8 +932,8 @@ jsp.submit.select-collection.heading = Submit: Choose
jsp.submit.select-collection.info1 = Select the collection you wish to submit an item to from the list below, then click "Next". jsp.submit.select-collection.info1 = Select the collection you wish to submit an item to from the list below, then click "Next".
jsp.submit.select-collection.none-authorized = You are not authorized to submit to any collections jsp.submit.select-collection.none-authorized = You are not authorized to submit to any collections
jsp.submit.select-collection.title = Select Collection to Submit to jsp.submit.select-collection.title = Select Collection to Submit to
jsp.submit.select-collection.no-collection = You must select a collection for this item. jsp.submit.select-collection.no-collection = You must select a collection for this item.
jsp.submit.select-collection.cancel = Cancel jsp.submit.select-collection.cancel = Cancel
jsp.submit.show-license.grant.button = I Grant the License jsp.submit.show-license.grant.button = I Grant the License
jsp.submit.show-license.heading1 = Submit: Grant DSpace Distribution License jsp.submit.show-license.heading1 = Submit: Grant DSpace Distribution License
jsp.submit.show-license.info1 = <strong>There is one last step:</strong> In order for DSpace to reproduce, translate and distribute your submission worldwide, your agreement to the following terms is necessary. Please take a moment to read the terms of this license, and click on one of the buttons at the bottom of the page. By clicking on the "Grant License" button, you indicate that you grant the following terms of the license. jsp.submit.show-license.info1 = <strong>There is one last step:</strong> In order for DSpace to reproduce, translate and distribute your submission worldwide, your agreement to the following terms is necessary. Please take a moment to read the terms of this license, and click on one of the buttons at the bottom of the page. By clicking on the "Grant License" button, you indicate that you grant the following terms of the license.
@@ -1123,6 +1123,7 @@ jsp.tools.edit-item-form.reinstate.button = Reinstate
jsp.tools.edit-item-form.replacecc.button = Replace Creative Commons License jsp.tools.edit-item-form.replacecc.button = Replace Creative Commons License
jsp.tools.edit-item-form.title = Edit Item jsp.tools.edit-item-form.title = Edit Item
jsp.tools.edit-item-form.withdraw-w-confirm.button = Withdraw... jsp.tools.edit-item-form.withdraw-w-confirm.button = Withdraw...
jsp.tools.edit-item-form.unlock = Unlock the authority key value for manual editing, or toggle it locked again
jsp.tools.eperson-list.close.button = Close jsp.tools.eperson-list.close.button = Close
jsp.tools.eperson-list.heading = E-people {0}-{1} of {2} jsp.tools.eperson-list.heading = E-people {0}-{1} of {2}
jsp.tools.eperson-list.info1 = Clicking on the 'Add' button next to an e-person will add that e-person to the list on the main form. jsp.tools.eperson-list.info1 = Clicking on the 'Add' button next to an e-person will add that e-person to the list on the main form.
@@ -1373,7 +1374,7 @@ org.dspace.content.Community.untitled
org.dspace.eperson.LDAPAuthentication.title = Enter LDAP Netid and Password org.dspace.eperson.LDAPAuthentication.title = Enter LDAP Netid and Password
org.dspace.eperson.PasswordAuthentication.title = Enter DSpace Username and Password org.dspace.eperson.PasswordAuthentication.title = Enter DSpace Username and Password
org.dspace.eperson.X509Authentication.title = Enter DSpace using Web Certificate org.dspace.eperson.X509Authentication.title = Enter DSpace using Web Certificate
org.dspace.authenticate.ShibAuthentication.title = Login via Shibboleth org.dspace.authenticate.ShibAuthentication.title = Login via Shibboleth
org.dspace.eperson.Subscribe.authors = Authors: org.dspace.eperson.Subscribe.authors = Authors:
org.dspace.eperson.Subscribe.id = ID: org.dspace.eperson.Subscribe.id = ID:
org.dspace.eperson.Subscribe.new-items = New Items: org.dspace.eperson.Subscribe.new-items = New Items:
@@ -1394,3 +1395,76 @@ search.sort-by.title
search.sort-by.dateissued = Issue Date search.sort-by.dateissued = Issue Date
search.sort-by.dateaccessioned = Submit Date search.sort-by.dateaccessioned = Submit Date
search.update = Update search.update = Update
jsp.layout.navbar-admin.authority = Authority control<br/> management
#org.dspace.app.webui.AuthorityManagementServlet
org.dspace.app.webui.AuthorityManagementServlet.submit_reject = The selected potential matches has been rejected!
org.dspace.app.webui.AuthorityManagementServlet.submit_accept = The selected potential matches has been confirmed!
#dspace-admin/auhtority.jsp
jsp.dspace-admin.authority = Authority management
jsp.dspace-admin.authority-heading = Statistics about the authority for the metadata {0}
jsp.dspace-admin.authority-statistics.label = Stat
jsp.dspace-admin.authority-statistics.value = # of ...
jsp.dspace-admin.authority-statistics.numTotMetadata = # of metadata
jsp.dspace-admin.authority-statistics.numTotMetadata-level = # of metadata grouped by confidence
jsp.dspace-admin.authority-statistics.numAuthorityKey = # of in-use authority keys
jsp.dspace-admin.authority-statistics.numAuthorityIssued = # of authority keys pending approval
jsp.dspace-admin.authority-statistics.numItems = # of items with authority key
jsp.dspace-admin.authority-statistics.numIssuedItems = # of issued items
jsp.common.authority-level0 = No Value
jsp.common.authority-level1 = Rejected
jsp.common.authority-level2 = Failed
jsp.common.authority-level3 = Not Found
jsp.common.authority-level4 = Ambiguous
jsp.common.authority-level5 = Uncertain
jsp.common.authority-level6 = Accepted
jsp.dspace-admin.authority-statistics.numTotMetadata-value = #
#dspace-admin/auhtority-issued.jsp
jsp.dspace-admin.authority-issued = List of authority key pending approval for the metadata: {0}
#dspace-admin/auhtority-key.jsp
jsp.dspace-admin.authority-key.title = Issued item of the authority key {0}
jsp.dspace-admin.authority-key.heading = Issued item of the authority key {0}
jsp.dspace-admin.authority-key.items-heading = List of items pending approval
jsp.dspace-admin.authority-key.info-heading = Information about the authority
jsp.dspace-admin.authority-key.label = Label
jsp.dspace-admin.authority-key.key = Authority key
jsp.dspace-admin.authority-key.variants = Variants
jsp.dspace-admin.authority-key.accept = Accept
jsp.dspace-admin.authority-key.reject = Reject
jsp.dspace-admin.authority-key.previous = Previous
jsp.dspace-admin.authority-key.list = Return to the list
jsp.dspace-admin.authority-key.next = Next
# authority-control confidence levels, descriptions:
jsp.authority.confidence.description.unset = Confidence was never recorded for this value
jsp.authority.confidence.description.novalue = No reasonable confidence value was returned from the authority
jsp.authority.confidence.description.rejected = The authority recommends this submission be rejected
jsp.authority.confidence.description.failed = The authority encountered an internal failure
jsp.authority.confidence.description.notfound = There are no matching answers in the authority
jsp.authority.confidence.description.ambiguous = There are multiple matching authority values of equal validity
jsp.authority.confidence.description.uncertain = Value is singular and valid but has not been seen and accepted by a human so it is still uncertain
jsp.authority.confidence.description.accepted = This authority value has been confirmed as accurate by an interactive user
jsp.tools.lookup.title = DSpace Value Lookup
jsp.tools.lookup.heading = Looking Up Value
jsp.tools.lookup.accept = Accept
jsp.tools.lookup.add = Add
jsp.tools.lookup.cancel = Cancel
jsp.tools.lookup.more = See More Results
jsp.tools.lookup.fail = Failed to load choice data:
jsp.tools.lookup.results = Results @1@ to @2@ of @3@ for "@4@"
jsp.tools.lookup.lookup = Lookup this value
# choice lookup example for dc.publisher
jsp.tools.lookup.field.dc_publisher.help = Name of Publisher
jsp.tools.lookup.field.dc_publisher.title = Look up Publisher
jsp.tools.lookup.field.dc_publisher.nonauthority = Non-authority value: @1@
# choice lookup example for dc.contributor.author
jsp.tools.lookup.field.dc_contributor_author.help = Name in "Last, First" format
jsp.tools.lookup.field.dc_contributor_author.help.last = Last name, e.g. "Smith"
jsp.tools.lookup.field.dc_contributor_author.help.first = First name(s) e.g. "Fred"
jsp.tools.lookup.field.dc_contributor_author.title = LC Name Authority author lookup
jsp.tools.lookup.field.dc_contributor_author.nonauthority = Local value '@1@' (not in Naming Authority)

View File

@@ -66,8 +66,10 @@ import java.awt.image.BufferedImage;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.dspace.content.authority.MetadataAuthorityManager;
/** /**
* Tag for display a list of items * Tag for display a list of items
@@ -532,19 +534,36 @@ public class BrowseListTag extends TagSupport
String endLink = ""; String endLink = "";
if (!StringUtils.isEmpty(browseType[colIdx]) && !disableCrossLinks) if (!StringUtils.isEmpty(browseType[colIdx]) && !disableCrossLinks)
{ {
String argument = "value"; String argument;
String value;
if (metadataArray[j].authority != null &&
metadataArray[j].confidence >= MetadataAuthorityManager.getManager()
.getMinConfidence(metadataArray[j].schema, metadataArray[j].element, metadataArray[j].qualifier))
{
argument = "authority";
value = metadataArray[j].authority;
}
else
{
argument = "value";
value = metadataArray[j].value;
}
if (viewFull[colIdx]) if (viewFull[colIdx])
{ {
argument = "vfocus"; argument = "vfocus";
} }
startLink = "<a href=\"" + hrq.getContextPath() + "/browse?type=" + browseType[colIdx] + "&amp;" + startLink = "<a href=\"" + hrq.getContextPath() + "/browse?type=" + browseType[colIdx] + "&amp;" +
argument + "=" + Utils.addEntities(metadataArray[j].value); argument + "=" + URLEncoder.encode(value,"UTF-8");
if (metadataArray[j].language != null) if (metadataArray[j].language != null)
{ {
startLink = startLink + "&amp;" + startLink = startLink + "&amp;" +
argument + "_lang=" + Utils.addEntities(metadataArray[j].language) + argument + "_lang=" + URLEncoder.encode(metadataArray[j].language, "UTF-8");
"\">"; }
if ("authority".equals(argument))
{
startLink += "\" class=\"authority " +browseType[colIdx] + "\">";
} }
else else
{ {

View File

@@ -70,6 +70,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.StringTokenizer; import java.util.StringTokenizer;
@@ -80,6 +81,7 @@ import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.jstl.fmt.LocaleSupport; import javax.servlet.jsp.jstl.fmt.LocaleSupport;
import javax.servlet.jsp.tagext.TagSupport; import javax.servlet.jsp.tagext.TagSupport;
import org.dspace.content.authority.MetadataAuthorityManager;
/** /**
* Tag for display a list of items * Tag for display a list of items
@@ -501,19 +503,36 @@ public class ItemListTag extends TagSupport
String endLink = ""; String endLink = "";
if (!StringUtils.isEmpty(browseType[colIdx]) && !disableCrossLinks) if (!StringUtils.isEmpty(browseType[colIdx]) && !disableCrossLinks)
{ {
String argument = "value"; String argument;
String value;
if (metadataArray[j].authority != null &&
metadataArray[j].confidence >= MetadataAuthorityManager.getManager()
.getMinConfidence(metadataArray[j].schema, metadataArray[j].element, metadataArray[j].qualifier))
{
argument = "authority";
value = metadataArray[j].authority;
}
else
{
argument = "value";
value = metadataArray[j].value;
}
if (viewFull[colIdx]) if (viewFull[colIdx])
{ {
argument = "vfocus"; argument = "vfocus";
} }
startLink = "<a href=\"" + hrq.getContextPath() + "/browse?type=" + browseType[colIdx] + "&amp;" + startLink = "<a href=\"" + hrq.getContextPath() + "/browse?type=" + browseType[colIdx] + "&amp;" +
argument + "=" + Utils.addEntities(metadataArray[j].value); argument + "=" + URLEncoder.encode(value,"UTF-8");
if (metadataArray[j].language != null) if (metadataArray[j].language != null)
{ {
startLink = startLink + "&amp;" + startLink = startLink + "&amp;" +
argument + "_lang=" + Utils.addEntities(metadataArray[j].language) + argument + "_lang=" + URLEncoder.encode(metadataArray[j].language, "UTF-8");
"\">"; }
if ("authority".equals(argument))
{
startLink += "\" class=\"authority " +browseType[colIdx] + "\">";
} }
else else
{ {
@@ -557,13 +576,13 @@ public class ItemListTag extends TagSupport
{ {
String id = "t" + Integer.toString(cOddOrEven.length + 1); String id = "t" + Integer.toString(cOddOrEven.length + 1);
out.print("<td headers=\"" + id + "\" class=\"" out.print("<td headers=\"" + id + "\" class=\""
+ rOddOrEven + "Row" + cOddOrEven[cOddOrEven.length - 2] + "Col\" nowrap>" + rOddOrEven + "Row" + cOddOrEven[cOddOrEven.length - 2] + "Col\" nowrap>"
+ "<form method=\"get\" action=\"" + hrq.getContextPath() + "/tools/edit-item\">" + "<form method=\"get\" action=\"" + hrq.getContextPath() + "/tools/edit-item\">"
+ "<input type=\"hidden\" name=\"handle\" value=\"" + items[i].getHandle() + "\" />" + "<input type=\"hidden\" name=\"handle\" value=\"" + items[i].getHandle() + "\" />"
+ "<input type=\"submit\" value=\"Edit Item\" /></form>" + "<input type=\"submit\" value=\"Edit Item\" /></form>"
+ "</td>"); + "</td>");
} }
out.println("</tr>"); out.println("</tr>");
} }
@@ -861,5 +880,5 @@ public class ItemListTag extends TagSupport
{ {
throw new JspException("Server does not support DSpace's default encoding. ", e); throw new JspException("Server does not support DSpace's default encoding. ", e);
} }
}
} }
}

View File

@@ -65,6 +65,7 @@ import org.dspace.content.Collection;
import org.dspace.content.DCDate; import org.dspace.content.DCDate;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.I18nUtil; import org.dspace.core.I18nUtil;
@@ -547,10 +548,24 @@ public class ItemTag extends TagSupport
} }
else if (browseIndex != null) else if (browseIndex != null)
{ {
out.print("<a href=\"" + request.getContextPath() + "/browse?type=" + browseIndex + "&amp;value=" String argument, value;
+ URLEncoder.encode(values[j].value, "UTF-8") + "\">" + Utils.addEntities(values[j].value) if ( values[j].authority != null &&
+ "</a>"); values[j].confidence >= MetadataAuthorityManager.getManager()
} .getMinConfidence( values[j].schema, values[j].element, values[j].qualifier))
{
argument = "authority";
value = values[j].authority;
}
else
{
argument = "value";
value = values[j].value;
}
out.print("<a class=\"" + ("authority".equals(argument)?"authority ":"") + browseIndex + "\""
+ "href=\"" + request.getContextPath() + "/browse?type=" + browseIndex + "&amp;" + argument + "="
+ URLEncoder.encode(value, "UTF-8") + "\">" + Utils.addEntities(values[j].value)
+ "</a>");
}
else else
{ {
out.print(Utils.addEntities(values[j].value)); out.print(Utils.addEntities(values[j].value));

View File

@@ -120,6 +120,7 @@ public abstract class AbstractBrowserServlet extends DSpaceServlet
String startsWith = request.getParameter("starts_with"); String startsWith = request.getParameter("starts_with");
String valueFocus = request.getParameter("vfocus"); String valueFocus = request.getParameter("vfocus");
String valueFocusLang = request.getParameter("vfocus_lang"); String valueFocusLang = request.getParameter("vfocus_lang");
String authority = request.getParameter("authority");
int focus = UIUtil.getIntParameter(request, "focus"); int focus = UIUtil.getIntParameter(request, "focus");
int offset = UIUtil.getIntParameter(request, "offset"); int offset = UIUtil.getIntParameter(request, "offset");
int resultsperpage = UIUtil.getIntParameter(request, "rpp"); int resultsperpage = UIUtil.getIntParameter(request, "rpp");
@@ -229,7 +230,7 @@ public abstract class AbstractBrowserServlet extends DSpaceServlet
// determine which level of the browse we are at: 0 for top, 1 for second // determine which level of the browse we are at: 0 for top, 1 for second
int level = 0; int level = 0;
if (value != null) if (value != null || authority != null)
{ {
level = 1; level = 1;
} }
@@ -281,7 +282,7 @@ public abstract class AbstractBrowserServlet extends DSpaceServlet
BrowserScope scope = new BrowserScope(context); BrowserScope scope = new BrowserScope(context);
scope.setBrowseIndex(bi); scope.setBrowseIndex(bi);
scope.setOrder(order); scope.setOrder(order);
scope.setFilterValue(value); scope.setFilterValue(value != null?value:authority);
scope.setFilterValueLang(valueLang); scope.setFilterValueLang(valueLang);
scope.setJumpToItem(focus); scope.setJumpToItem(focus);
scope.setJumpToValue(valueFocus); scope.setJumpToValue(valueFocus);
@@ -292,6 +293,7 @@ public abstract class AbstractBrowserServlet extends DSpaceServlet
scope.setSortBy(sortBy); scope.setSortBy(sortBy);
scope.setBrowseLevel(level); scope.setBrowseLevel(level);
scope.setEtAl(etAl); scope.setEtAl(etAl);
scope.setAuthorityValue(authority);
// assign the scope of either Community or Collection if necessary // assign the scope of either Community or Collection if necessary
if (community != null) if (community != null)

View File

@@ -0,0 +1,105 @@
/*
*
*/
package org.dspace.app.webui.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Properties;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.xml.sax.SAXException;
import org.apache.commons.digester.plugins.PluginAssertionFailure;
import org.dspace.app.webui.util.UIUtil;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.authority.Choice;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.Choices;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.content.authority.ChoicesXMLGenerator;
import org.dspace.core.Context;
import org.apache.xml.serializer.SerializerFactory;
import org.apache.xml.serializer.Serializer;
import org.apache.xml.serializer.OutputPropertiesFactory;
import org.apache.xml.serializer.Method;
/**
*
* @author bollini
*/
public class AuthorityChooseServlet extends DSpaceServlet {
@Override
protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException {
process(context, request, response);
}
@Override
protected void doDSPost(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException {
process(context, request, response);
}
/**
* Generate the AJAX response Document.
*
* Looks for request parameters:
* field - MD field key, i.e. form key, REQUIRED - derivated from url.
* query - string to match
* collection - db ID of Collection ot serve as context
* start - index to start from, default 0.
* limit - max number of lines, default 1000.
* format - opt. result XML/XHTML format: "select", "ul", "xml"(default)
* locale - explicit locale, pass to choice plugin
*/
private void process(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException {
String[] paths = request.getPathInfo().split("/");
String field = paths[paths.length-1];
ChoiceAuthorityManager cam = ChoiceAuthorityManager.getManager();
String query = request.getParameter("query");
String format = request.getParameter("format");
int collection = UIUtil.getIntParameter(request, "collection");
int start = UIUtil.getIntParameter(request, "start");
int limit = UIUtil.getIntParameter(request, "limit");
Choices result = cam.getMatches(field, query, collection, start, limit, null);
// Choice[] testValues = {
// new Choice("rp0001", "VALUE1","TEST LABEL1"),
// new Choice("rp0002", "VALUE2","TEST LABEL2"),
// new Choice("rp0003", "VALUE3","TEST LABEL3"),
// new Choice("rp0004", "VALUE COGN, LABEL1","TEST COGN, LABEL1"),
// new Choice("rp0005", "VALUE COGN, LABEL2","TEST COGN, LABEL2"),
// new Choice("rp0006", "VALUE COGN, LABEL3","TEST COGN, LABEL3")
// };
//
// Choices result = new Choices(testValues,start,testValues.length,Choices.CF_ACCEPTED,false);
Writer writer = response.getWriter();
// borrow xalan's serializer to let us use SAX choice menu generator
Properties props =
OutputPropertiesFactory.getDefaultMethodProperties(Method.XML);
Serializer ser = SerializerFactory.getSerializer(props);
ser.setWriter(writer);
try
{
ChoicesXMLGenerator.generate(result, format, ser.asContentHandler());
}
catch(SAXException e)
{
throw new IOException(e.toString());
}
finally
{
ser.reset();
}
writer.flush();
}
}

View File

@@ -76,6 +76,7 @@ import org.dspace.content.FormatIdentifier;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataField; import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema; import org.dspace.content.MetadataSchema;
import org.dspace.content.authority.Choices;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.LogManager; import org.dspace.core.LogManager;
@@ -278,21 +279,21 @@ public class EditItemServlet extends DSpaceServlet
break; break;
case START_MOVE_ITEM: case START_MOVE_ITEM:
if (AuthorizeManager.isAdmin(context,item)) if (AuthorizeManager.isAdmin(context,item))
{ {
// Display move collection page with fields of collections and communities // Display move collection page with fields of collections and communities
Collection[] allNotLinkedCollections = item.getCollectionsNotLinked(); Collection[] allNotLinkedCollections = item.getCollectionsNotLinked();
Collection[] allLinkedCollections = item.getCollections(); Collection[] allLinkedCollections = item.getCollections();
// get only the collection where the current user has the right permission // get only the collection where the current user has the right permission
List<Collection> authNotLinkedCollections = new ArrayList<Collection>(); List<Collection> authNotLinkedCollections = new ArrayList<Collection>();
for (Collection c : allNotLinkedCollections) for (Collection c : allNotLinkedCollections)
{ {
if (AuthorizeManager.authorizeActionBoolean(context, c, Constants.ADD)) if (AuthorizeManager.authorizeActionBoolean(context, c, Constants.ADD))
{ {
authNotLinkedCollections.add(c); authNotLinkedCollections.add(c);
} }
} }
List<Collection> authLinkedCollections = new ArrayList<Collection>(); List<Collection> authLinkedCollections = new ArrayList<Collection>();
for (Collection c : allLinkedCollections) for (Collection c : allLinkedCollections)
@@ -308,39 +309,39 @@ public class EditItemServlet extends DSpaceServlet
Collection[] linkedCollections = new Collection[authLinkedCollections.size()]; Collection[] linkedCollections = new Collection[authLinkedCollections.size()];
linkedCollections = authLinkedCollections.toArray(linkedCollections); linkedCollections = authLinkedCollections.toArray(linkedCollections);
request.setAttribute("linkedCollections", linkedCollections); request.setAttribute("linkedCollections", linkedCollections);
request.setAttribute("notLinkedCollections", notLinkedCollections); request.setAttribute("notLinkedCollections", notLinkedCollections);
JSPManager.showJSP(request, response, "/tools/move-item.jsp"); JSPManager.showJSP(request, response, "/tools/move-item.jsp");
} else } else
{ {
throw new ServletException("You must be an administrator to move an item"); throw new ServletException("You must be an administrator to move an item");
} }
break; break;
case CONFIRM_MOVE_ITEM: case CONFIRM_MOVE_ITEM:
if (AuthorizeManager.isAdmin(context,item)) if (AuthorizeManager.isAdmin(context,item))
{ {
Collection fromCollection = Collection.find(context, UIUtil.getIntParameter(request, "collection_from_id")); Collection fromCollection = Collection.find(context, UIUtil.getIntParameter(request, "collection_from_id"));
Collection toCollection = Collection.find(context, UIUtil.getIntParameter(request, "collection_to_id")); Collection toCollection = Collection.find(context, UIUtil.getIntParameter(request, "collection_to_id"));
if (fromCollection == null || toCollection == null) if (fromCollection == null || toCollection == null)
{ {
throw new ServletException("Missing or incorrect collection IDs for moving item"); throw new ServletException("Missing or incorrect collection IDs for moving item");
} }
item.move(fromCollection, toCollection); item.move(fromCollection, toCollection);
showEditForm(context, request, response, item); showEditForm(context, request, response, item);
context.complete(); context.complete();
} else } else
{ {
throw new ServletException("You must be an administrator to move an item"); throw new ServletException("You must be an administrator to move an item");
} }
break; break;
default: default:
@@ -400,11 +401,11 @@ public class EditItemServlet extends DSpaceServlet
// turn off auth system to allow replace also to user that can't // turn off auth system to allow replace also to user that can't
// remove/add bitstream to the item // remove/add bitstream to the item
context.turnOffAuthorisationSystem(); context.turnOffAuthorisationSystem();
// set or replace existing CC license // set or replace existing CC license
CreativeCommons.setLicense( context, item, CreativeCommons.setLicense( context, item,
request.getParameter("cc_license_url") ); request.getParameter("cc_license_url") );
context.restoreAuthSystemState(); context.restoreAuthSystemState();
context.commit(); context.commit();
} }
// Get the handle, if any // Get the handle, if any
@@ -605,16 +606,33 @@ public class EditItemServlet extends DSpaceServlet
language = null; language = null;
} }
// Get the authority key if any
String authority = request.getParameter("choice_" + key + "_authority_"
+ sequenceNumber);
// Empty string authority = null
if ((authority != null) && authority.equals(""))
{
authority = null;
}
// Get the authority confidence value, passed as symbolic name
String sconfidence = request.getParameter("choice_" + key + "_confidence_" + sequenceNumber);
int confidence = (sconfidence == null || sconfidence.equals("")) ?
Choices.CF_NOVALUE : Choices.getConfidenceValue(sconfidence);
// Get the value // Get the value
String value = request.getParameter(p).trim(); String value = request.getParameter(p).trim();
// If remove button pressed for this value, we don't add it // If remove button pressed for this value, we don't add it
// back to the item. We also don't add empty values. // back to the item. We also don't add empty values
if (!(value.equals("") || button.equals("submit_remove_" + key // (if no authority is specified).
if (!((value.equals("") && authority == null) || button.equals("submit_remove_" + key
+ "_" + sequenceNumber))) + "_" + sequenceNumber)))
{ {
// Value is empty, or remove button for this wasn't pressed // Value is empty, or remove button for this wasn't pressed
item.addMetadata(schema, element, qualifier, language, value); item.addMetadata(schema, element, qualifier, language, value,
authority, confidence);
} }
} }
else if (p.startsWith("bitstream_name")) else if (p.startsWith("bitstream_name"))

View File

@@ -50,6 +50,8 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.app.util.DCInputsReader;
import org.dspace.app.util.DCInputsReaderException;
import org.dspace.app.util.SubmissionInfo; import org.dspace.app.util.SubmissionInfo;
import org.dspace.app.webui.submit.JSPStep; import org.dspace.app.webui.submit.JSPStep;
import org.dspace.app.webui.submit.JSPStepManager; import org.dspace.app.webui.submit.JSPStepManager;
@@ -238,8 +240,16 @@ public class JSPDescribeStep extends JSPStep
Collection c = subInfo.getSubmissionItem().getCollection(); Collection c = subInfo.getSubmissionItem().getCollection();
// requires configurable form info per collection // requires configurable form info per collection
request.setAttribute("submission.inputs", DescribeStep.getInputsReader(formFileName).getInputs(c try
.getHandle())); {
request.setAttribute("submission.inputs", DescribeStep.getInputsReader(formFileName).getInputs(c
.getHandle()));
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
// forward to edit-metadata JSP // forward to edit-metadata JSP
JSPStepManager.showJSP(request, response, subInfo, DISPLAY_JSP); JSPStepManager.showJSP(request, response, subInfo, DISPLAY_JSP);

View File

@@ -49,6 +49,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.app.util.DCInputsReader; import org.dspace.app.util.DCInputsReader;
import org.dspace.app.util.DCInputsReaderException;
import org.dspace.app.util.SubmissionInfo; import org.dspace.app.util.SubmissionInfo;
import org.dspace.app.webui.submit.JSPStep; import org.dspace.app.webui.submit.JSPStep;
import org.dspace.app.webui.submit.JSPStepManager; import org.dspace.app.webui.submit.JSPStepManager;
@@ -233,12 +234,19 @@ public class JSPInitialQuestionsStep extends JSPStep
// determine collection // determine collection
Collection c = subInfo.getSubmissionItem().getCollection(); Collection c = subInfo.getSubmissionItem().getCollection();
// read configurable submissions forms data try
DCInputsReader inputsReader = new DCInputsReader(); {
// read configurable submissions forms data
DCInputsReader inputsReader = new DCInputsReader();
// load the proper submission inputs to be used by the JSP // load the proper submission inputs to be used by the JSP
request.setAttribute("submission.inputs", inputsReader.getInputs(c request.setAttribute("submission.inputs", inputsReader.getInputs(c
.getHandle())); .getHandle()));
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
// forward to initial questions JSP // forward to initial questions JSP
JSPStepManager.showJSP(request, response, subInfo, INITIAL_QUESTIONS_JSP); JSPStepManager.showJSP(request, response, subInfo, INITIAL_QUESTIONS_JSP);

View File

@@ -53,6 +53,7 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.app.util.DCInputsReader; import org.dspace.app.util.DCInputsReader;
import org.dspace.app.util.DCInputsReaderException;
import org.dspace.app.util.Util; import org.dspace.app.util.Util;
import org.dspace.app.webui.submit.JSPStep; import org.dspace.app.webui.submit.JSPStep;
import org.dspace.app.webui.submit.JSPStepManager; import org.dspace.app.webui.submit.JSPStepManager;
@@ -161,9 +162,16 @@ public class JSPUploadStep extends JSPStep
if (subInfo != null) if (subInfo != null)
{ {
Collection c = subInfo.getSubmissionItem().getCollection(); Collection c = subInfo.getSubmissionItem().getCollection();
DCInputsReader inputsReader = new DCInputsReader(); try
request.setAttribute("submission.inputs", inputsReader.getInputs(c {
.getHandle())); DCInputsReader inputsReader = new DCInputsReader();
request.setAttribute("submission.inputs", inputsReader.getInputs(c
.getHandle()));
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
} }
// show whichever upload page is appropriate // show whichever upload page is appropriate
@@ -254,10 +262,18 @@ public class JSPUploadStep extends JSPStep
// We need to show the file upload error page // We need to show the file upload error page
if (subInfo != null) if (subInfo != null)
{ {
Collection c = subInfo.getSubmissionItem().getCollection(); try
DCInputsReader inputsReader = new DCInputsReader(); {
request.setAttribute("submission.inputs", inputsReader Collection c = subInfo.getSubmissionItem().getCollection();
.getInputs(c.getHandle())); DCInputsReader inputsReader = new DCInputsReader();
request.setAttribute("submission.inputs", inputsReader
.getInputs(c.getHandle()));
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
} }
JSPStepManager.showJSP(request, response, subInfo, UPLOAD_ERROR_JSP); JSPStepManager.showJSP(request, response, subInfo, UPLOAD_ERROR_JSP);
} }

View File

@@ -135,6 +135,11 @@
<groupId>org.dspace</groupId> <groupId>org.dspace</groupId>
<artifactId>dspace-jspui-api</artifactId> <artifactId>dspace-jspui-api</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.dspace</groupId>
<artifactId>dspace-ui-shared</artifactId>
<type>war</type>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -203,15 +203,15 @@
<servlet-class>org.dspace.app.webui.servlet.ItemExportArchiveServlet</servlet-class> <servlet-class>org.dspace.app.webui.servlet.ItemExportArchiveServlet</servlet-class>
</servlet> </servlet>
<servlet> <servlet>
<servlet-name>browse</servlet-name> <servlet-name>browse</servlet-name>
<servlet-class>org.dspace.app.webui.servlet.BrowserServlet</servlet-class> <servlet-class>org.dspace.app.webui.servlet.BrowserServlet</servlet-class>
</servlet> </servlet>
<servlet> <servlet>
<servlet-name>browsewithdrawn</servlet-name> <servlet-name>browsewithdrawn</servlet-name>
<servlet-class>org.dspace.app.webui.servlet.admin.WithdrawnBrowserServlet</servlet-class> <servlet-class>org.dspace.app.webui.servlet.admin.WithdrawnBrowserServlet</servlet-class>
</servlet> </servlet>
<servlet> <servlet>
<servlet-name>collection-wizard</servlet-name> <servlet-name>collection-wizard</servlet-name>
@@ -449,6 +449,10 @@
<servlet-class>org.dspace.app.webui.servlet.ControlledVocabularySearchServlet</servlet-class> <servlet-class>org.dspace.app.webui.servlet.ControlledVocabularySearchServlet</servlet-class>
</servlet> </servlet>
<servlet>
<servlet-name>AuthorityChooseServlet</servlet-name>
<servlet-class>org.dspace.app.webui.servlet.AuthorityChooseServlet</servlet-class>
</servlet>
<!-- shibbolized dspace --> <!-- shibbolized dspace -->
<servlet> <servlet>
@@ -484,15 +488,15 @@
<url-pattern>/exportdownload/*</url-pattern> <url-pattern>/exportdownload/*</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping> <servlet-mapping>
<servlet-name>browse</servlet-name> <servlet-name>browse</servlet-name>
<url-pattern>/browse</url-pattern> <url-pattern>/browse</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping> <servlet-mapping>
<servlet-name>browsewithdrawn</servlet-name> <servlet-name>browsewithdrawn</servlet-name>
<url-pattern>/dspace-admin/withdrawn</url-pattern> <url-pattern>/dspace-admin/withdrawn</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping> <servlet-mapping>
<servlet-name>community-list</servlet-name> <servlet-name>community-list</servlet-name>
@@ -724,6 +728,10 @@
<url-pattern>/subject-search</url-pattern> <url-pattern>/subject-search</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>AuthorityChooseServlet</servlet-name>
<url-pattern>/choices/*</url-pattern>
</servlet-mapping>
<!-- Icon MIME type --> <!-- Icon MIME type -->
<mime-mapping> <mime-mapping>

View File

@@ -331,14 +331,14 @@
<% <%
// Row: toggles between Odd and Even // Row: toggles between Odd and Even
String row = "odd"; String row = "odd";
String[] results = bi.getStringResults(); String[][] results = bi.getStringResults();
for (int i = 0; i < results.length; i++) for (int i = 0; i < results.length; i++)
{ {
%> %>
<tr> <tr>
<td class="<%= row %>RowOddCol"> <td class="<%= row %>RowOddCol">
<a href="<%= sharedLink %>&amp;value=<%= URLEncoder.encode(results[i], "UTF-8") %>"><%= Utils.addEntities(results[i]) %></a> <a href="<%= sharedLink %><% if (results[i][1] != null) { %>&amp;authority=<%= URLEncoder.encode(results[i][1], "UTF-8") %>" class="authority <%= bix.getName() %>"><%= Utils.addEntities(results[i][0]) %></a> <% } else { %>&amp;value=<%= URLEncoder.encode(results[i][0], "UTF-8") %>"><%= Utils.addEntities(results[i][0]) %></a> <% } %>
</td> </td>
</tr> </tr>
<% <%

Binary file not shown.

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -0,0 +1,28 @@
The following icon files:
- book_key.png
- zoom.png
- bug.png
are taken from
Silk icon set 1.3
_________________________________________
Mark James
http://www.famfamfam.com/lab/icons/silk/
_________________________________________
This work is licensed under a
Creative Commons Attribution 2.5 License.
[ http://creativecommons.org/licenses/by/2.5/ ]
This means you may use it for any purpose,
and make any changes you like.
All I ask is that you include a link back
to this page in your credits.
Are you using this icon set? Send me an email
(including a link or picture if available) to
mjames@gmail.com
Any other questions about this icon set please
contact mjames@gmail.com

Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 587 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 595 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 537 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 588 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

View File

@@ -0,0 +1,46 @@
16x16 Free Application Icons
This icon set is free for use in personal and commercial projects.
License Agreement
By purchasing icons from Aha-Soft, You (the purchaser)
agree to the terms of this agreement, as detailed below.
You may use the icons from Aha-Soft in commercial and
personal design projects, software or Internet products.
Icons can be displayed in documentation, help files, and
advertising materials. You are free to sell and distribute
products and projects using purchased icons without further
royalty fees.
All icon files are provided 'as is'. Aha-Soft cannot be
held liable for any negative issues that may occur as a
result of using the icons.
You agree that all ownership and copyright of the icons
remains the property of Aha-Soft. You may not resell,
distribute, lease, license or sub-license the icons or
modified icons (or a subset of the icons), to any third
party unless they are incorporated into your software or
design products.
If you have any questions regarding copyright or licensing,
including whether another license is required for icon use
within products, please contact us here: www.aha-soft.com/support.htm
Product page: http://www.small-icons.com/stock-icons/16x16-free-application-icons.htm
Icon Design Service
We can design custom icons for you. Please find the basic information
about ordering icons, pricing and the portfolio here:
www.aha-soft.com/customdev/design.htm
Notice
Web-site small-icons.com belongs to Aha-Soft.
Support page: http://www.aha-soft.com/support.htm
Copyright <20> 2009 Aha-Soft. All rights reserved.

Binary file not shown.

After

Width:  |  Height:  |  Size: 904 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

View File

@@ -0,0 +1,51 @@
<%--
-- footer-home.jsp
--
-- Version: $Revision: 3705 $
--
-- Date: $Date: 2009-04-11 13:02:24 -0400 (Sat, 11 Apr 2009) $
--
-- Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
-- Institute of Technology. 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 Hewlett-Packard Company nor the name of the
-- Massachusetts Institute of Technology nor the names of their
-- 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.
--%>
<%--
- Footer for home page
--%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ page contentType="text/html;charset=UTF-8" %>
</body>
</html>

View File

@@ -96,13 +96,18 @@
} }
if (extraHeadData != null) if (extraHeadData != null)
{ %> { %>
<%= extraHeadData %> <%= extraHeadData %>
<% <%
} }
%> %>
<script type="text/javascript" src="<%= request.getContextPath() %>/utils.js"></script> <script type="text/javascript" src="<%= request.getContextPath() %>/utils.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/prototype.js"> </script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/effects.js"> </script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/builder.js"> </script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/controls.js"> </script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/choice-support.js"> </script>
</head> </head>
<%-- HACK: leftmargin, topmargin: for non-CSS compliant Microsoft IE browser --%> <%-- HACK: leftmargin, topmargin: for non-CSS compliant Microsoft IE browser --%>

View File

@@ -0,0 +1,104 @@
<%--
- header-home.jsp
-
- Version: $Revision: 4254 $
-
- Date: $Date: 2009-09-11 11:59:19 -0400 (Fri, 11 Sep 2009) $
-
- Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
- Institute of Technology. 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 Hewlett-Packard Company nor the name of the
- Massachusetts Institute of Technology nor the names of their
- 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.
--%>
<%--
- HTML header for main home page
--%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ page import="java.util.List"%>
<%@ page import="java.util.Enumeration"%>
<%@ page import="org.dspace.app.webui.util.JSPManager" %>
<%@ page import="org.dspace.core.ConfigurationManager" %>
<%@ page import="javax.servlet.jsp.jstl.core.*" %>
<%@ page import="javax.servlet.jsp.jstl.fmt.*" %>
<%
String title = (String) request.getAttribute("dspace.layout.title");
String navbar = (String) request.getAttribute("dspace.layout.navbar");
boolean locbar = ((Boolean) request.getAttribute("dspace.layout.locbar")).booleanValue();
String siteName = ConfigurationManager.getProperty("dspace.name");
String feedRef = (String)request.getAttribute("dspace.layout.feedref");
List parts = (List)request.getAttribute("dspace.layout.linkparts");
String extraHeadData = (String)request.getAttribute("dspace.layout.head");
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title><%= siteName %>: <%= title %></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="Generator" content="DSpace" />
<link rel="stylesheet" href="<%= request.getContextPath() %>/styles.css.jsp" type="text/css" />
<link rel="stylesheet" href="<%= request.getContextPath() %>/print.css" media="print" type="text/css" />
<link rel="shortcut icon" href="<%= request.getContextPath() %>/favicon.ico" type="image/x-icon"/>
<%
if (extraHeadData != null)
{ %>
<%= extraHeadData %>
<%
}
%>
<script type="text/javascript" src="<%= request.getContextPath() %>/utils.js"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/prototype.js"> </script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/effects.js"> </script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/builder.js"> </script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/controls.js"> </script>
<script type="text/javascript" src="<%= request.getContextPath() %>/static/js/choice-support.js"> </script>
</head>
<%-- HACK: leftmargin, topmargin: for non-CSS compliant Microsoft IE browser --%>
<%-- HACK: marginwidth, marginheight: for non-CSS compliant Netscape browser --%>
<body>
<%-- Localization --%>
<%-- <c:if test="${param.locale != null}">--%>
<%-- <fmt:setLocale value="${param.locale}" scope="session" /> --%>
<%-- </c:if> --%>
<%-- <fmt:setBundle basename="Messages" scope="session"/> --%>
<%-- Page contents --%>

View File

@@ -254,7 +254,7 @@ UL { font-family: "verdana", "Arial", "Helvetica", sans-serif;
font-weight: bold } font-weight: bold }
.communityStrength { .communityStrength {
font-family: "verdana", "Arial", "Helvetica", sans-serif; font-family: "verdana", "Arial", "Helvetica", sans-serif;
font-size: 12pt; font-size: 12pt;
font-weight: normal } font-weight: normal }
@@ -621,23 +621,23 @@ UL { font-family: "verdana", "Arial", "Helvetica", sans-serif;
<%-- The following rules are used by the controlled-vocabulary add-on --%> <%-- The following rules are used by the controlled-vocabulary add-on --%>
ul.controlledvocabulary { ul.controlledvocabulary {
list-style-type:none; } list-style-type:none; }
.controlledvocabulary ul li ul { .controlledvocabulary ul li ul {
list-style-type:none; list-style-type:none;
display:none; } display:none; }
input.controlledvocabulary { input.controlledvocabulary {
border:0px; } border:0px; }
img.controlledvocabulary { img.controlledvocabulary {
margin-right:8px ! important; margin-right:8px ! important;
margin-left:11px ! important; margin-left:11px ! important;
cursor:hand; } cursor:hand; }
.submitFormHelpControlledVocabularies { .submitFormHelpControlledVocabularies {
margin-left: 10px; margin-left: 10px;
margin-right: 10px; margin-right: 10px;
font-family: "verdana", "Arial", "Helvetica", sans-serif; font-family: "verdana", "Arial", "Helvetica", sans-serif;
font-size: 8pt; font-size: 8pt;
@@ -649,23 +649,126 @@ img.controlledvocabulary {
.browse_buttons .browse_buttons
{ {
float: right; float: right;
padding: 1px; padding: 1px;
margin: 1px; margin: 1px;
} }
#browse_navigation #browse_navigation
{ {
margin-bottom: 10px; margin-bottom: 10px;
} }
#browse_controls #browse_controls
{ {
margin-bottom: 10px; margin-bottom: 10px;
} }
.browse_range .browse_range
{ {
margin-top: 5px; margin-top: 5px;
margin-bottom: 5px; margin-bottom: 5px;
} }
<%-- styles added by authority control --%>
div.autocomplete {
background-color:white;
border:1px solid #888888;
margin:0;
padding:0;
position:absolute;
width:250px;
}
div.autocomplete ul {
list-style-type:none;
margin:0;
padding:0;
}
div.autocomplete ul li {
cursor:pointer;
}
div.autocomplete ul li.selected {
text-decoration: underline;
}
div.autocomplete ul li:hover {
text-decoration: underline;
}
div.autocomplete ul li span.value {
display:none;
}
/* this magic gets the 16x16 icon to show up.. setting height/width didn't
do it, but adding padding actually made it show up. */
img.ds-authority-confidence,
span.ds-authority-confidence
{ width: 16px; height: 16px; margin: 5px; background-repeat: no-repeat;
padding: 0px 2px; vertical-align: bottom; color: transparent;}
img.ds-authority-confidence.cf-unset,
span.ds-authority-confidence.cf-unset
{ background-image: url(<%= request.getContextPath() %>/image/authority/bug.png);}
img.ds-authority-confidence.cf-novalue,
span.ds-authority-confidence.cf-novalue
{ background-image: url(<%= request.getContextPath() %>/image/confidence/0-unauthored.gif);}
img.ds-authority-confidence.cf-rejected,
img.ds-authority-confidence.cf-failed,
span.ds-authority-confidence.cf-rejected,
span.ds-authority-confidence.cf-failed
{ background-image: url(<%= request.getContextPath() %>/image/confidence/2-errortriangle.gif); }
img.ds-authority-confidence.cf-notfound,
span.ds-authority-confidence.cf-notfound
{ background-image: url(<%= request.getContextPath() %>/image/confidence/3-thumb1.gif); }
img.ds-authority-confidence.cf-ambiguous,
span.ds-authority-confidence.cf-ambiguous
{ background-image: url(<%= request.getContextPath() %>/image/confidence/4-question.gif); }
img.ds-authority-confidence.cf-uncertain,
span.ds-authority-confidence.cf-uncertain
{ background-image: url(<%= request.getContextPath() %>/image/confidence/5-pinion.gif); }
img.ds-authority-confidence.cf-accepted,
span.ds-authority-confidence.cf-accepted
{ background-image: url(<%= request.getContextPath() %>/image/confidence/6-greencheck.gif); }
/* hide authority-value inputs in forms */
input.ds-authority-value { display:none; }
/** XXX Change to this to get the authority value to show up for debugging:
input.ds-authority-value { display:inline; }
**/
/* ..except, show authority-value inputs in on the Item EditMetadata page */
table.miscTable input.ds-authority-value { display: inline; }
table.authority-statistics {padding: 5px; margin-bottom: 15px;}
table.authority-statistics table {float: left; text-align: center;}
div.authority-key-nav-link, div.authority-page-nav-link {margin-top: 20px;}
div#authority-message {
width: 80%;
display:block;
text-align: center;
margin-left: 10%;
padding: 10px;
border: 1px dashed #FFCC00;
background-color: #FFF4C8;
}
a.authority {
background: transparent url(<%= request.getContextPath() %>/image/authority/book_key.png) no-repeat;
background-position: top right;
padding-right: 20px;
}
/* for edit-item-form lock button */
input.ds-authority-lock
{ vertical-align: bottom; height: 24px; width: 24px; margin-right: 8px;
background-repeat: no-repeat; background-color: transparent; }
input.ds-authority-lock.is-locked
{ background-image: url(<%= request.getContextPath() %>/image/lock24.png); }
input.ds-authority-lock.is-unlocked
{ background-image: url(<%= request.getContextPath() %>/image/unlock24.png); }

View File

@@ -56,6 +56,7 @@
<%@ page import="org.dspace.content.InProgressSubmission" %> <%@ page import="org.dspace.content.InProgressSubmission" %>
<%@ page import="org.dspace.app.webui.util.UIUtil" %> <%@ page import="org.dspace.app.webui.util.UIUtil" %>
<%@ page import="org.dspace.app.util.DCInputsReader" %> <%@ page import="org.dspace.app.util.DCInputsReader" %>
<%@ page import="org.dspace.app.util.DCInputsReaderException" %>
<%@ page import="org.dspace.app.util.DCInputSet" %> <%@ page import="org.dspace.app.util.DCInputSet" %>
<%@ page import="org.dspace.app.util.DCInput" %> <%@ page import="org.dspace.app.util.DCInput" %>
<%@ page import="org.dspace.content.Collection" %> <%@ page import="org.dspace.content.Collection" %>
@@ -66,6 +67,8 @@
<%@ page import="org.dspace.core.Context" %> <%@ page import="org.dspace.core.Context" %>
<%@ page import="org.dspace.core.Utils" %> <%@ page import="org.dspace.core.Utils" %>
<%@ page import="org.dspace.content.authority.MetadataAuthorityManager" %>
<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %>
<%@ page import="javax.servlet.jsp.PageContext" %> <%@ page import="javax.servlet.jsp.PageContext" %>
@@ -79,28 +82,37 @@
// Obtain DSpace context // Obtain DSpace context
Context context = UIUtil.obtainContext(request); Context context = UIUtil.obtainContext(request);
//get submission information object //get submission information object
SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request);
//get the step number (for jump-to link and to determine page) //get the step number (for jump-to link and to determine page)
String stepJump = (String) request.getParameter("submission.jump"); String stepJump = (String) request.getParameter("submission.jump");
//extract out the step & page numbers from the stepJump (format: stepNum.pageNum) //extract out the step & page numbers from the stepJump (format: stepNum.pageNum)
//(since there are multiple pages, we need to know which page we are reviewing!) //(since there are multiple pages, we need to know which page we are reviewing!)
String[] fields = stepJump.split("\\."); //split on period String[] fields = stepJump.split("\\."); //split on period
int stepNum = Integer.parseInt(fields[0]); int stepNum = Integer.parseInt(fields[0]);
int pageNum = Integer.parseInt(fields[1]); int pageNum = Integer.parseInt(fields[1]);
Item item = subInfo.getSubmissionItem().getItem(); Item item = subInfo.getSubmissionItem().getItem();
//get the inputs reader // determine collection
DCInputsReader inputsReader = DescribeStep.getInputsReader();
// determine collection
Collection c = subInfo.getSubmissionItem().getCollection(); Collection c = subInfo.getSubmissionItem().getCollection();
//load the input set for the current collection DCInputSet inputSet = null;
DCInputSet inputSet = inputsReader.getInputs(c.getHandle());
try
{
//get the inputs reader
DCInputsReader inputsReader = DescribeStep.getInputsReader();
//load the input set for the current collection
inputSet = inputsReader.getInputs(c.getHandle());
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
%> %>
<%!void layoutSection(HttpServletRequest request, <%!void layoutSection(HttpServletRequest request,
@@ -114,10 +126,14 @@
{ {
InProgressSubmission ip = subInfo.getSubmissionItem(); InProgressSubmission ip = subInfo.getSubmissionItem();
//need to actually get the rows for pageNum-1 (since first page is index 0) //need to actually get the rows for pageNum-1 (since first page is index 0)
DCInput[] inputs = inputSet.getPageRows(pageNum-1, DCInput[] inputs = inputSet.getPageRows(pageNum-1,
ip.hasMultipleTitles(), ip.hasMultipleTitles(),
ip.isPublishedBefore()); ip.isPublishedBefore());
MetadataAuthorityManager mam = MetadataAuthorityManager.getManager();
for (int z = 0; z < inputs.length; z++) for (int z = 0; z < inputs.length; z++)
{ {
String scope = subInfo.isInWorkflow() ? DCInput.WORKFLOW_SCOPE : DCInput.SUBMISSION_SCOPE; String scope = subInfo.isInWorkflow() ? DCInput.WORKFLOW_SCOPE : DCInput.SUBMISSION_SCOPE;
@@ -151,6 +167,9 @@
} }
else else
{ {
boolean isAuthorityControlled = mam.isAuthorityControlled(inputs[z].getSchema(),
inputs[z].getElement(),inputs[z].getQualifier());
for (int i = 0; i < values.length; i++) for (int i = 0; i < values.length; i++)
{ {
boolean newline = true; boolean newline = true;
@@ -200,7 +219,12 @@
{ {
row.append(Utils.addEntities(values[i].value)); row.append(Utils.addEntities(values[i].value));
} }
if (isAuthorityControlled)
{
row.append("<span class=\"ds-authority-confidence cf-")
.append(values[i].confidence).append("\">")
.append(" </span>");
}
if (newline) if (newline)
{ {
row.append("<br />"); row.append("<br />");
@@ -225,12 +249,12 @@
<table width="700px"> <table width="700px">
<% <%
layoutSection(request, out, inputSet, subInfo, item, pageNum, pageContext); layoutSection(request, out, inputSet, subInfo, item, pageNum, pageContext);
%> %>
</table> </table>
</td> </td>
<td valign="middle"> <td valign="middle">
<input type="submit" name="submit_jump_<%=stepJump%>" value="<fmt:message key="jsp.submit.review.button.correct"/>" /> <input type="submit" name="submit_jump_<%=stepJump%>" value="<fmt:message key="jsp.submit.review.button.correct"/>" />
</td> </td>
</tr> </tr>
</table> </table>

View File

@@ -75,6 +75,9 @@
<%@ page import="org.dspace.core.ConfigurationManager" %> <%@ page import="org.dspace.core.ConfigurationManager" %>
<%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.eperson.EPerson" %>
<%@ page import="org.dspace.core.Utils" %> <%@ page import="org.dspace.core.Utils" %>
<%@ page import="org.dspace.content.authority.MetadataAuthorityManager" %>
<%@ page import="org.dspace.content.authority.ChoiceAuthorityManager" %>
<%@ page import="org.dspace.content.authority.Choices" %>
<% <%
Item item = (Item) request.getAttribute("item"); Item item = (Item) request.getAttribute("item");
@@ -111,8 +114,96 @@
Boolean reinstate = (Boolean)request.getAttribute("reinstate_button"); Boolean reinstate = (Boolean)request.getAttribute("reinstate_button");
boolean bReinstate = (reinstate == null ? false : reinstate.booleanValue()); boolean bReinstate = (reinstate == null ? false : reinstate.booleanValue());
%>
// owning Collection ID for choice authority calls
int collectionID = -1;
if (collections.length > 0)
collectionID = collections[0].getID();
%>
<%!
StringBuffer doAuthority(MetadataAuthorityManager mam, ChoiceAuthorityManager cam,
PageContext pageContext,
String contextPath, String fieldName, String idx,
DCValue dcv, int collectionID)
{
StringBuffer sb = new StringBuffer();
if (cam.isChoicesConfigured(fieldName))
{
boolean authority = mam.isAuthorityControlled(fieldName);
boolean required = authority && mam.isAuthorityRequired(fieldName);
String fieldNameIdx = "value_" + fieldName + "_" + idx;
String authorityName = "choice_" + fieldName + "_authority_" + idx;
String confidenceName = "choice_" + fieldName + "_confidence_" + idx;
// put up a SELECT element containing all choices
if ("select".equals(cam.getPresentation(fieldName)))
{
sb.append("<select id=\"").append(fieldNameIdx)
.append("\" name=\"").append(fieldNameIdx)
.append("\" size=\"1\">");
Choices cs = cam.getMatches(fieldName, dcv.value, collectionID, 0, 0, null);
if (cs.defaultSelected < 0)
sb.append("<option value=\"").append(dcv.value).append("\" selected>")
.append(dcv.value).append("</option>\n");
for (int i = 0; i < cs.values.length; ++i)
{
sb.append("<option value=\"").append(cs.values[i].value).append("\"")
.append(i == cs.defaultSelected ? " selected>":">")
.append(cs.values[i].label).append("</option>\n");
}
sb.append("</select>\n");
}
// use lookup for any other presentation style (i.e "select")
else
{
String confidenceIndicator = "indicator_"+confidenceName;
sb.append("<textarea id=\"").append(fieldNameIdx).append("\" name=\"").append(fieldNameIdx)
.append("\" rows=\"3\" cols=\"50\">")
.append(dcv.value).append("</textarea>\n<br/>\n");
if (authority)
{
String confidenceSymbol = Choices.getConfidenceText(dcv.confidence).toLowerCase();
sb.append("<img id=\""+confidenceIndicator+"\" title=\"")
.append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.authority.confidence.description."+confidenceSymbol))
.append("\" class=\"ds-authority-confidence cf-"+ confidenceSymbol)
.append("\" src=\"").append(contextPath).append("/image/confidence/invisible.gif\" />")
.append("<input type=\"text\" readonly value=\"")
.append(dcv.authority != null ? dcv.authority : "")
.append("\" id=\"").append(authorityName)
.append("\" onChange=\"javascript: return DSpaceAuthorityOnChange(this, '")
.append(confidenceName).append("','").append(confidenceIndicator)
.append("');\" name=\"").append(authorityName).append("\" class=\"ds-authority-value ds-authority-visible \"/>")
.append("<input type=\"image\" class=\"ds-authority-lock is-locked \" ")
.append(" src=\"").append(contextPath).append("/image/confidence/invisible.gif\" ")
.append(" onClick=\"javascript: return DSpaceToggleAuthorityLock(this, '").append(authorityName).append("');\" ")
.append(" title=\"")
.append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.edit-item-form.unlock"))
.append("\" >")
.append("<input type=\"hidden\" value=\"").append(confidenceSymbol).append("\" id=\"").append(confidenceName)
.append("\" name=\"").append(confidenceName)
.append("\" class=\"ds-authority-confidence-input\"/>");
}
sb.append("<input type=\"image\" name=\"").append(fieldNameIdx).append("_lookup\" ")
.append("onclick=\"javascript: return DSpaceChoiceLookup('")
.append(contextPath).append("/tools/lookup.jsp','")
.append(fieldName).append("','edit_metadata','")
.append(fieldNameIdx).append("','").append(authorityName).append("','")
.append(confidenceIndicator).append("',")
.append(String.valueOf(collectionID)).append(",")
.append("false").append(",false);\"")
.append(" title=\"")
.append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.lookup"))
.append("\" width=\"16px\" height=\"16px\" src=\""+contextPath+"/image/authority/zoom.png\" />");
}
}
return sb;
}
%>
<dspace:layout titlekey="jsp.tools.edit-item-form.title" <dspace:layout titlekey="jsp.tools.edit-item-form.title"
navbar="admin" navbar="admin"
@@ -122,21 +213,21 @@
nocache="true"> nocache="true">
<%-- <h1>Edit Item</h1> --%> <%-- <h1>Edit Item</h1> --%>
<h1><fmt:message key="jsp.tools.edit-item-form.title"/></h1> <h1><fmt:message key="jsp.tools.edit-item-form.title"/></h1>
<%-- <p><strong>PLEASE NOTE: These changes are not validated in any way. <%-- <p><strong>PLEASE NOTE: These changes are not validated in any way.
You are responsible for entering the data in the correct format. You are responsible for entering the data in the correct format.
If you are not sure what the format is, please do NOT make changes.</strong></p> --%> If you are not sure what the format is, please do NOT make changes.</strong></p> --%>
<p><strong><fmt:message key="jsp.tools.edit-item-form.note"/></strong></p> <p><strong><fmt:message key="jsp.tools.edit-item-form.note"/></strong></p>
<%-- <p><dspace:popup page="/help/collection-admin.html#editmetadata">More help...</dspace:popup></p> --%> <%-- <p><dspace:popup page="/help/collection-admin.html#editmetadata">More help...</dspace:popup></p> --%>
<div><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.collection-admin\") + \"#editmetadata\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> <div><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.collection-admin\") + \"#editmetadata\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div>
<center> <center>
<table width="70%" summary="Edit item table"> <table width="70%" summary="Edit item table">
<tr> <tr>
<%-- <td class="submitFormLabel">Item&nbsp;internal&nbsp;ID:</td> --%> <%-- <td class="submitFormLabel">Item&nbsp;internal&nbsp;ID:</td> --%>
<td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.itemID"/></td> <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.itemID"/></td>
<td class="standard"><%= item.getID() %></td> <td class="standard"><%= item.getID() %></td>
<td class="standard" width="100%" align="right" rowspan="5"> <td class="standard" width="100%" align="right" rowspan="5">
<% <%
@@ -147,7 +238,7 @@
<input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="item_id" value="<%= item.getID() %>" />
<input type="hidden" name="action" value="<%= EditItemServlet.START_WITHDRAW %>" /> <input type="hidden" name="action" value="<%= EditItemServlet.START_WITHDRAW %>" />
<%-- <input type="submit" name="submit" value="Withdraw..."> --%> <%-- <input type="submit" name="submit" value="Withdraw..."> --%>
<input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.withdraw-w-confirm.button"/>"/> <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.withdraw-w-confirm.button"/>"/>
</form> </form>
<% <%
} }
@@ -158,7 +249,7 @@
<input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="item_id" value="<%= item.getID() %>" />
<input type="hidden" name="action" value="<%= EditItemServlet.REINSTATE %>" /> <input type="hidden" name="action" value="<%= EditItemServlet.REINSTATE %>" />
<%-- <input type="submit" name="submit" value="Reinstate"> --%> <%-- <input type="submit" name="submit" value="Reinstate"> --%>
<input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.reinstate.button"/>"/> <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.reinstate.button"/>"/>
</form> </form>
<% <%
} }
@@ -173,7 +264,7 @@
<input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="item_id" value="<%= item.getID() %>" />
<input type="hidden" name="action" value="<%= EditItemServlet.START_DELETE %>" /> <input type="hidden" name="action" value="<%= EditItemServlet.START_DELETE %>" />
<%-- <input type="submit" name="submit" value="Delete (Expunge)..."> --%> <%-- <input type="submit" name="submit" value="Delete (Expunge)..."> --%>
<input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.delete-w-confirm.button"/>"/> <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.delete-w-confirm.button"/>"/>
</form> </form>
<% <%
} }
@@ -183,7 +274,7 @@
%> <form method="post" action="<%= request.getContextPath() %>/tools/edit-item"> %> <form method="post" action="<%= request.getContextPath() %>/tools/edit-item">
<input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="item_id" value="<%= item.getID() %>" />
<input type="hidden" name="action" value="<%= EditItemServlet.START_MOVE_ITEM %>" /> <input type="hidden" name="action" value="<%= EditItemServlet.START_MOVE_ITEM %>" />
<input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.move-item.button"/>"/> <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.move-item.button"/>"/>
</form> </form>
<% <%
} }
@@ -192,17 +283,17 @@
</tr> </tr>
<tr> <tr>
<%-- <td class="submitFormLabel">Handle:</td> --%> <%-- <td class="submitFormLabel">Handle:</td> --%>
<td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.handle"/></td> <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.handle"/></td>
<td class="standard"><%= (handle == null ? "None" : handle) %></td> <td class="standard"><%= (handle == null ? "None" : handle) %></td>
</tr> </tr>
<tr> <tr>
<%-- <td class="submitFormLabel">Last modified:</td> --%> <%-- <td class="submitFormLabel">Last modified:</td> --%>
<td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.modified"/></td> <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.modified"/></td>
<td class="standard"><dspace:date date="<%= new DCDate(item.getLastModified()) %>" /></td> <td class="standard"><dspace:date date="<%= new DCDate(item.getLastModified()) %>" /></td>
</tr> </tr>
<tr> <tr>
<%-- <td class="submitFormLabel">In Collections:</td> --%> <%-- <td class="submitFormLabel">In Collections:</td> --%>
<td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.collections"/></td> <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.collections"/></td>
<td class="standard"> <td class="standard">
<% for (int i = 0; i < collections.length; i++) { %> <% for (int i = 0; i < collections.length; i++) { %>
<%= collections[i].getMetadata("name") %><br/> <%= collections[i].getMetadata("name") %><br/>
@@ -212,7 +303,7 @@
<tr> <tr>
<%-- <td class="submitFormLabel">Item page:</td> --%> <%-- <td class="submitFormLabel">Item page:</td> --%>
<td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.itempage"/></td> <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.itempage"/></td>
<td class="standard"> <td class="standard">
<% if (handle == null) { %> <% if (handle == null) { %>
<em><fmt:message key="jsp.tools.edit-item-form.na"/></em> <em><fmt:message key="jsp.tools.edit-item-form.na"/></em>
@@ -231,13 +322,13 @@
=========================================================== --%> =========================================================== --%>
<tr> <tr>
<%-- <td class="submitFormLabel">Item's Authorizations:</td> --%> <%-- <td class="submitFormLabel">Item's Authorizations:</td> --%>
<td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.item"/></td> <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.item"/></td>
<td> <td>
<form method="post" action="<%= request.getContextPath() %>/tools/authorize"> <form method="post" action="<%= request.getContextPath() %>/tools/authorize">
<input type="hidden" name="handle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>" /> <input type="hidden" name="handle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>" />
<input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="item_id" value="<%= item.getID() %>" />
<%-- <input type="submit" name="submit_item_select" value="Edit..."> --%> <%-- <input type="submit" name="submit_item_select" value="Edit..."> --%>
<input type="submit" name="submit_item_select" value="<fmt:message key="jsp.tools.general.edit"/>"/> <input type="submit" name="submit_item_select" value="<fmt:message key="jsp.tools.general.edit"/>"/>
</form> </form>
</td> </td>
</tr> </tr>
@@ -253,14 +344,14 @@
{ {
%> %>
<%-- <p align="center"><strong>This item was withdrawn from DSpace</strong></p> --%> <%-- <p align="center"><strong>This item was withdrawn from DSpace</strong></p> --%>
<p align="center"><strong><fmt:message key="jsp.tools.edit-item-form.msg"/></strong></p> <p align="center"><strong><fmt:message key="jsp.tools.edit-item-form.msg"/></strong></p>
<% <%
} }
%> %>
<p>&nbsp;</p> <p>&nbsp;</p>
<form method="post" action="<%= request.getContextPath() %>/tools/edit-item"> <form id="edit_metadata" name="edit_metadata" method="post" action="<%= request.getContextPath() %>/tools/edit-item">
<table class="miscTable" summary="Edit item withdrawn table"> <table class="miscTable" summary="Edit item withdrawn table">
<tr> <tr>
<%-- <th class="oddRowOddCol"><strong>Element</strong></th> <%-- <th class="oddRowOddCol"><strong>Element</strong></th>
@@ -276,6 +367,8 @@
<th id="t5" class="oddRowEvenCol">&nbsp;</th> <th id="t5" class="oddRowEvenCol">&nbsp;</th>
</tr> </tr>
<% <%
MetadataAuthorityManager mam = MetadataAuthorityManager.getManager();
ChoiceAuthorityManager cam = ChoiceAuthorityManager.getManager();
DCValue[] dcv = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); DCValue[] dcv = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
String row = "even"; String row = "even";
@@ -288,8 +381,7 @@
{ {
// Find out how many values with this element/qualifier we've found // Find out how many values with this element/qualifier we've found
String key = dcv[i].schema + "_" + dcv[i].element + String key = ChoiceAuthorityManager.makeFieldKey(dcv[i].schema, dcv[i].element, dcv[i].qualifier);
(dcv[i].qualifier == null ? "" : "_" + dcv[i].qualifier);
Integer count = (Integer) dcCounter.get(key); Integer count = (Integer) dcCounter.get(key);
if (count == null) if (count == null)
@@ -316,14 +408,24 @@
<td headers="t1" class="<%= row %>RowEvenCol"><%= dcv[i].element %>&nbsp;&nbsp;</td> <td headers="t1" class="<%= row %>RowEvenCol"><%= dcv[i].element %>&nbsp;&nbsp;</td>
<td headers="t2" class="<%= row %>RowOddCol"><%= (dcv[i].qualifier == null ? "" : dcv[i].qualifier) %></td> <td headers="t2" class="<%= row %>RowOddCol"><%= (dcv[i].qualifier == null ? "" : dcv[i].qualifier) %></td>
<td headers="t3" class="<%= row %>RowEvenCol"> <td headers="t3" class="<%= row %>RowEvenCol">
<textarea name="value_<%= key %>_<%= sequenceNumber %>" rows="3" cols="50"><%= Utils.addEntities(dcv[i].value) %></textarea> <%
if (cam.isChoicesConfigured(key))
{
%>
<%=
doAuthority(mam, cam, pageContext, request.getContextPath(), key, sequenceNumber,
dcv[i], collectionID).toString()
%>
<% } else { %>
<textarea id="value_<%= key %>_<%= sequenceNumber %>" name="value_<%= key %>_<%= sequenceNumber %>" rows="3" cols="50"><%= dcv[i].value %></textarea>
<% } %>
</td> </td>
<td headers="t4" class="<%= row %>RowOddCol"> <td headers="t4" class="<%= row %>RowOddCol">
<input type="text" name="language_<%= key %>_<%= sequenceNumber %>" value="<%= (dcv[i].language == null ? "" : dcv[i].language) %>" size="5"/> <input type="text" name="language_<%= key %>_<%= sequenceNumber %>" value="<%= (dcv[i].language == null ? "" : dcv[i].language) %>" size="5"/>
</td> </td>
<td headers="t5" class="<%= row %>RowEvenCol"> <td headers="t5" class="<%= row %>RowEvenCol">
<%-- <input type="submit" name="submit_remove_<%= key %>_<%= sequenceNumber %>" value="Remove" /> --%> <%-- <input type="submit" name="submit_remove_<%= key %>_<%= sequenceNumber %>" value="Remove" /> --%>
<input type="submit" name="submit_remove_<%= key %>_<%= sequenceNumber %>" value="<fmt:message key="jsp.tools.general.remove"/>"/> <input type="submit" name="submit_remove_<%= key %>_<%= sequenceNumber %>" value="<fmt:message key="jsp.tools.general.remove"/>"/>
</td> </td>
</tr> </tr>
<% row = (row.equals("odd") ? "even" : "odd"); <% row = (row.equals("odd") ? "even" : "odd");
@@ -337,8 +439,8 @@
<select name="addfield_dctype"> <select name="addfield_dctype">
<% for (int i = 0; i < dcTypes.length; i++) <% for (int i = 0; i < dcTypes.length; i++)
{ {
Integer fieldID = new Integer(dcTypes[i].getFieldID()); Integer fieldID = new Integer(dcTypes[i].getFieldID());
String displayName = (String)metadataFields.get(fieldID); String displayName = (String)metadataFields.get(fieldID);
%> %>
<option value="<%= fieldID.intValue() %>"><%= displayName %></option> <option value="<%= fieldID.intValue() %>"><%= displayName %></option>
<% } %> <% } %>
@@ -352,7 +454,7 @@
</td> </td>
<td headers="t5" class="<%= row %>RowOddCol"> <td headers="t5" class="<%= row %>RowOddCol">
<%-- <input type="submit" name="submit_addfield" value="Add"> --%> <%-- <input type="submit" name="submit_addfield" value="Add"> --%>
<input type="submit" name="submit_addfield" value="<fmt:message key="jsp.tools.general.add"/>"/> <input type="submit" name="submit_addfield" value="<fmt:message key="jsp.tools.general.add"/>"/>
</td> </td>
</tr> </tr>
</table> </table>
@@ -360,23 +462,23 @@
<p>&nbsp;</p> <p>&nbsp;</p>
<%-- <h2>Bitstreams</h2> --%> <%-- <h2>Bitstreams</h2> --%>
<h2><fmt:message key="jsp.tools.edit-item-form.heading"/></h2> <h2><fmt:message key="jsp.tools.edit-item-form.heading"/></h2>
<%-- <p>Note that if the "user format description" field isn't empty, the format will <%-- <p>Note that if the "user format description" field isn't empty, the format will
always be set to "Unknown", so clear the user format description before changing the always be set to "Unknown", so clear the user format description before changing the
format field.</p> --%> format field.</p> --%>
<p><fmt:message key="jsp.tools.edit-item-form.note3"/></p> <p><fmt:message key="jsp.tools.edit-item-form.note3"/></p>
<table class="miscTable" summary="Bitstream data table"> <table class="miscTable" summary="Bitstream data table">
<tr> <tr>
<%-- <th class="oddRowEvenCol"><strong>Primary<br>Bitstream</strong></th> <%-- <th class="oddRowEvenCol"><strong>Primary<br>Bitstream</strong></th>
<th class="oddRowOddCol"><strong>Name</strong></th> <th class="oddRowOddCol"><strong>Name</strong></th>
<th class="oddRowEvenCol"><strong>Source</strong></th> <th class="oddRowEvenCol"><strong>Source</strong></th>
<th class="oddRowOddCol"><strong>Description</strong></th> <th class="oddRowOddCol"><strong>Description</strong></th>
<th class="oddRowEvenCol"><strong>Format</strong></th> <th class="oddRowEvenCol"><strong>Format</strong></th>
<th class="oddRowOddCol"><strong>User&nbsp;Format&nbsp;Description</strong></th> --%> <th class="oddRowOddCol"><strong>User&nbsp;Format&nbsp;Description</strong></th> --%>
<th id="t11" class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem5"/></strong></th> <th id="t11" class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem5"/></strong></th>
<th id="t12" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem7"/></strong></th> <th id="t12" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem7"/></strong></th>
<th id="t13" class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem8"/></strong></th> <th id="t13" class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem8"/></strong></th>
<th id="t14" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem9"/></strong></th> <th id="t14" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem9"/></strong></th>
@@ -399,17 +501,17 @@
BitstreamFormat bf = bitstreams[j].getFormat(); BitstreamFormat bf = bitstreams[j].getFormat();
%> %>
<tr> <tr>
<% if (bundles[i].getName().equals("ORIGINAL")) <% if (bundles[i].getName().equals("ORIGINAL"))
{ %> { %>
<td headers="t11" class="<%= row %>RowEvenCol" align="center"> <td headers="t11" class="<%= row %>RowEvenCol" align="center">
<input type="radio" name="<%= bundles[i].getID() %>_primary_bitstream_id" value="<%= bitstreams[j].getID() %>" <input type="radio" name="<%= bundles[i].getID() %>_primary_bitstream_id" value="<%= bitstreams[j].getID() %>"
<% if (bundles[i].getPrimaryBitstreamID() == bitstreams[j].getID()) { %> <% if (bundles[i].getPrimaryBitstreamID() == bitstreams[j].getID()) { %>
checked="<%="checked" %>" checked="<%="checked" %>"
<% } %> /> <% } %> />
</td> </td>
<% } else { %> <% } else { %>
<td headers="t11"> </td> <td headers="t11"> </td>
<% } %> <% } %>
<td headers="t12" class="<%= row %>RowOddCol"> <td headers="t12" class="<%= row %>RowOddCol">
<input type="text" name="bitstream_name_<%= key %>" value="<%= (bitstreams[j].getName() == null ? "" : Utils.addEntities(bitstreams[j].getName())) %>"/> <input type="text" name="bitstream_name_<%= key %>" value="<%= (bitstreams[j].getName() == null ? "" : Utils.addEntities(bitstreams[j].getName())) %>"/>
</td> </td>
@@ -427,10 +529,10 @@
</td> </td>
<td headers="t17" class="<%= row %>RowEvenCol"> <td headers="t17" class="<%= row %>RowEvenCol">
<%-- <a target="_blank" href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[j].getID() %>">View</a>&nbsp;<input type="submit" name="submit_delete_bitstream_<%= key %>" value="Remove"> --%> <%-- <a target="_blank" href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[j].getID() %>">View</a>&nbsp;<input type="submit" name="submit_delete_bitstream_<%= key %>" value="Remove"> --%>
<a target="_blank" href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[j].getID() %>"><fmt:message key="jsp.tools.general.view"/></a>&nbsp; <a target="_blank" href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[j].getID() %>"><fmt:message key="jsp.tools.general.view"/></a>&nbsp;
<% if (bRemoveBits) { %> <% if (bRemoveBits) { %>
<input type="submit" name="submit_delete_bitstream_<%= key %>" value="<fmt:message key="jsp.tools.general.remove"/>" /> <input type="submit" name="submit_delete_bitstream_<%= key %>" value="<fmt:message key="jsp.tools.general.remove"/>" />
<% } %> <% } %>
</td> </td>
</tr> </tr>
<% <%
@@ -447,23 +549,23 @@
<table width="70%" align="center"> <table width="70%" align="center">
<tr> <tr>
<td> <td>
<% <%
if (bCreateBits) { if (bCreateBits) {
%> %>
<input type="submit" name="submit_addbitstream" value="<fmt:message key="jsp.tools.edit-item-form.addbit.button"/>"/> <input type="submit" name="submit_addbitstream" value="<fmt:message key="jsp.tools.edit-item-form.addbit.button"/>"/>
<% } <% }
if (ConfigurationManager.getBooleanProperty("webui.submit.enable-cc") && bccLicense) if (ConfigurationManager.getBooleanProperty("webui.submit.enable-cc") && bccLicense)
{ {
String s; String s;
Bundle[] ccBundle = item.getBundles("CC-LICENSE"); Bundle[] ccBundle = item.getBundles("CC-LICENSE");
s = ccBundle.length > 0 ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.edit-item-form.replacecc.button") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.edit-item-form.addcc.button"); s = ccBundle.length > 0 ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.edit-item-form.replacecc.button") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.edit-item-form.addcc.button");
%> %>
<input type="submit" name="submit_addcc" value="<%= s %>" /> <input type="submit" name="submit_addcc" value="<%= s %>" />
<input type="hidden" name="handle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>"/> <input type="hidden" name="handle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>"/>
<input type="hidden" name="item_id" value="<%= item.getID() %>"/> <input type="hidden" name="item_id" value="<%= item.getID() %>"/>
<% <%
} }
%> %>
</td> </td>
</tr> </tr>
@@ -479,12 +581,12 @@
<tr> <tr>
<td align="left"> <td align="left">
<%-- <input type="submit" name="submit" value="Update" /> --%> <%-- <input type="submit" name="submit" value="Update" /> --%>
<input type="submit" name="submit" value="<fmt:message key="jsp.tools.general.update"/>" /> <input type="submit" name="submit" value="<fmt:message key="jsp.tools.general.update"/>" />
</td> </td>
<td align="right"> <td align="right">
<%-- <input type="submit" name="submit_cancel" value="Cancel" /> --%> <%-- <input type="submit" name="submit_cancel" value="Cancel" /> --%>
<input type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.general.cancel"/>" /> <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.general.cancel"/>" />
</td> </td>
</tr> </tr>
</table> </table>

View File

@@ -0,0 +1,174 @@
<%--
- lookup.jsp
-
- Version: $Revision: 3705 $
-
- Date: $Date: 2009-04-11 13:02:24 -0400 (Sat, 11 Apr 2009) $
-
- Copyright (c) 2002, Hewlett-Packard Company and Massachusetts
- Institute of Technology. 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 Hewlett-Packard Company nor the name of the
- Massachusetts Institute of Technology nor the names of their
- 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.
--%>
<%--
- Form requesting a Handle or internal item ID for item editing
-
- Attributes:
- invalid.id - if this attribute is present, display error msg
--%>
<%@ page contentType="text/html;charset=UTF-8" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"
prefix="fmt" %>
<%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %>
<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %>
<%@ page import="javax.servlet.http.HttpServletRequest" %>
<%@ page import="javax.servlet.jsp.tagext.TagSupport" %>
<%@ page import="javax.servlet.jsp.PageContext" %>
<%@ page import="javax.servlet.ServletException" %>
<%@ page import="org.dspace.core.ConfigurationManager" %>
<%-- invoke "popup" style which elides all the header and footer stuff.
--%>
<%!
// get request parameter but return a default value if not present.
String getDefaultedRequestParameter(HttpServletRequest r, String param, String dflt)
{
String result = r.getParameter(param);
return (result == null) ? dflt : result;
}
%>
<%
String mdfield = getDefaultedRequestParameter(request,"field", "FieldMissing");
String isNameValue = getDefaultedRequestParameter(request,"isName", "false");
String isRepeatingValue = getDefaultedRequestParameter(request,"isRepeating", "false");
boolean isName = isNameValue.equalsIgnoreCase("true");
boolean isRepeating = isRepeatingValue.equalsIgnoreCase("true");
%>
<dspace:layout titlekey="jsp.tools.lookup.title"
style="popup"
navbar="off"
locbar="off"
parenttitlekey="jsp.administer"
parentlink="/dspace-admin">
<h1><%= LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.field."+mdfield+".title") %></h1>
<form id="aspect_general_ChoiceLookupTransformer_div_lookup"
class="ds-interactive-div popup" action="" method="get">
<fieldset id="aspect_general_ChoiceLookupTransformer_list_choicesList"
class="ds-form-list choices-lookup">
<%-- Results @1@ to @2@ of @3@ for "@4@" --%>
<legend><fmt:message key="jsp.tools.lookup.results"/></legend>
<ol>
<li id="aspect_general_ChoiceLookupTransformer_item_select" class="ds-form-item choices-lookup"> 
<div class="ds-form-content">
<div>
<select onChange="javascript:DSpaceChoicesSelectOnChange();" id="aspect_general_ChoiceLookupTransformer_field_chooser" class="ds-select-field choices-lookup" name="chooser"
size="<%= String.valueOf(ConfigurationManager.getIntProperty("webui.lookup.select.size", 12)) %>">
<!--space filler because "unclosed" select annoys browsers-->
</select>
<img style="display:none;" alt="Loading..." id="lookup_indicator_id" class="choices-lookup"
src="<%= request.getContextPath() %>/image/authority/load-indicator.gif" />
</div>
<input type="hidden" name="paramField" value="<%= getDefaultedRequestParameter(request,"field", "") %>" />
<input type="hidden" name="paramValue" value="<%= getDefaultedRequestParameter(request,"value", "") %>" />
<input type="hidden" name="paramIsName" value="<%= isNameValue %>" />
<input type="hidden" name="paramIsRepeating" value="<%= isRepeatingValue %>" />
<input type="hidden" name="paramValueInput" value="<%= getDefaultedRequestParameter(request,"valueInput", "") %>" />
<input type="hidden" name="paramAuthorityInput" value="<%= getDefaultedRequestParameter(request,"authorityInput", "") %>" />
<input type="hidden" name="paramStart" value="<%= getDefaultedRequestParameter(request,"start", "0") %>" />
<input type="hidden" name="paramLimit" value="<%= getDefaultedRequestParameter(request,"limit", "0") %>" />
<input type="hidden" name="paramFormID" value="<%= getDefaultedRequestParameter(request,"formID", "") %>" />
<input type="hidden" name="paramIsClosed" value="<%= getDefaultedRequestParameter(request,"isClosed", "false") %>" />
<input type="hidden" name="paramConfIndicatorID" value="<%= getDefaultedRequestParameter(request,"confIndicatorID", "") %>" />
<input type="hidden" name="paramCollection" value="<%= getDefaultedRequestParameter(request,"collection", "-1") %>" />
<%-- XXX get this from dspace config if available..?? --%>
<input type="hidden" name="paramNonAuthority" value="<%= LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.field."+mdfield+".nonauthority") %>" />
<input name="paramFail" type="hidden" value="<%= LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.fail") %>" />
<input name="contextPath" type="hidden" value="<%= request.getContextPath() %>" />
</div>
</li>
<li id="aspect_general_ChoiceLookupTransformer_item_textFields" class="ds-form-item choices-lookup"> 
<div class="ds-form-content">
<% if (isName) { %>
<%-- XXX get this from dspace config if available..?? --%>
<% String help1 = LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.field."+mdfield+".help.last"); %>
<% String help2 = LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.field."+mdfield+".help.first"); %>
<label class="ds-composite-component">
<input class="ds-text-field choices-lookup" name="text1" type="text" value=""
title="<%= help1 %>" />
<br/><%= help1 %>
</label>
<label class="ds-composite-component last">
<input class="ds-text-field choices-lookup" name="text2" type="text" value=""
title="<%= help2 %>" />
<br/><%= help2 %>
</label>
<% } else { %>
<%-- XXX get this from dspace config if available..?? --%>
<% String help = LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.field."+mdfield+".help"); %>
<label class="ds-composite-component">
<input class="ds-text-field choices-lookup" name="text1" type="text" value=""
title="<%= help %>" />
<br/><%= help %>
</label>
<% } %>
<div class="spacer"> </div>
</div>
</li>
<li class="ds-form-item last choices-lookup"> 
<div class="ds-form-content">
<input name="accept" onClick="javascript:DSpaceChoicesAcceptOnClick();" type="button" class="ds-button-field choices-lookup"
value="<%= LocaleSupport.getLocalizedMessage(pageContext, isRepeating ? "jsp.tools.lookup.add":"jsp.tools.lookup.accept") %>"/>
<input name="more" onClick="javascript:DSpaceChoicesMoreOnClick();" type="button" class="ds-button-field choices-lookup" disabled="disabled"
value="<%= LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.more") %>"/>
<input name="cancel" onClick="javascript:DSpaceChoicesCancelOnClick();" type="button" class="ds-button-field choices-lookup"
value="<%= LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.cancel") %>"/>
</div>
</li>
</ol>
</fieldset>
</form>
<script type="text/javascript">
var form = document.getElementById('aspect_general_ChoiceLookupTransformer_div_lookup');
DSpaceChoicesSetup(form);
</script>
</dspace:layout>

54
dspace-ui-shared/pom.xml Normal file
View File

@@ -0,0 +1,54 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.dspace</groupId>
<artifactId>dspace-ui-shared</artifactId>
<packaging>war</packaging>
<name>DSpace UI :: Shared JS code</name>
<description>Some JS artifacts shared betwee DSpace JSPUI and XMLUI</description>
<url>http://projects.dspace.org/dspace-ui-shared</url>
<!--
A Parent POM that Maven inherits DSpace Defaults
POM atrributes from.
-->
<parent>
<groupId>org.dspace</groupId>
<artifactId>dspace-parent</artifactId>
<version>1.6.0-SNAPSHOT</version>
</parent>
<repositories>
<repository>
<id>maven.dspace.org-snapshot</id>
<name>DSpace Maven Snapshot Repository</name>
<url>http://maven.dspace.org/snapshot</url>
<releases>
<enabled>false</enabled>
<checksumPolicy>fail</checksumPolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>never</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
</repositories>
<!--
The Subversion repository location is used by Continuum to update against
when changes have occured, this spawns a new build cycle and releases snapshots
into the snapshot repository below.
-->
<scm>
<connection>scm:svn:http://scm.dspace.org/svn/repo/dspace/trunk/dspace</connection>
<developerConnection>scm:svn:https://scm.dspace.org/svn/repo/dspace/trunk/dspace</developerConnection>
<url>http://scm.dspace.org/svn/repo/dspace/trunk/dspace</url>
</scm>
<!--
Runtime and Compile Time dependencies for DSpace.
-->
<dependencies>
</dependencies>
</project>

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<!--
- web.xml
-
- Version: $Revision: 4254 $
-
- Date: $Date: 2009-09-11 11:59:19 -0400 (Fri, 11 Sep 2009) $
-
- Copyright (c) 2002-2006, Hewlett-Packard Company and Massachusetts
- Institute of Technology. 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 Hewlett-Packard Company nor the name of the
- Massachusetts Institute of Technology nor the names of their
- 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.
-->
<!--
- The is the servlet deployment descriptor for Tomcat 4.0 for the DSpace
- Web user interface
-
- '@@dspace.dir@@' will be replaced with the directory where DSpace is installed
-->
<web-app>
<display-name>DSpace Web UI</display-name>
</web-app>

View File

@@ -0,0 +1,575 @@
/*
* choice-support.js
*
* 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.
*/
// Client-side scripting to support DSpace Choice Control
// IMPORTANT NOTE:
// This code depends on a *MODIFIED* version of the
// script.aculo.us controls v1.8.2, fixed to avoid a bug that
// affects autocomplete in Firefox 3. This code is included in DSpace.
// Entry points:
// 1. DSpaceAutocomplete -- add autocomplete (suggest) to an input field
//
// 2. DSpaceChoiceLookup -- create popup window with authority choices
//
// @Author: Larry Stone <lcs@hulmail.harvard.edu>
// $Revision $
// -------------------- support for Autocomplete (Suggest)
// Autocomplete utility:
// Arguments:
// formID -- ID attribute of form tag
// args properties:
// metadataField -- metadata field e.g. dc_contributor_author
// inputName -- input field name for text input, or base of "Name" pair
// authorityName -- input field name in which to set authority
// containerID -- ID attribute of DIV to hold the menu objects
// indicatorID -- ID attribute of element to use as a "loading" indicator
// confidenceIndicatorID -- ID of element on which to set confidence
// confidenceName - NAME of confidence input (not ID)
// contextPath -- URL path prefix (i.e. webapp contextPath) for DSpace.
// collection -- db ID of dspace collection to serve as context
// isClosed -- true if authority value is required, false = non-auth allowed
// XXX Can't really enforce "isClosed=true" with autocomplete, user can type anything
//
// NOTE: Successful autocomplete always sets confidence to 'accepted' since
// authority value (if any) *was* chosen interactively by a human.
function DSpaceSetupAutocomplete(formID, args)
{
if (args.authorityName == null)
args.authorityName = dspace_makeFieldInput(args.inputName,'_authority');
var form = document.getElementById(formID);
var inputID = form.elements[args.inputName].id;
var authorityID = null;
if (form.elements[args.authorityName] != null)
authorityID = form.elements[args.authorityName].id;
// AJAX menu source, can add &query=TEXT
var choiceURL = args.contextPath+"/choices/"+args.metadataField;
var collID = args.collection == null ? -1 : args.collection;
// field in whcih to store authority value
var options =
{
// class name of spans that contain value in li elements
select: "value",
// make up query args for AJAX callback
parameters: 'collection='+collID+'&format=ul',
callback:
function(inField, querystring) {
return querystring+"&query="+inField.value;
},
// called after target field is updated
afterUpdateElement:
function(ignoreField, li)
{
// NOTE: lookup element late because it might not be in DOM
// at the time we evaluate the function..
var authInput = document.getElementById(authorityID);
var authValue = li == null ? "" : li.getAttribute("authority");
if (authInput != null)
{
authInput.value = authValue;
// update confidence input's value too if available.
if (args.confidenceName != null)
{
var confInput = authInput.form.elements[args.confidenceName];
if (confInput != null)
confInput.value = 'accepted';
}
}
// make indicator blank if no authority value
DSpaceUpdateConfidence(document, args.confidenceIndicatorID,
authValue == null || authValue == '' ? 'blank' :'accepted');
}
};
if (args.indicatorID != null)
options.indicator = args.indicatorID;
// be sure to turn off autocomplete, it absorbs arrow-key events!
form.elements[args.inputName].setAttribute("autocomplete", "off");
new Ajax.Autocompleter(inputID, args.containerID, choiceURL, options);
}
// -------------------- support for Lookup Popup
// Create popup window with authority choices for value of an input field.
// This is intended to be called by onClick of a "Lookup" or "Add" button.
function DSpaceChoiceLookup(url, field, formID, valueInput, authInput,
confIndicatorID, collectionID, isName, isRepeating)
{
// fill in URL
url += '?field='+field+'&formID='+formID+'&valueInput='+valueInput+
'&authorityInput='+authInput+'&collection='+collectionID+
'&isName='+isName+'&isRepeating='+isRepeating+'&confIndicatorID='+confIndicatorID;
// primary input field - for positioning popup.
var inputFieldName = isName ? dspace_makeFieldInput(valueInput,'_last') : valueInput;
var inputField = document.getElementById(formID).elements[inputFieldName];
// scriptactulous magic to figure out true offset:
var cOffset = 0;
if (inputField != null)
cOffset = $(inputField).cumulativeOffset();
var width = 600; // XXX guesses! these should be params, or configured..
var height = 470;
var left; var top;
if (window.screenX == null) {
left = window.screenLeft + cOffset.left - (width/2);
top = window.screenTop + cOffset.top - (height/2);
} else {
left = window.screenX + cOffset.left - (width/2);
top = window.screenY + cOffset.top - (height/2);
}
if (left < 0) left = 0;
if (top < 0) top = 0;
var pw = window.open(url, 'ignoreme',
'width='+width+',height='+height+',left='+left+',top='+top+
',toolbar=no,menubar=no,location=no,status=no,resizable');
if (window.focus) pw.focus();
return false;
}
// Run this as the Lookup page is loaded to initialize DOM objects, load choices
function DSpaceChoicesSetup(form)
{
// find the "LEGEND" in fieldset, which acts as page title,
// and save it as a bogus form element, e.g. elements['statline']
var fieldset = document.getElementById('aspect_general_ChoiceLookupTransformer_list_choicesList');
for (i = 0; i < fieldset.childNodes.length; ++i)
{
if (fieldset.childNodes[i].nodeName == 'LEGEND')
{
form.statline = fieldset.childNodes[i];
form.statline_template = fieldset.childNodes[i].innerHTML;
fieldset.childNodes[i].innerHTML = "Loading...";
break;
}
}
DSpaceChoicesLoad(form);
}
// populate the "select" with options from ajax request
// stash some parameters as properties of the "select" so we can add to
// the last start index to query for next set of results.
function DSpaceChoicesLoad(form)
{
var field = form.elements['paramField'].value;
var value = form.elements['paramValue'].value;
var start = form.elements['paramStart'].value;
var limit = form.elements['paramLimit'].value;
var formID = form.elements['paramFormID'].value;
var collID = form.elements['paramCollection'].value;
var isName = form.elements['paramIsName'].value == 'true';
var isRepeating = form.elements['paramIsRepeating'].value == 'true';
var isClosed = form.elements['paramIsClosed'].value == 'true';
var contextPath = form.elements['contextPath'].value;
var fail = form.elements['paramFail'].value;
var nonAuthority = "";
if (form.elements['paramNonAuthority'] != null)
nonAuthority = form.elements['paramNonAuthority'].value;
// get value from form inputs in opener if not explicitly supplied
if (value.length == 0)
{
var of = window.opener.document.getElementById(formID);
var valueInput = form.elements['paramValueInput'].value;
if (isName)
value = makePersonName(of.elements[dspace_makeFieldInput(valueInput,'_last')].value,
of.elements[dspace_makeFieldInput(valueInput,'_first')].value);
else
value = of.elements[valueInput].value;
}
// start spinner
var indicator = document.getElementById('lookup_indicator_id');
if (indicator != null)
indicator.style.display = "inline";
new Ajax.Request(contextPath+"/choices/"+field,
{
method: "get",
parameters: {query: value, format: 'select', collection: collID,
start: start, limit: limit},
// triggered by any exception, even in success
onException: function(req, e) {
window.alert(fail+" Exception="+e);
if (indicator != null) indicator.style.display = "none";
},
// when http load of choices fails
onFailure: function() {
window.alert(fail+" HTTP error resonse");
if (indicator != null) indicator.style.display = "none";
},
// format is <select><option authority="key" value="val">label</option>...
onSuccess: function(transport) {
var ul = transport.responseXML.firstChild;
var err = ul.getAttributeNode('error');
if (err != null && err.value == 'true')
window.alert(fail+" Server indicates error in response.");
var opts = ul.getElementsByTagName('option');
// update range message and update 'more' button
var oldStart = 1 * ul.getAttributeNode('start').value;
var nextStart = oldStart + opts.length;
var lastTotal = ul.getAttributeNode('total').value;
var resultMore = ul.getAttributeNode('more');
form.elements['more'].disabled = !(resultMore != null && resultMore.value == 'true');
form.elements['paramStart'].value = nextStart;
// clear select first
var select = form.elements['chooser'];
for (var i = select.length-1; i >= 0; --i)
select.remove(i);
// load select and look for default selection
var selectedByValue = -1; // select by value match
var selectedByChoices = -1; // Choice says its selected
for (var i = 0; i < opts.length; ++i)
{
var opt = opts.item(i);
var olabel = "";
for (var j = 0; j < opt.childNodes.length; ++j)
{
var node = opt.childNodes[j];
if (node.nodeName == "#text")
olabel += node.data;
}
var ovalue = opt.getAttributeNode('value').value;
var option = new Option(olabel, ovalue);
option.authority = opt.getAttributeNode('authority').value;
select.add(option, null);
if (value == ovalue)
selectedByValue = select.options.length - 1;
if (opt.getAttributeNode('selected') != null)
selectedByChoices = select.options.length - 1;
}
// add non-authority option if needed.
if (!isClosed)
{
select.add(new Option(dspace_formatMessage(nonAuthority, value), value), null);
}
var defaultSelected = -1;
if (selectedByChoices >= 0)
defaultSelected = selectedByChoices;
else if (selectedByValue >= 0)
defaultSelected = selectedByValue;
else if (select.options.length == 1)
defaultSelected = 0;
// load default-selected value
if (defaultSelected >= 0)
{
select.options[defaultSelected].defaultSelected = true;
var so = select.options[defaultSelected];
if (isName)
{
form.elements['text1'].value = lastNameOf(so.value);
form.elements['text2'].value = firstNameOf(so.value);
}
else
form.elements['text1'].value = so.value;
}
// turn off spinner
if (indicator != null)
indicator.style.display = "none";
// "results" status line
var statLast = nextStart + (isClosed ? 2 : 1);
form.statline.innerHTML =
dspace_formatMessage(form.statline_template,
oldStart+1, statLast, Math.max(lastTotal,statLast), value);
}
});
}
// handler for change event on choice selector - load new values
function DSpaceChoicesSelectOnChange ()
{
// "this" is the window,
var form = document.getElementById('aspect_general_ChoiceLookupTransformer_div_lookup');
var select = form.elements['chooser'];
var so = select.options[select.selectedIndex];
var isName = form.elements['paramIsName'].value == 'true';
if (isName)
{
form.elements['text1'].value = lastNameOf(so.value);
form.elements['text2'].value = firstNameOf(so.value);
}
else
form.elements['text1'].value = so.value;
}
// handler for lookup popup's accept (or add) button
// stuff values back to calling page, force an add if necessary, and close.
function DSpaceChoicesAcceptOnClick ()
{
var select = this.form.elements['chooser'];
var isName = this.form.elements['paramIsName'].value == 'true';
var isRepeating = this.form.elements['paramIsRepeating'].value == 'true';
var valueInput = this.form.elements['paramValueInput'].value;
var authorityInput = this.form.elements['paramAuthorityInput'].value;
var formID = this.form.elements['paramFormID'].value;
var confIndicatorID = this.form.elements['paramConfIndicatorID'] == null?null:this.form.elements['paramConfIndicatorID'].value;
// default the authority input if not supplied.
if (authorityInput.length == 0)
authorityInput = dspace_makeFieldInput(valueInput,'_authority');
// always stuff text fields back into caller's value input(s)
if (valueInput.length > 0)
{
var of = window.opener.document.getElementById(formID);
if (isName)
{
of.elements[dspace_makeFieldInput(valueInput,'_last')].value = this.form.elements['text1'].value;
of.elements[dspace_makeFieldInput(valueInput,'_first')].value = this.form.elements['text2'].value;
}
else
of.elements[valueInput].value = this.form.elements['text1'].value;
if (authorityInput.length > 0 && of.elements[authorityInput] != null)
{
// conf input is auth input, substitute '_confidence' for '_authority'
// if conf fieldname is FIELD_confidence_NUMBER, then '_authority_' => '_confidence_'
var confInput = "";
var ci = authorityInput.lastIndexOf("_authority_");
if (ci < 0)
confInput = authorityInput.substring(0, authorityInput.length-10)+'_confidence';
else
confInput = authorityInput.substring(0, ci)+"_confidence_"+authorityInput.substring(ci+11);
// DEBUG:
// window.alert('Setting fields auth="'+authorityInput+'", conf="'+confInput+'"');
var authValue = null;
if (select.selectedIndex >= 0 && select.options[select.selectedIndex].authority != null)
{
authValue = select.options[select.selectedIndex].authority;
of.elements[authorityInput].value = authValue;
}
if (of.elements[confInput] != null)
of.elements[confInput].value = 'accepted';
// make indicator blank if no authority value
DSpaceUpdateConfidence(window.opener.document, confIndicatorID,
authValue == null || authValue == '' ? 'blank' :'accepted');
}
// force the submit button -- if there is an "add"
if (isRepeating)
{
var add = of.elements["submit_"+valueInput+"_add"];
if (add != null)
add.click();
else
alert('Sanity check: Cannot find button named "submit_'+valueInput+'_add"');
}
}
window.close();
return false;
}
// handler for lookup popup's more button
function DSpaceChoicesMoreOnClick ()
{
DSpaceChoicesLoad(this.form);
}
// handler for lookup popup's cancel button
function DSpaceChoicesCancelOnClick ()
{
window.close();
return false;
}
// -------------------- Utilities
// DSpace person-name conventions, see DCPersonName
function makePersonName(lastName, firstName)
{
return (firstName == null || firstName.length == 0) ? lastName :
lastName+", "+firstName;
}
// DSpace person-name conventions, see DCPersonName
function firstNameOf(personName)
{
var comma = personName.indexOf(",");
return (comma < 0) ? "" : stringTrim(personName.substring(comma+1));
}
// DSpace person-name conventions, see DCPersonName
function lastNameOf(personName)
{
var comma = personName.indexOf(",");
return stringTrim((comma < 0) ? personName : personName.substring(0, comma));
}
// replicate java String.trim()
function stringTrim(str)
{
var start = 0;
var end = str.length;
for (; str.charAt(start) == ' '&& start < end; ++start) ;
for (; end > start && str.charAt(end-1) == ' '; --end) ;
return str.slice(start, end);
}
// format utility - replace @1@, @2@ etc with args 1, 2, 3..
// NOTE params MUST be monotonically increasing
// NOTE we can't use "{1}" like the i18n catalog because it elides them!!
// ...UNLESS maybe it were to be fixed not to when no params...
function dspace_formatMessage()
{
var template = dspace_formatMessage.arguments[0];
var i;
for (i = 1; i < arguments.length; ++i)
{
var pattern = '@'+i+'@';
if (template.search(pattern) >= 0)
template = template.replace(pattern, dspace_formatMessage.arguments[i]);
}
return template;
}
// utility to make sub-field name of input field, e.g. _last, _first, _auth..
// if name ends with _1, _2 etc, put sub-name BEFORE the number
function dspace_makeFieldInput(name, sub)
{
var i = name.search("_[0-9]+$");
if (i < 0)
return name+sub;
else
return name.substr(0, i)+sub+name.substr(i);
}
// update the class value of confidence-indicating element
function DSpaceUpdateConfidence(doc, confIndicatorID, newValue)
{
// sanity checks - need valid ID and a real DOM object
if (confIndicatorID == null || confIndicatorID == "")
return;
var confElt = doc.getElementById(confIndicatorID);
if (confElt == null)
return;
// add or update CSS class with new confidence value, e.g. "cf-accepted".
if (confElt.className == null)
confElt.className = "cf-"+newValue;
else
{
var classes = confElt.className.split(" ");
var newClasses = "";
var found = false;
for (var i = 0; i < classes.length; ++i)
{
if (classes[i].match('^cf-[a-zA-Z0-9]+$'))
{
newClasses += "cf-"+newValue+" ";
found = true;
}
else
newClasses += classes[i]+" ";
}
if (!found)
newClasses += "cf-"+newValue+" ";
confElt.className = newClasses;
}
}
// respond to "onchanged" event on authority input field
// set confidence to 'accepted' if authority was changed by user.
function DSpaceAuthorityOnChange(self, confValueID, confIndicatorID)
{
var confidence = 'accepted';
if (confValueID != null && confValueID != '')
{
var confValueField = document.getElementById(confValueID);
if (confValueField != null)
confValueField.value = confidence;
}
DSpaceUpdateConfidence(document, confIndicatorID, confidence)
return false;
}
// respond to click on the authority-value lock button in Edit Item Metadata:
// "button" is bound to the image input for the lock button, "this"
function DSpaceToggleAuthorityLock(button, authInputID)
{
// sanity checks - need valid ID and a real DOM object
if (authInputID == null || authInputID == '')
return false;
var authInput = document.getElementById(authInputID);
if (authInput == null)
return false;
// look for is-locked or is-unlocked in class list:
var classes = button.className.split(' ');
var newClass = '';
var newLocked = false;
var found = false;
for (var i = 0; i < classes.length; ++i)
{
if (classes[i] == 'is-locked')
{
newLocked = false;
found = true;
}
else if (classes[i] == 'is-unlocked')
{
newLocked = true;
found = true;
}
else
newClass += classes[i]+' ';
}
if (!found)
return false;
// toggle the image, and set readability
button.className = newClass + (newLocked ? 'is-locked' : 'is-unlocked') + ' ';
authInput.readOnly = newLocked;
return false;
}

View File

@@ -0,0 +1,136 @@
// script.aculo.us builder.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
var Builder = {
NODEMAP: {
AREA: 'map',
CAPTION: 'table',
COL: 'table',
COLGROUP: 'table',
LEGEND: 'fieldset',
OPTGROUP: 'select',
OPTION: 'select',
PARAM: 'object',
TBODY: 'table',
TD: 'table',
TFOOT: 'table',
TH: 'table',
THEAD: 'table',
TR: 'table'
},
// note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
// due to a Firefox bug
node: function(elementName) {
elementName = elementName.toUpperCase();
// try innerHTML approach
var parentTag = this.NODEMAP[elementName] || 'div';
var parentElement = document.createElement(parentTag);
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
} catch(e) {}
var element = parentElement.firstChild || null;
// see if browser added wrapping tags
if(element && (element.tagName.toUpperCase() != elementName))
element = element.getElementsByTagName(elementName)[0];
// fallback to createElement approach
if(!element) element = document.createElement(elementName);
// abort if nothing could be created
if(!element) return;
// attributes (or text)
if(arguments[1])
if(this._isStringOrNumber(arguments[1]) ||
(arguments[1] instanceof Array) ||
arguments[1].tagName) {
this._children(element, arguments[1]);
} else {
var attrs = this._attributes(arguments[1]);
if(attrs.length) {
try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
parentElement.innerHTML = "<" +elementName + " " +
attrs + "></" + elementName + ">";
} catch(e) {}
element = parentElement.firstChild || null;
// workaround firefox 1.0.X bug
if(!element) {
element = document.createElement(elementName);
for(attr in arguments[1])
element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
}
if(element.tagName.toUpperCase() != elementName)
element = parentElement.getElementsByTagName(elementName)[0];
}
}
// text, or array of children
if(arguments[2])
this._children(element, arguments[2]);
return $(element);
},
_text: function(text) {
return document.createTextNode(text);
},
ATTR_MAP: {
'className': 'class',
'htmlFor': 'for'
},
_attributes: function(attributes) {
var attrs = [];
for(attribute in attributes)
attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
'="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
return attrs.join(" ");
},
_children: function(element, children) {
if(children.tagName) {
element.appendChild(children);
return;
}
if(typeof children=='object') { // array can hold nodes and text
children.flatten().each( function(e) {
if(typeof e=='object')
element.appendChild(e);
else
if(Builder._isStringOrNumber(e))
element.appendChild(Builder._text(e));
});
} else
if(Builder._isStringOrNumber(children))
element.appendChild(Builder._text(children));
},
_isStringOrNumber: function(param) {
return(typeof param=='string' || typeof param=='number');
},
build: function(html) {
var element = this.node('div');
$(element).update(html.strip());
return element.down();
},
dump: function(scope) {
if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
"BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
"FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
"KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
"PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
"TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
tags.each( function(tag){
scope[tag] = function() {
return Builder.node.apply(Builder, [tag].concat($A(arguments)));
};
});
}
};

View File

@@ -0,0 +1,980 @@
// script.aculo.us controls.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
// Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
// (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
// (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
// Contributors:
// Richard Livsey
// Rahul Bhargava
// Rob Wills
//
// script.aculo.us is freely distributable under the terms of an MIT-style license.
// For details, see the script.aculo.us web site: http://script.aculo.us/
// Autocompleter.Base handles all the autocompletion functionality
// that's independent of the data source for autocompletion. This
// includes drawing the autocompletion menu, observing keyboard
// and mouse events, and similar.
//
// Specific autocompleters need to provide, at the very least,
// a getUpdatedChoices function that will be invoked every time
// the text inside the monitored textbox changes. This method
// should get the text for which to provide autocompletion by
// invoking this.getToken(), NOT by directly accessing
// this.element.value. This is to allow incremental tokenized
// autocompletion. Specific auto-completion logic (AJAX, etc)
// belongs in getUpdatedChoices.
//
// Tokenized incremental autocompletion is enabled automatically
// when an autocompleter is instantiated with the 'tokens' option
// in the options parameter, e.g.:
// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
// will incrementally autocomplete with a comma as the token.
// Additionally, ',' in the above example can be replaced with
// a token array, e.g. { tokens: [',', '\n'] } which
// enables autocompletion on multiple tokens. This is most
// useful when one of the tokens is \n (a newline), as it
// allows smart autocompletion after linebreaks.
if(typeof Effect == 'undefined')
throw("controls.js requires including script.aculo.us' effects.js library");
var Autocompleter = { };
Autocompleter.Base = Class.create({
baseInitialize: function(element, update, options) {
element = $(element);
this.element = element;
this.update = $(update);
this.hasFocus = false;
this.changed = false;
this.active = false;
this.index = 0;
this.entryCount = 0;
this.oldElementValue = this.element.value;
if(this.setOptions)
this.setOptions(options);
else
this.options = options || { };
this.options.paramName = this.options.paramName || this.element.name;
this.options.tokens = this.options.tokens || [];
this.options.frequency = this.options.frequency || 0.4;
this.options.minChars = this.options.minChars || 1;
this.options.onShow = this.options.onShow ||
function(element, update){
if(!update.style.position || update.style.position=='absolute') {
update.style.position = 'absolute';
Position.clone(element, update, {
setHeight: false,
offsetTop: element.offsetHeight
});
}
Effect.Appear(update,{duration:0.15});
};
this.options.onHide = this.options.onHide ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
if(typeof(this.options.tokens) == 'string')
this.options.tokens = new Array(this.options.tokens);
// Force carriage returns as token delimiters anyway
if (!this.options.tokens.include('\n'))
this.options.tokens.push('\n');
this.observer = null;
this.element.setAttribute('autocomplete','off');
Element.hide(this.update);
Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
},
show: function() {
if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
if(!this.iefix &&
(Prototype.Browser.IE) &&
(Element.getStyle(this.update, 'position')=='absolute')) {
new Insertion.After(this.update,
'<iframe id="' + this.update.id + '_iefix" '+
'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
this.iefix = $(this.update.id+'_iefix');
}
if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
},
fixIEOverlapping: function() {
Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
this.iefix.style.zIndex = 1;
this.update.style.zIndex = 2;
Element.show(this.iefix);
},
hide: function() {
this.stopIndicator();
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
if(this.iefix) Element.hide(this.iefix);
},
startIndicator: function() {
if(this.options.indicator) Element.show(this.options.indicator);
},
stopIndicator: function() {
if(this.options.indicator) Element.hide(this.options.indicator);
},
onKeyPress: function(event) {
if(this.active)
switch(event.keyCode) {
case Event.KEY_TAB:
case Event.KEY_RETURN:
this.selectEntry();
Event.stop(event);
case Event.KEY_ESC:
this.hide();
this.active = false;
Event.stop(event);
return;
case Event.KEY_LEFT:
case Event.KEY_RIGHT:
return;
case Event.KEY_UP:
this.markPrevious();
this.render();
Event.stop(event);
return;
case Event.KEY_DOWN:
this.markNext();
this.render();
Event.stop(event);
return;
}
else
if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
(Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
this.changed = true;
this.hasFocus = true;
if(this.observer) clearTimeout(this.observer);
this.observer =
setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
},
activate: function() {
this.changed = false;
this.hasFocus = true;
this.getUpdatedChoices();
},
onHover: function(event) {
var element = Event.findElement(event, 'LI');
if(this.index != element.autocompleteIndex)
{
this.index = element.autocompleteIndex;
this.render();
}
Event.stop(event);
},
onClick: function(event) {
var element = Event.findElement(event, 'LI');
this.index = element.autocompleteIndex;
this.selectEntry();
this.hide();
},
onBlur: function(event) {
// needed to make click events working
setTimeout(this.hide.bind(this), 250);
this.hasFocus = false;
this.active = false;
},
render: function() {
if(this.entryCount > 0) {
for (var i = 0; i < this.entryCount; i++)
this.index==i ?
Element.addClassName(this.getEntry(i),"selected") :
Element.removeClassName(this.getEntry(i),"selected");
if(this.hasFocus) {
this.show();
this.active = true;
}
} else {
this.active = false;
this.hide();
}
},
markPrevious: function() {
if(this.index > 0) this.index--;
else {
this.index = this.entryCount-1;
this.update.scrollTop = this.update.scrollHeight;
}
selection = this.getEntry(this.index);
selection_top = selection.offsetTop;
if(selection_top < this.update.scrollTop){
this.update.scrollTop = this.update.scrollTop-selection.offsetHeight;
}
},
markNext: function() {
if(this.index < this.entryCount-1) this.index++;
else {
this.index = 0;
this.update.scrollTop = 0;
}
selection = this.getEntry(this.index);
selection_bottom = selection.offsetTop+selection.offsetHeight;
if(selection_bottom > this.update.scrollTop+this.update.offsetHeight){
this.update.scrollTop = this.update.scrollTop+selection.offsetHeight;
}
},
getEntry: function(index) {
return this.update.firstChild.childNodes[index];
},
getCurrentEntry: function() {
return this.getEntry(this.index);
},
selectEntry: function() {
this.active = false;
this.updateElement(this.getCurrentEntry());
},
updateElement: function(selectedElement) {
if (this.options.updateElement) {
this.options.updateElement(selectedElement);
return;
}
var value = '';
if (this.options.select) {
var nodes = $(selectedElement).select('.' + this.options.select) || [];
if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
} else
value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
var bounds = this.getTokenBounds();
if (bounds[0] != -1) {
var newValue = this.element.value.substr(0, bounds[0]);
var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
if (whitespace)
newValue += whitespace[0];
this.element.value = newValue + value + this.element.value.substr(bounds[1]);
} else {
this.element.value = value;
}
this.oldElementValue = this.element.value;
this.element.focus();
if (this.options.afterUpdateElement)
this.options.afterUpdateElement(this.element, selectedElement);
},
updateChoices: function(choices) {
if(!this.changed && this.hasFocus) {
this.update.innerHTML = choices;
Element.cleanWhitespace(this.update);
Element.cleanWhitespace(this.update.down());
if(this.update.firstChild && this.update.down().childNodes) {
this.entryCount =
this.update.down().childNodes.length;
for (var i = 0; i < this.entryCount; i++) {
var entry = this.getEntry(i);
entry.autocompleteIndex = i;
this.addObservers(entry);
}
} else {
this.entryCount = 0;
}
this.stopIndicator();
this.update.scrollTop = 0;
this.index = 0;
if(this.entryCount==1 && this.options.autoSelect) {
this.selectEntry();
this.hide();
} else {
this.render();
}
}
},
addObservers: function(element) {
Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
Event.observe(element, "click", this.onClick.bindAsEventListener(this));
},
onObserverEvent: function() {
this.changed = false;
this.tokenBounds = null;
if(this.getToken().length>=this.options.minChars) {
this.getUpdatedChoices();
} else {
this.active = false;
this.hide();
}
this.oldElementValue = this.element.value;
},
getToken: function() {
var bounds = this.getTokenBounds();
return this.element.value.substring(bounds[0], bounds[1]).strip();
},
getTokenBounds: function() {
if (null != this.tokenBounds) return this.tokenBounds;
var value = this.element.value;
if (value.strip().empty()) return [-1, 0];
var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
var offset = (diff == this.oldElementValue.length ? 1 : 0);
var prevTokenPos = -1, nextTokenPos = value.length;
var tp;
for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
if (tp > prevTokenPos) prevTokenPos = tp;
tp = value.indexOf(this.options.tokens[index], diff + offset);
if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
}
return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
}
});
Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
var boundary = Math.min(newS.length, oldS.length);
for (var index = 0; index < boundary; ++index)
if (newS[index] != oldS[index])
return index;
return boundary;
};
Ajax.Autocompleter = Class.create(Autocompleter.Base, {
initialize: function(element, update, url, options) {
this.baseInitialize(element, update, options);
this.options.asynchronous = true;
this.options.onComplete = this.onComplete.bind(this);
this.options.defaultParams = this.options.parameters || null;
this.url = url;
},
getUpdatedChoices: function() {
this.startIndicator();
var entry = encodeURIComponent(this.options.paramName) + '=' +
encodeURIComponent(this.getToken());
this.options.parameters = this.options.callback ?
this.options.callback(this.element, entry) : entry;
if(this.options.defaultParams)
this.options.parameters += '&' + this.options.defaultParams;
new Ajax.Request(this.url, this.options);
},
onComplete: function(request) {
this.updateChoices(request.responseText);
}
});
// The local array autocompleter. Used when you'd prefer to
// inject an array of autocompletion options into the page, rather
// than sending out Ajax queries, which can be quite slow sometimes.
//
// The constructor takes four parameters. The first two are, as usual,
// the id of the monitored textbox, and id of the autocompletion menu.
// The third is the array you want to autocomplete from, and the fourth
// is the options block.
//
// Extra local autocompletion options:
// - choices - How many autocompletion choices to offer
//
// - partialSearch - If false, the autocompleter will match entered
// text only at the beginning of strings in the
// autocomplete array. Defaults to true, which will
// match text at the beginning of any *word* in the
// strings in the autocomplete array. If you want to
// search anywhere in the string, additionally set
// the option fullSearch to true (default: off).
//
// - fullSsearch - Search anywhere in autocomplete array strings.
//
// - partialChars - How many characters to enter before triggering
// a partial match (unlike minChars, which defines
// how many characters are required to do any match
// at all). Defaults to 2.
//
// - ignoreCase - Whether to ignore case when autocompleting.
// Defaults to true.
//
// It's possible to pass in a custom function as the 'selector'
// option, if you prefer to write your own autocompletion logic.
// In that case, the other options above will not apply unless
// you support them.
Autocompleter.Local = Class.create(Autocompleter.Base, {
initialize: function(element, update, array, options) {
this.baseInitialize(element, update, options);
this.options.array = array;
},
getUpdatedChoices: function() {
this.updateChoices(this.options.selector(this));
},
setOptions: function(options) {
this.options = Object.extend({
choices: 10,
partialSearch: true,
partialChars: 2,
ignoreCase: true,
fullSearch: false,
selector: function(instance) {
var ret = []; // Beginning matches
var partial = []; // Inside matches
var entry = instance.getToken();
var count = 0;
for (var i = 0; i < instance.options.array.length &&
ret.length < instance.options.choices ; i++) {
var elem = instance.options.array[i];
var foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase()) :
elem.indexOf(entry);
while (foundPos != -1) {
if (foundPos == 0 && elem.length != entry.length) {
ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
elem.substr(entry.length) + "</li>");
break;
} else if (entry.length >= instance.options.partialChars &&
instance.options.partialSearch && foundPos != -1) {
if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
foundPos + entry.length) + "</li>");
break;
}
}
foundPos = instance.options.ignoreCase ?
elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
elem.indexOf(entry, foundPos + 1);
}
}
if (partial.length)
ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
return "<ul>" + ret.join('') + "</ul>";
}
}, options || { });
}
});
// AJAX in-place editor and collection editor
// Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
// Use this if you notice weird scrolling problems on some browsers,
// the DOM might be a bit confused when this gets called so do this
// waits 1 ms (with setTimeout) until it does the activation
Field.scrollFreeActivate = function(field) {
setTimeout(function() {
Field.activate(field);
}, 1);
};
Ajax.InPlaceEditor = Class.create({
initialize: function(element, url, options) {
this.url = url;
this.element = element = $(element);
this.prepareOptions();
this._controls = { };
arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
Object.extend(this.options, options || { });
if (!this.options.formId && this.element.id) {
this.options.formId = this.element.id + '-inplaceeditor';
if ($(this.options.formId))
this.options.formId = '';
}
if (this.options.externalControl)
this.options.externalControl = $(this.options.externalControl);
if (!this.options.externalControl)
this.options.externalControlOnly = false;
this._originalBackground = this.element.getStyle('background-color') || 'transparent';
this.element.title = this.options.clickToEditText;
this._boundCancelHandler = this.handleFormCancellation.bind(this);
this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
this._boundFailureHandler = this.handleAJAXFailure.bind(this);
this._boundSubmitHandler = this.handleFormSubmission.bind(this);
this._boundWrapperHandler = this.wrapUp.bind(this);
this.registerListeners();
},
checkForEscapeOrReturn: function(e) {
if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
if (Event.KEY_ESC == e.keyCode)
this.handleFormCancellation(e);
else if (Event.KEY_RETURN == e.keyCode)
this.handleFormSubmission(e);
},
createControl: function(mode, handler, extraClasses) {
var control = this.options[mode + 'Control'];
var text = this.options[mode + 'Text'];
if ('button' == control) {
var btn = document.createElement('input');
btn.type = 'submit';
btn.value = text;
btn.className = 'editor_' + mode + '_button';
if ('cancel' == mode)
btn.onclick = this._boundCancelHandler;
this._form.appendChild(btn);
this._controls[mode] = btn;
} else if ('link' == control) {
var link = document.createElement('a');
link.href = '#';
link.appendChild(document.createTextNode(text));
link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
link.className = 'editor_' + mode + '_link';
if (extraClasses)
link.className += ' ' + extraClasses;
this._form.appendChild(link);
this._controls[mode] = link;
}
},
createEditField: function() {
var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
var fld;
if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
fld = document.createElement('input');
fld.type = 'text';
var size = this.options.size || this.options.cols || 0;
if (0 < size) fld.size = size;
} else {
fld = document.createElement('textarea');
fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
fld.cols = this.options.cols || 40;
}
fld.name = this.options.paramName;
fld.value = text; // No HTML breaks conversion anymore
fld.className = 'editor_field';
if (this.options.submitOnBlur)
fld.onblur = this._boundSubmitHandler;
this._controls.editor = fld;
if (this.options.loadTextURL)
this.loadExternalText();
this._form.appendChild(this._controls.editor);
},
createForm: function() {
var ipe = this;
function addText(mode, condition) {
var text = ipe.options['text' + mode + 'Controls'];
if (!text || condition === false) return;
ipe._form.appendChild(document.createTextNode(text));
};
this._form = $(document.createElement('form'));
this._form.id = this.options.formId;
this._form.addClassName(this.options.formClassName);
this._form.onsubmit = this._boundSubmitHandler;
this.createEditField();
if ('textarea' == this._controls.editor.tagName.toLowerCase())
this._form.appendChild(document.createElement('br'));
if (this.options.onFormCustomization)
this.options.onFormCustomization(this, this._form);
addText('Before', this.options.okControl || this.options.cancelControl);
this.createControl('ok', this._boundSubmitHandler);
addText('Between', this.options.okControl && this.options.cancelControl);
this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
addText('After', this.options.okControl || this.options.cancelControl);
},
destroy: function() {
if (this._oldInnerHTML)
this.element.innerHTML = this._oldInnerHTML;
this.leaveEditMode();
this.unregisterListeners();
},
enterEditMode: function(e) {
if (this._saving || this._editing) return;
this._editing = true;
this.triggerCallback('onEnterEditMode');
if (this.options.externalControl)
this.options.externalControl.hide();
this.element.hide();
this.createForm();
this.element.parentNode.insertBefore(this._form, this.element);
if (!this.options.loadTextURL)
this.postProcessEditField();
if (e) Event.stop(e);
},
enterHover: function(e) {
if (this.options.hoverClassName)
this.element.addClassName(this.options.hoverClassName);
if (this._saving) return;
this.triggerCallback('onEnterHover');
},
getText: function() {
return this.element.innerHTML.unescapeHTML();
},
handleAJAXFailure: function(transport) {
this.triggerCallback('onFailure', transport);
if (this._oldInnerHTML) {
this.element.innerHTML = this._oldInnerHTML;
this._oldInnerHTML = null;
}
},
handleFormCancellation: function(e) {
this.wrapUp();
if (e) Event.stop(e);
},
handleFormSubmission: function(e) {
var form = this._form;
var value = $F(this._controls.editor);
this.prepareSubmission();
var params = this.options.callback(form, value) || '';
if (Object.isString(params))
params = params.toQueryParams();
params.editorId = this.element.id;
if (this.options.htmlResponse) {
var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Updater({ success: this.element }, this.url, options);
} else {
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: params,
onComplete: this._boundWrapperHandler,
onFailure: this._boundFailureHandler
});
new Ajax.Request(this.url, options);
}
if (e) Event.stop(e);
},
leaveEditMode: function() {
this.element.removeClassName(this.options.savingClassName);
this.removeForm();
this.leaveHover();
this.element.style.backgroundColor = this._originalBackground;
this.element.show();
if (this.options.externalControl)
this.options.externalControl.show();
this._saving = false;
this._editing = false;
this._oldInnerHTML = null;
this.triggerCallback('onLeaveEditMode');
},
leaveHover: function(e) {
if (this.options.hoverClassName)
this.element.removeClassName(this.options.hoverClassName);
if (this._saving) return;
this.triggerCallback('onLeaveHover');
},
loadExternalText: function() {
this._form.addClassName(this.options.loadingClassName);
this._controls.editor.disabled = true;
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
this._form.removeClassName(this.options.loadingClassName);
var text = transport.responseText;
if (this.options.stripLoadedTextTags)
text = text.stripTags();
this._controls.editor.value = text;
this._controls.editor.disabled = false;
this.postProcessEditField();
}.bind(this),
onFailure: this._boundFailureHandler
});
new Ajax.Request(this.options.loadTextURL, options);
},
postProcessEditField: function() {
var fpc = this.options.fieldPostCreation;
if (fpc)
$(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
},
prepareOptions: function() {
this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
[this._extraDefaultOptions].flatten().compact().each(function(defs) {
Object.extend(this.options, defs);
}.bind(this));
},
prepareSubmission: function() {
this._saving = true;
this.removeForm();
this.leaveHover();
this.showSaving();
},
registerListeners: function() {
this._listeners = { };
var listener;
$H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
listener = this[pair.value].bind(this);
this._listeners[pair.key] = listener;
if (!this.options.externalControlOnly)
this.element.observe(pair.key, listener);
if (this.options.externalControl)
this.options.externalControl.observe(pair.key, listener);
}.bind(this));
},
removeForm: function() {
if (!this._form) return;
this._form.remove();
this._form = null;
this._controls = { };
},
showSaving: function() {
this._oldInnerHTML = this.element.innerHTML;
this.element.innerHTML = this.options.savingText;
this.element.addClassName(this.options.savingClassName);
this.element.style.backgroundColor = this._originalBackground;
this.element.show();
},
triggerCallback: function(cbName, arg) {
if ('function' == typeof this.options[cbName]) {
this.options[cbName](this, arg);
}
},
unregisterListeners: function() {
$H(this._listeners).each(function(pair) {
if (!this.options.externalControlOnly)
this.element.stopObserving(pair.key, pair.value);
if (this.options.externalControl)
this.options.externalControl.stopObserving(pair.key, pair.value);
}.bind(this));
},
wrapUp: function(transport) {
this.leaveEditMode();
// Can't use triggerCallback due to backward compatibility: requires
// binding + direct element
this._boundComplete(transport, this.element);
}
});
Object.extend(Ajax.InPlaceEditor.prototype, {
dispose: Ajax.InPlaceEditor.prototype.destroy
});
Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
initialize: function($super, element, url, options) {
this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
$super(element, url, options);
},
createEditField: function() {
var list = document.createElement('select');
list.name = this.options.paramName;
list.size = 1;
this._controls.editor = list;
this._collection = this.options.collection || [];
if (this.options.loadCollectionURL)
this.loadCollection();
else
this.checkForExternalText();
this._form.appendChild(this._controls.editor);
},
loadCollection: function() {
this._form.addClassName(this.options.loadingClassName);
this.showLoadingText(this.options.loadingCollectionText);
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
var js = transport.responseText.strip();
if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
throw('Server returned an invalid collection representation.');
this._collection = eval(js);
this.checkForExternalText();
}.bind(this),
onFailure: this.onFailure
});
new Ajax.Request(this.options.loadCollectionURL, options);
},
showLoadingText: function(text) {
this._controls.editor.disabled = true;
var tempOption = this._controls.editor.firstChild;
if (!tempOption) {
tempOption = document.createElement('option');
tempOption.value = '';
this._controls.editor.appendChild(tempOption);
tempOption.selected = true;
}
tempOption.update((text || '').stripScripts().stripTags());
},
checkForExternalText: function() {
this._text = this.getText();
if (this.options.loadTextURL)
this.loadExternalText();
else
this.buildOptionList();
},
loadExternalText: function() {
this.showLoadingText(this.options.loadingText);
var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
Object.extend(options, {
parameters: 'editorId=' + encodeURIComponent(this.element.id),
onComplete: Prototype.emptyFunction,
onSuccess: function(transport) {
this._text = transport.responseText.strip();
this.buildOptionList();
}.bind(this),
onFailure: this.onFailure
});
new Ajax.Request(this.options.loadTextURL, options);
},
buildOptionList: function() {
this._form.removeClassName(this.options.loadingClassName);
this._collection = this._collection.map(function(entry) {
return 2 === entry.length ? entry : [entry, entry].flatten();
});
var marker = ('value' in this.options) ? this.options.value : this._text;
var textFound = this._collection.any(function(entry) {
return entry[0] == marker;
}.bind(this));
this._controls.editor.update('');
var option;
this._collection.each(function(entry, index) {
option = document.createElement('option');
option.value = entry[0];
option.selected = textFound ? entry[0] == marker : 0 == index;
option.appendChild(document.createTextNode(entry[1]));
this._controls.editor.appendChild(option);
}.bind(this));
this._controls.editor.disabled = false;
Field.scrollFreeActivate(this._controls.editor);
}
});
//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
//**** This only exists for a while, in order to let ****
//**** users adapt to the new API. Read up on the new ****
//**** API and convert your code to it ASAP! ****
Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
if (!options) return;
function fallback(name, expr) {
if (name in options || expr === undefined) return;
options[name] = expr;
};
fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
options.cancelLink == options.cancelButton == false ? false : undefined)));
fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
options.okLink == options.okButton == false ? false : undefined)));
fallback('highlightColor', options.highlightcolor);
fallback('highlightEndColor', options.highlightendcolor);
};
Object.extend(Ajax.InPlaceEditor, {
DefaultOptions: {
ajaxOptions: { },
autoRows: 3, // Use when multi-line w/ rows == 1
cancelControl: 'link', // 'link'|'button'|false
cancelText: 'cancel',
clickToEditText: 'Click to edit',
externalControl: null, // id|elt
externalControlOnly: false,
fieldPostCreation: 'activate', // 'activate'|'focus'|false
formClassName: 'inplaceeditor-form',
formId: null, // id|elt
highlightColor: '#ffff99',
highlightEndColor: '#ffffff',
hoverClassName: '',
htmlResponse: true,
loadingClassName: 'inplaceeditor-loading',
loadingText: 'Loading...',
okControl: 'button', // 'link'|'button'|false
okText: 'ok',
paramName: 'value',
rows: 1, // If 1 and multi-line, uses autoRows
savingClassName: 'inplaceeditor-saving',
savingText: 'Saving...',
size: 0,
stripLoadedTextTags: false,
submitOnBlur: false,
textAfterControls: '',
textBeforeControls: '',
textBetweenControls: ''
},
DefaultCallbacks: {
callback: function(form) {
return Form.serialize(form);
},
onComplete: function(transport, element) {
// For backward compatibility, this one is bound to the IPE, and passes
// the element directly. It was too often customized, so we don't break it.
new Effect.Highlight(element, {
startcolor: this.options.highlightColor, keepBackgroundImage: true });
},
onEnterEditMode: null,
onEnterHover: function(ipe) {
ipe.element.style.backgroundColor = ipe.options.highlightColor;
if (ipe._effect)
ipe._effect.cancel();
},
onFailure: function(transport, ipe) {
alert('Error communication with the server: ' + transport.responseText.stripTags());
},
onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
onLeaveEditMode: null,
onLeaveHover: function(ipe) {
ipe._effect = new Effect.Highlight(ipe.element, {
startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
restorecolor: ipe._originalBackground, keepBackgroundImage: true
});
}
},
Listeners: {
click: 'enterEditMode',
keydown: 'checkForEscapeOrReturn',
mouseover: 'enterHover',
mouseout: 'leaveHover'
}
});
Ajax.InPlaceCollectionEditor.DefaultOptions = {
loadingCollectionText: 'Loading options...'
};
// Delayed observer, like Form.Element.Observer,
// but waits for delay after last key input
// Ideal for live-search fields
Form.Element.DelayedObserver = Class.create({
initialize: function(element, delay, callback) {
this.delay = delay || 0.5;
this.element = $(element);
this.callback = callback;
this.timer = null;
this.lastValue = $F(this.element);
Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
},
delayedListener: function(event) {
if(this.lastValue == $F(this.element)) return;
if(this.timer) clearTimeout(this.timer);
this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
this.lastValue = $F(this.element);
},
onTimerEvent: function() {
this.timer = null;
this.callback(this.element, $F(this.element));
}
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,7 @@
* *
* Date: $Date$ * Date: $Date$
* *
* Copyright (c) 2002, Hewlett-Packard Company and Massachusetts * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved.
* Institute of Technology. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@@ -19,8 +18,7 @@
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* - Neither the name of the Hewlett-Packard Company nor the name of the * - Neither the name of the DSpace Foundation nor the names of its
* Massachusetts Institute of Technology nor the names of their
* contributors may be used to endorse or promote products derived from * contributors may be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
@@ -36,7 +34,8 @@
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE. * DAMAGE.
*/package org.dspace.app.xmlui.aspect.administrative; */
package org.dspace.app.xmlui.aspect.administrative;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -59,6 +58,7 @@ import org.dspace.content.FormatIdentifier;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataField; import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema; import org.dspace.content.MetadataSchema;
import org.dspace.content.authority.Choices;
import org.dspace.core.Constants; import org.dspace.core.Constants;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.handle.HandleManager; import org.dspace.handle.HandleManager;
@@ -213,6 +213,8 @@ public class FlowItemUtils
{ {
String name = request.getParameter("name_"+index); String name = request.getParameter("name_"+index);
String value = request.getParameter("value_"+index); String value = request.getParameter("value_"+index);
String authority = request.getParameter("value_"+index+"_authority");
String confidence = request.getParameter("value_"+index+"_confidence");
String lang = request.getParameter("language_"+index); String lang = request.getParameter("language_"+index);
String remove = request.getParameter("remove_"+index); String remove = request.getParameter("remove_"+index);
@@ -223,8 +225,15 @@ public class FlowItemUtils
// get the field's name broken up // get the field's name broken up
String[] parts = parseName(name); String[] parts = parseName(name);
// Add the metadata back in. // probe for a confidence value
item.addMetadata(parts[0], parts[1], parts[2], lang, value); int iconf = Choices.CF_UNSET;
if (confidence != null && confidence.length() > 0)
iconf = Choices.getConfidenceValue(confidence);
// upgrade to a minimum of NOVALUE if there IS an authority key
if (authority != null && authority.length() > 0 && iconf == Choices.CF_UNSET)
iconf = Choices.CF_NOVALUE;
item.addMetadata(parts[0], parts[1], parts[2], lang,
value, authority, iconf);
} }
item.update(); item.update();

View File

@@ -210,9 +210,9 @@ public class WithdrawnItems extends AbstractDSpaceTransformer implements
else else
{ {
// Add the metadata to the validity // Add the metadata to the validity
for (String singleEntry : browseInfo.getStringResults()) for (String[] singleEntry : browseInfo.getStringResults())
{ {
validity.add(singleEntry); validity.add(singleEntry[0]+"#"+singleEntry[1]);
} }
} }
} }
@@ -310,16 +310,24 @@ public class WithdrawnItems extends AbstractDSpaceTransformer implements
message("xmlui.ArtifactBrowser.ConfigurableBrowse." + type + ".column_heading")); message("xmlui.ArtifactBrowser.ConfigurableBrowse." + type + ".column_heading"));
// Iterate each result // Iterate each result
for (String singleEntry : browseInfo.getStringResults()) for (String[] singleEntry : browseInfo.getStringResults())
{ {
// Create a Map of the query parameters for the link // Create a Map of the query parameters for the link
Map<String, String> queryParams = new HashMap<String, String>(); Map<String, String> queryParams = new HashMap<String, String>();
queryParams.put(BrowseParams.TYPE, URLEncode(type)); queryParams.put(BrowseParams.TYPE, URLEncode(type));
queryParams.put(BrowseParams.FILTER_VALUE, URLEncode(singleEntry)); if (singleEntry[1] != null)
{
queryParams.put(BrowseParams.FILTER_VALUE[1], URLEncode(
singleEntry[1]));
}
else
{
queryParams.put(BrowseParams.FILTER_VALUE[0], URLEncode(
singleEntry[0]));
}
// Create an entry in the table, and a linked entry // Create an entry in the table, and a linked entry
Cell cell = singleTable.addRow().addCell(); Cell cell = singleTable.addRow().addCell();
cell.addXref(super.generateURL(WITHDRAWN_URL_BASE, queryParams), singleEntry); cell.addXref(super.generateURL(WITHDRAWN_URL_BASE, queryParams), singleEntry[0]);
} }
} }
} }
@@ -623,7 +631,16 @@ public class WithdrawnItems extends AbstractDSpaceTransformer implements
params.scope.setResultsPerPage(RequestUtils.getIntParameter(request, params.scope.setResultsPerPage(RequestUtils.getIntParameter(request,
BrowseParams.RESULTS_PER_PAGE)); BrowseParams.RESULTS_PER_PAGE));
params.scope.setStartsWith(request.getParameter(BrowseParams.STARTS_WITH)); params.scope.setStartsWith(request.getParameter(BrowseParams.STARTS_WITH));
params.scope.setFilterValue(request.getParameter(BrowseParams.FILTER_VALUE)); String filterValue = request.getParameter(BrowseParams.FILTER_VALUE[0]);
if (filterValue == null)
{
filterValue = request.getParameter(BrowseParams.FILTER_VALUE[1]);
}
else
{
params.scope.setAuthorityValue(filterValue);
}
params.scope.setFilterValue(filterValue);
params.scope.setJumpToValue(request.getParameter(BrowseParams.JUMPTO_VALUE)); params.scope.setJumpToValue(request.getParameter(BrowseParams.JUMPTO_VALUE));
params.scope.setJumpToValueLang(request.getParameter(BrowseParams.JUMPTO_VALUE_LANG)); params.scope.setJumpToValueLang(request.getParameter(BrowseParams.JUMPTO_VALUE_LANG));
params.scope.setFilterValueLang(request.getParameter(BrowseParams.FILTER_VALUE_LANG)); params.scope.setFilterValueLang(request.getParameter(BrowseParams.FILTER_VALUE_LANG));
@@ -863,7 +880,7 @@ class BrowseParams
final static String STARTS_WITH = "starts_with"; final static String STARTS_WITH = "starts_with";
final static String FILTER_VALUE = "value"; final static String[] FILTER_VALUE = new String[]{"value","authority"};
final static String FILTER_VALUE_LANG = "value_lang"; final static String FILTER_VALUE_LANG = "value_lang";
@@ -877,7 +894,9 @@ class BrowseParams
if (scope.getFilterValue() != null) if (scope.getFilterValue() != null)
{ {
paramMap.put(BrowseParams.FILTER_VALUE, AbstractDSpaceTransformer.URLEncode( paramMap.put(scope.getAuthorityValue() != null?
BrowseParams.FILTER_VALUE[1]:BrowseParams.FILTER_VALUE[0],
AbstractDSpaceTransformer.URLEncode(
scope.getFilterValue())); scope.getFilterValue()));
} }

View File

@@ -5,8 +5,7 @@
* *
* Date: $Date$ * Date: $Date$
* *
* Copyright (c) 2002, Hewlett-Packard Company and Massachusetts * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved.
* Institute of Technology. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@@ -19,8 +18,7 @@
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* - Neither the name of the Hewlett-Packard Company nor the name of the * - Neither the name of the DSpace Foundation nor the names of its
* Massachusetts Institute of Technology nor the names of their
* contributors may be used to endorse or promote products derived from * contributors may be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
@@ -49,6 +47,7 @@ import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer;
import org.dspace.app.xmlui.wing.Message; import org.dspace.app.xmlui.wing.Message;
import org.dspace.app.xmlui.wing.WingException; import org.dspace.app.xmlui.wing.WingException;
import org.dspace.app.xmlui.wing.element.Body; import org.dspace.app.xmlui.wing.element.Body;
import org.dspace.app.xmlui.wing.element.Button;
import org.dspace.app.xmlui.wing.element.Cell; import org.dspace.app.xmlui.wing.element.Cell;
import org.dspace.app.xmlui.wing.element.CheckBox; import org.dspace.app.xmlui.wing.element.CheckBox;
import org.dspace.app.xmlui.wing.element.Composite; import org.dspace.app.xmlui.wing.element.Composite;
@@ -56,16 +55,22 @@ import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.List; import org.dspace.app.xmlui.wing.element.List;
import org.dspace.app.xmlui.wing.element.PageMeta; import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.app.xmlui.wing.element.Para; import org.dspace.app.xmlui.wing.element.Para;
import org.dspace.app.xmlui.wing.element.Params;
import org.dspace.app.xmlui.wing.element.Row; import org.dspace.app.xmlui.wing.element.Row;
import org.dspace.app.xmlui.wing.element.Select; import org.dspace.app.xmlui.wing.element.Select;
import org.dspace.app.xmlui.wing.element.Table; import org.dspace.app.xmlui.wing.element.Table;
import org.dspace.app.xmlui.wing.element.Text; import org.dspace.app.xmlui.wing.element.Text;
import org.dspace.app.xmlui.wing.element.TextArea; import org.dspace.app.xmlui.wing.element.TextArea;
import org.dspace.app.xmlui.wing.element.Value;
import org.dspace.content.Collection; import org.dspace.content.Collection;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.MetadataField; import org.dspace.content.MetadataField;
import org.dspace.content.MetadataSchema; import org.dspace.content.MetadataSchema;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.Choice;
import org.dspace.content.authority.Choices;
/** /**
* Display a list of all metadata available for this item and allow the user to * Display a list of all metadata available for this item and allow the user to
@@ -77,64 +82,67 @@ import org.dspace.content.MetadataSchema;
public class EditItemMetadataForm extends AbstractDSpaceTransformer { public class EditItemMetadataForm extends AbstractDSpaceTransformer {
/** Language strings */ /** Language strings */
private static final Message T_dspace_home = message("xmlui.general.dspace_home"); private static final Message T_dspace_home = message("xmlui.general.dspace_home");
private static final Message T_submit_update = message("xmlui.general.update"); private static final Message T_submit_update = message("xmlui.general.update");
private static final Message T_submit_return = message("xmlui.general.return"); private static final Message T_submit_return = message("xmlui.general.return");
private static final Message T_item_trail = message("xmlui.administrative.item.general.item_trail"); private static final Message T_item_trail = message("xmlui.administrative.item.general.item_trail");
private static final Message T_template_head = message("xmlui.administrative.item.general.template_head"); private static final Message T_template_head = message("xmlui.administrative.item.general.template_head");
private static final Message T_option_head = message("xmlui.administrative.item.general.option_head"); private static final Message T_option_head = message("xmlui.administrative.item.general.option_head");
private static final Message T_option_status = message("xmlui.administrative.item.general.option_status"); private static final Message T_option_status = message("xmlui.administrative.item.general.option_status");
private static final Message T_option_bitstreams = message("xmlui.administrative.item.general.option_bitstreams"); private static final Message T_option_bitstreams = message("xmlui.administrative.item.general.option_bitstreams");
private static final Message T_option_metadata = message("xmlui.administrative.item.general.option_metadata"); private static final Message T_option_metadata = message("xmlui.administrative.item.general.option_metadata");
private static final Message T_option_view = message("xmlui.administrative.item.general.option_view"); private static final Message T_option_view = message("xmlui.administrative.item.general.option_view");
private static final Message T_title = message("xmlui.administrative.item.EditItemMetadataForm.title"); private static final Message T_title = message("xmlui.administrative.item.EditItemMetadataForm.title");
private static final Message T_trail = message("xmlui.administrative.item.EditItemMetadataForm.trail"); private static final Message T_trail = message("xmlui.administrative.item.EditItemMetadataForm.trail");
private static final Message T_head1 = message("xmlui.administrative.item.EditItemMetadataForm.head1"); private static final Message T_head1 = message("xmlui.administrative.item.EditItemMetadataForm.head1");
private static final Message T_name_label = message("xmlui.administrative.item.EditItemMetadataForm.name_label"); private static final Message T_name_label = message("xmlui.administrative.item.EditItemMetadataForm.name_label");
private static final Message T_value_label = message("xmlui.administrative.item.EditItemMetadataForm.value_label"); private static final Message T_value_label = message("xmlui.administrative.item.EditItemMetadataForm.value_label");
private static final Message T_lang_label = message("xmlui.administrative.item.EditItemMetadataForm.lang_label"); private static final Message T_lang_label = message("xmlui.administrative.item.EditItemMetadataForm.lang_label");
private static final Message T_submit_add = message("xmlui.administrative.item.EditItemMetadataForm.submit_add"); private static final Message T_submit_add = message("xmlui.administrative.item.EditItemMetadataForm.submit_add");
private static final Message T_para1 = message("xmlui.administrative.item.EditItemMetadataForm.para1"); private static final Message T_para1 = message("xmlui.administrative.item.EditItemMetadataForm.para1");
private static final Message T_head2 = message("xmlui.administrative.item.EditItemMetadataForm.head2"); private static final Message T_head2 = message("xmlui.administrative.item.EditItemMetadataForm.head2");
private static final Message T_column1 = message("xmlui.administrative.item.EditItemMetadataForm.column1"); private static final Message T_column1 = message("xmlui.administrative.item.EditItemMetadataForm.column1");
private static final Message T_column2 = message("xmlui.administrative.item.EditItemMetadataForm.column2"); private static final Message T_column2 = message("xmlui.administrative.item.EditItemMetadataForm.column2");
private static final Message T_column3 = message("xmlui.administrative.item.EditItemMetadataForm.column3"); private static final Message T_column3 = message("xmlui.administrative.item.EditItemMetadataForm.column3");
private static final Message T_column4 = message("xmlui.administrative.item.EditItemMetadataForm.column4"); private static final Message T_column4 = message("xmlui.administrative.item.EditItemMetadataForm.column4");
private static final Message T_unlock = message("xmlui.authority.confidence.unlock.help");
public void addPageMeta(PageMeta pageMeta) throws WingException, SQLException
{
Item item = Item.find(context, parameters.getParameterAsInteger("itemID",-1));
Collection owner = item.getOwningCollection();
int collectionID = (owner == null) ? -1 : owner.getID();
pageMeta.addMetadata("choice", "collection").addContent(String.valueOf(collectionID));
pageMeta.addMetadata("title").addContent(T_title);
pageMeta.addTrailLink(contextPath + "/", T_dspace_home);
pageMeta.addTrailLink(contextPath + "/admin/item", T_item_trail);
pageMeta.addTrail().addContent(T_trail);
}
public void addPageMeta(PageMeta pageMeta) throws WingException /**
{ * Add either the simple Ajax response document or the full
pageMeta.addMetadata("title").addContent(T_title); * document with header and full edit item form based on the
* mode parameter. Mode parameter values are set in the Flowscipt
* and can be either 'ajax' or 'normal'.
*/
@SuppressWarnings("unchecked") // the cast is correct
public void addBody(Body body) throws SQLException, WingException
{
// Get our parameters and state
int itemID = parameters.getParameterAsInteger("itemID",-1);
Item item = Item.find(context, itemID);
DCValue[] values = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
Arrays.sort(values, new DCValueComparator());
String baseURL = contextPath+"/admin/item?administrative-continue="+knot.getId();
pageMeta.addTrailLink(contextPath + "/", T_dspace_home); Request request = ObjectModelHelper.getRequest(objectModel);
pageMeta.addTrailLink(contextPath + "/admin/item", T_item_trail); String previousFieldID = request.getParameter("field");
pageMeta.addTrail().addContent(T_trail);
}
/**
* Add either the simple Ajax response document or the full
* document with header and full edit item form based on the
* mode parameter. Mode parameter values are set in the Flowscipt
* and can be either 'ajax' or 'normal'.
*/
@SuppressWarnings("unchecked") // the cast is correct
public void addBody(Body body) throws SQLException, WingException
{
// Get our parameters and state
int itemID = parameters.getParameterAsInteger("itemID",-1);
Item item = Item.find(context, itemID);
DCValue[] values = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
Arrays.sort(values, new DCValueComparator());
String baseURL = contextPath+"/admin/item?administrative-continue="+knot.getId();
Request request = ObjectModelHelper.getRequest(objectModel);
String previousFieldID = request.getParameter("field");
// Metadata editing is the only type of editing available for a template item. // Metadata editing is the only type of editing available for a template item.
boolean editingTemplateItem = false; boolean editingTemplateItem = false;
@@ -147,139 +155,178 @@ public class EditItemMetadataForm extends AbstractDSpaceTransformer {
editingTemplateItem = true; editingTemplateItem = true;
} }
// DIVISION: main // DIVISION: main
Division main = body.addInteractiveDivision("edit-item-status", contextPath+"/admin/item", Division.METHOD_POST,"primary administrative item"); Division main = body.addInteractiveDivision("edit-item-status", contextPath+"/admin/item", Division.METHOD_POST,"primary administrative item");
if (editingTemplateItem) if (editingTemplateItem)
{ {
main.setHead(T_template_head.parameterize(templateCollection.getName())); main.setHead(T_template_head.parameterize(templateCollection.getName()));
} }
else else
{ {
main.setHead(T_option_head); main.setHead(T_option_head);
} }
Collection owner = item.getOwningCollection();
int collectionID = (owner == null) ? -1 : owner.getID();
// LIST: options
// LIST: options if (!editingTemplateItem)
if (!editingTemplateItem)
{ {
List options = main.addList("options",List.TYPE_SIMPLE,"horizontal"); List options = main.addList("options",List.TYPE_SIMPLE,"horizontal");
options.addItem().addXref(baseURL+"&submit_status",T_option_status); options.addItem().addXref(baseURL+"&submit_status",T_option_status);
options.addItem().addXref(baseURL+"&submit_bitstreams",T_option_bitstreams); options.addItem().addXref(baseURL+"&submit_bitstreams",T_option_bitstreams);
options.addItem().addHighlight("bold").addXref(baseURL+"&submit_metadata",T_option_metadata); options.addItem().addHighlight("bold").addXref(baseURL+"&submit_metadata",T_option_metadata);
options.addItem().addXref(baseURL + "&view_item", T_option_view); options.addItem().addXref(baseURL + "&view_item", T_option_view);
} }
// LIST: add new metadata // LIST: add new metadata
List addForm = main.addList("addItemMetadata",List.TYPE_FORM); List addForm = main.addList("addItemMetadata",List.TYPE_FORM);
addForm.setHead(T_head1); addForm.setHead(T_head1);
Select addName = addForm.addItem().addSelect("field"); Select addName = addForm.addItem().addSelect("field");
addName.setLabel(T_name_label); addName.setLabel(T_name_label);
MetadataField[] fields = MetadataField.findAll(context); MetadataField[] fields = MetadataField.findAll(context);
for (MetadataField field : fields) for (MetadataField field : fields)
{ {
int fieldID = field.getFieldID(); int fieldID = field.getFieldID();
MetadataSchema schema = MetadataSchema.find(context, field.getSchemaID()); MetadataSchema schema = MetadataSchema.find(context, field.getSchemaID());
String name = schema.getName() +"."+field.getElement(); String name = schema.getName() +"."+field.getElement();
if (field.getQualifier() != null) if (field.getQualifier() != null)
name += "."+field.getQualifier(); name += "."+field.getQualifier();
addName.addOption(fieldID, name); addName.addOption(fieldID, name);
} }
if (previousFieldID != null) if (previousFieldID != null)
addName.setOptionSelected(previousFieldID); addName.setOptionSelected(previousFieldID);
Composite addComposite = addForm.addItem().addComposite("value"); Composite addComposite = addForm.addItem().addComposite("value");
addComposite.setLabel(T_value_label); addComposite.setLabel(T_value_label);
TextArea addValue = addComposite.addTextArea("value"); TextArea addValue = addComposite.addTextArea("value");
Text addLang = addComposite.addText("language"); Text addLang = addComposite.addText("language");
addValue.setSize(4, 35); addValue.setSize(4, 35);
addLang.setLabel(T_lang_label); addLang.setLabel(T_lang_label);
addLang.setSize(6); addLang.setSize(6);
addForm.addItem().addButton("submit_add").setValue(T_submit_add); addForm.addItem().addButton("submit_add").setValue(T_submit_add);
// PARA: Disclaimer // PARA: Disclaimer
main.addPara(T_para1); main.addPara(T_para1);
Para actions = main.addPara(null,"edit-metadata-actions top" ); Para actions = main.addPara(null,"edit-metadata-actions top" );
actions.addButton("submit_update").setValue(T_submit_update); actions.addButton("submit_update").setValue(T_submit_update);
actions.addButton("submit_return").setValue(T_submit_return); actions.addButton("submit_return").setValue(T_submit_return);
// TABLE: Metadata // TABLE: Metadata
main.addHidden("scope").setValue("*"); main.addHidden("scope").setValue("*");
int index = 1; int index = 1;
Table table = main.addTable("editItemMetadata",1,1); Table table = main.addTable("editItemMetadata",1,1);
table.setHead(T_head2); table.setHead(T_head2);
Row header = table.addRow(Row.ROLE_HEADER); Row header = table.addRow(Row.ROLE_HEADER);
header.addCell().addContent(T_column1); header.addCell().addContent(T_column1);
header.addCell().addContent(T_column2); header.addCell().addContent(T_column2);
header.addCell().addContent(T_column3); header.addCell().addContent(T_column3);
header.addCell().addContent(T_column4); header.addCell().addContent(T_column4);
for(DCValue value : values) ChoiceAuthorityManager cmgr = ChoiceAuthorityManager.getManager();
{ for(DCValue value : values)
String name = value.schema + "_" + value.element; {
if (value.qualifier != null) String name = value.schema + "_" + value.element;
name += "_" + value.qualifier; if (value.qualifier != null)
name += "_" + value.qualifier;
Row row = table.addRow(name,Row.ROLE_DATA,"metadata-value"); Row row = table.addRow(name,Row.ROLE_DATA,"metadata-value");
CheckBox remove = row.addCell().addCheckBox("remove_"+index); CheckBox remove = row.addCell().addCheckBox("remove_"+index);
remove.setLabel("remove"); remove.setLabel("remove");
remove.addOption(index); remove.addOption(index);
Cell cell = row.addCell(); Cell cell = row.addCell();
cell.addContent(name.replaceAll("_", ". ")); cell.addContent(name.replaceAll("_", ". "));
cell.addHidden("name_"+index).setValue(name); cell.addHidden("name_"+index).setValue(name);
TextArea mdValue = row.addCell().addTextArea("value_"+index); // value entry cell:
mdValue.setSize(4,35); Cell mdCell = row.addCell();
mdValue.setValue(value.value); String fieldKey = MetadataAuthorityManager.makeFieldKey(value.schema, value.element, value.qualifier);
Text mdLang = row.addCell().addText("language_"+index); // put up just a selector when preferred choice presentation is select:
mdLang.setSize(6); if (cmgr.isChoicesConfigured(fieldKey) &&
mdLang.setValue(value.language); Params.PRESENTATION_SELECT.equals(cmgr.getPresentation(fieldKey)))
{
Select mdSelect = mdCell.addSelect("value_"+index);
mdSelect.setSize(1);
Choices cs = cmgr.getMatches(fieldKey, value.value, collectionID, 0, 0, null);
if (cs.defaultSelected < 0)
mdSelect.addOption(true, value.value, value.value);
for (int i = 0; i < cs.values.length; ++i)
{
mdSelect.addOption(i == cs.defaultSelected, cs.values[i].value, cs.values[i].label);
}
}
else
{
TextArea mdValue = mdCell.addTextArea("value_"+index);
mdValue.setSize(4,35);
mdValue.setValue(value.value);
boolean isAuth = MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey);
if (isAuth)
{
mdValue.setAuthorityControlled();
mdValue.setAuthorityRequired(MetadataAuthorityManager.getManager().isAuthorityRequired(fieldKey));
Value authValue = mdValue.setAuthorityValue((value.authority == null)?"":value.authority, Choices.getConfidenceText(value.confidence));
// add the "unlock" button to auth field
Button unlock = authValue.addButton("authority_unlock_"+index,"ds-authority-lock");
unlock.setHelp(T_unlock);
}
if (ChoiceAuthorityManager.getManager().isChoicesConfigured(fieldKey))
{
mdValue.setChoices(fieldKey);
mdValue.setChoicesPresentation(Params.PRESENTATION_LOOKUP);
mdValue.setChoicesClosed(ChoiceAuthorityManager.getManager().isClosed(fieldKey));
}
}
Text mdLang = row.addCell().addText("language_"+index);
mdLang.setSize(6);
mdLang.setValue(value.language);
// Tick the index counter; // Tick the index counter;
index++; index++;
} }
// PARA: actions // PARA: actions
actions = main.addPara(null,"edit-metadata-actions bottom" ); actions = main.addPara(null,"edit-metadata-actions bottom" );
actions.addButton("submit_update").setValue(T_submit_update); actions.addButton("submit_update").setValue(T_submit_update);
actions.addButton("submit_return").setValue(T_submit_return); actions.addButton("submit_return").setValue(T_submit_return);
main.addHidden("administrative-continue").setValue(knot.getId()); main.addHidden("administrative-continue").setValue(knot.getId());
} }
/** /**
* Compare two metadata element's name so that they may be sorted. * Compare two metadata element's name so that they may be sorted.
*/ */
class DCValueComparator implements Comparator{ class DCValueComparator implements Comparator{
public int compare(Object arg0, Object arg1) { public int compare(Object arg0, Object arg1) {
final DCValue o1 = (DCValue)arg0; final DCValue o1 = (DCValue)arg0;
final DCValue o2 = (DCValue)arg1; final DCValue o2 = (DCValue)arg1;
final String s1 = o1.schema + o1.element + (o1.qualifier==null?"":("." + o1.qualifier)); final String s1 = o1.schema + o1.element + (o1.qualifier==null?"":("." + o1.qualifier));
final String s2 = o2.schema + o2.element + (o2.qualifier==null?"":("." + o2.qualifier)); final String s2 = o2.schema + o2.element + (o2.qualifier==null?"":("." + o2.qualifier));
return s1.compareTo(s2); return s1.compareTo(s2);
} }
} }
} }

View File

@@ -5,8 +5,7 @@
* *
* Date: $Date$ * Date: $Date$
* *
* Copyright (c) 2002-2005, Hewlett-Packard Company and Massachusetts * Copyright (c) 2002-2009, The DSpace Foundation. All rights reserved.
* Institute of Technology. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are * modification, are permitted provided that the following conditions are
@@ -19,8 +18,7 @@
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* *
* - Neither the name of the Hewlett-Packard Company nor the name of the * - Neither the name of the DSpace Foundation nor the names of its
* Massachusetts Institute of Technology nor the names of their
* contributors may be used to endorse or promote products derived from * contributors may be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
@@ -85,6 +83,7 @@ import org.dspace.content.Collection;
import org.dspace.content.Community; import org.dspace.content.Community;
import org.dspace.content.DCDate; import org.dspace.content.DCDate;
import org.dspace.content.DSpaceObject; import org.dspace.content.DSpaceObject;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context; import org.dspace.core.Context;
import org.dspace.core.LogManager; import org.dspace.core.LogManager;
@@ -217,9 +216,9 @@ public class ConfigurableBrowse extends AbstractDSpaceTransformer implements
else else
{ {
// Add the metadata to the validity // Add the metadata to the validity
for (String singleEntry : browseInfo.getStringResults()) for (String[] singleEntry : browseInfo.getStringResults())
{ {
validity.add(singleEntry); validity.add(singleEntry[0]+"#"+singleEntry[1]);
} }
} }
@@ -313,16 +312,26 @@ public class ConfigurableBrowse extends AbstractDSpaceTransformer implements
message("xmlui.ArtifactBrowser.ConfigurableBrowse." + type + ".column_heading")); message("xmlui.ArtifactBrowser.ConfigurableBrowse." + type + ".column_heading"));
// Iterate each result // Iterate each result
for (String singleEntry : browseInfo.getStringResults()) for (String[] singleEntry : browseInfo.getStringResults())
{ {
// Create a Map of the query parameters for the link // Create a Map of the query parameters for the link
Map<String, String> queryParams = new HashMap<String, String>(); Map<String, String> queryParams = new HashMap<String, String>();
queryParams.put(BrowseParams.TYPE, URLEncode(type)); queryParams.put(BrowseParams.TYPE, URLEncode(type));
queryParams.put(BrowseParams.FILTER_VALUE, URLEncode(singleEntry)); if (singleEntry[1] != null)
{
queryParams.put(BrowseParams.FILTER_VALUE[1], URLEncode(
singleEntry[1]));
}
else
{
queryParams.put(BrowseParams.FILTER_VALUE[0], URLEncode(
singleEntry[0]));
}
// Create an entry in the table, and a linked entry // Create an entry in the table, and a linked entry
Cell cell = singleTable.addRow().addCell(); Cell cell = singleTable.addRow().addCell();
cell.addXref(super.generateURL(BROWSE_URL_BASE, queryParams), singleEntry); cell.addXref(super.generateURL(BROWSE_URL_BASE, queryParams),
singleEntry[0]);
} }
} }
} }
@@ -667,7 +676,14 @@ public class ConfigurableBrowse extends AbstractDSpaceTransformer implements
params.scope.setResultsPerPage(RequestUtils.getIntParameter(request, params.scope.setResultsPerPage(RequestUtils.getIntParameter(request,
BrowseParams.RESULTS_PER_PAGE)); BrowseParams.RESULTS_PER_PAGE));
params.scope.setStartsWith(URLDecode(request.getParameter(BrowseParams.STARTS_WITH))); params.scope.setStartsWith(URLDecode(request.getParameter(BrowseParams.STARTS_WITH)));
params.scope.setFilterValue(URLDecode(request.getParameter(BrowseParams.FILTER_VALUE))); String filterValue = request.getParameter(BrowseParams.FILTER_VALUE[0]);
if (filterValue == null)
{
filterValue = request.getParameter(BrowseParams.FILTER_VALUE[1]);
params.scope.setAuthorityValue(filterValue);
}
params.scope.setFilterValue(filterValue);
params.scope.setJumpToValue(URLDecode(request.getParameter(BrowseParams.JUMPTO_VALUE))); params.scope.setJumpToValue(URLDecode(request.getParameter(BrowseParams.JUMPTO_VALUE)));
params.scope.setJumpToValueLang(URLDecode(request.getParameter(BrowseParams.JUMPTO_VALUE_LANG))); params.scope.setJumpToValueLang(URLDecode(request.getParameter(BrowseParams.JUMPTO_VALUE_LANG)));
params.scope.setFilterValueLang(URLDecode(request.getParameter(BrowseParams.FILTER_VALUE_LANG))); params.scope.setFilterValueLang(URLDecode(request.getParameter(BrowseParams.FILTER_VALUE_LANG)));
@@ -805,7 +821,18 @@ public class ConfigurableBrowse extends AbstractDSpaceTransformer implements
// For a second level browse (ie. items for author), // For a second level browse (ie. items for author),
// get the value we are focussing on (ie. author). // get the value we are focussing on (ie. author).
// (empty string if none). // (empty string if none).
String value = (info.hasValue() ? "\"" + info.getValue() + "\"" : ""); String value = "";
if (info.hasValue())
{
if (bix.isAuthorityIndex())
{
ChoiceAuthorityManager cm = ChoiceAuthorityManager.getManager();
String fk = cm.makeFieldKey(bix.getMetadata(0));
value = "\""+cm.getLabel(fk, info.getValue(), null)+"\"";
}
else
value = "\"" + info.getValue() + "\"";
}
// Get the name of any scoping element (collection / community) // Get the name of any scoping element (collection / community)
String scopeName = ""; String scopeName = "";
@@ -907,7 +934,7 @@ class BrowseParams
final static String STARTS_WITH = "starts_with"; final static String STARTS_WITH = "starts_with";
final static String FILTER_VALUE = "value"; final static String[] FILTER_VALUE = new String[]{"value","authority"};
final static String FILTER_VALUE_LANG = "value_lang"; final static String FILTER_VALUE_LANG = "value_lang";
@@ -924,7 +951,9 @@ class BrowseParams
if (scope.getFilterValue() != null) if (scope.getFilterValue() != null)
{ {
paramMap.put(BrowseParams.FILTER_VALUE, AbstractDSpaceTransformer.URLEncode( paramMap.put(scope.getAuthorityValue() != null?
BrowseParams.FILTER_VALUE[1]:BrowseParams.FILTER_VALUE[0],
AbstractDSpaceTransformer.URLEncode(
scope.getFilterValue())); scope.getFilterValue()));
} }
@@ -984,4 +1013,3 @@ class BrowseParams
} }
} }
}; };

View File

@@ -0,0 +1,338 @@
/*
* 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;
}
}

View File

@@ -51,6 +51,7 @@ import org.apache.log4j.Logger;
import org.dspace.app.util.DCInput; import org.dspace.app.util.DCInput;
import org.dspace.app.util.DCInputSet; import org.dspace.app.util.DCInputSet;
import org.dspace.app.util.DCInputsReader; import org.dspace.app.util.DCInputsReader;
import org.dspace.app.util.DCInputsReaderException;
import org.dspace.app.xmlui.utils.UIException; import org.dspace.app.xmlui.utils.UIException;
import org.dspace.app.xmlui.aspect.submission.AbstractSubmissionStep; import org.dspace.app.xmlui.aspect.submission.AbstractSubmissionStep;
import org.dspace.app.xmlui.aspect.submission.FlowUtils; import org.dspace.app.xmlui.aspect.submission.FlowUtils;
@@ -61,7 +62,10 @@ import org.dspace.app.xmlui.wing.element.CheckBox;
import org.dspace.app.xmlui.wing.element.Composite; import org.dspace.app.xmlui.wing.element.Composite;
import org.dspace.app.xmlui.wing.element.Division; import org.dspace.app.xmlui.wing.element.Division;
import org.dspace.app.xmlui.wing.element.Field; import org.dspace.app.xmlui.wing.element.Field;
import org.dspace.app.xmlui.wing.element.Instance;
import org.dspace.app.xmlui.wing.element.List; import org.dspace.app.xmlui.wing.element.List;
import org.dspace.app.xmlui.wing.element.PageMeta;
import org.dspace.app.xmlui.wing.element.Params;
import org.dspace.app.xmlui.wing.element.Radio; import org.dspace.app.xmlui.wing.element.Radio;
import org.dspace.app.xmlui.wing.element.Select; import org.dspace.app.xmlui.wing.element.Select;
import org.dspace.app.xmlui.wing.element.Text; import org.dspace.app.xmlui.wing.element.Text;
@@ -74,7 +78,10 @@ import org.dspace.content.DCPersonName;
import org.dspace.content.DCSeriesNumber; import org.dspace.content.DCSeriesNumber;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.authority.MetadataAuthorityManager;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.Choice;
import org.dspace.content.authority.Choices;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@@ -128,7 +135,7 @@ public class DescribeStep extends AbstractSubmissionStep
* Ensure that the inputs reader has been initialized, this method may be * Ensure that the inputs reader has been initialized, this method may be
* called multiple times with no ill-effect. * called multiple times with no ill-effect.
*/ */
private static void initializeInputsReader() throws ServletException private static void initializeInputsReader() throws DCInputsReaderException
{ {
if (INPUTS_READER == null) if (INPUTS_READER == null)
INPUTS_READER = new DCInputsReader(); INPUTS_READER = new DCInputsReader();
@@ -155,12 +162,22 @@ public class DescribeStep extends AbstractSubmissionStep
this.requireStep = true; this.requireStep = true;
//Ensure that the InputsReader is initialized. //Ensure that the InputsReader is initialized.
initializeInputsReader(); try
{
initializeInputsReader();
}
catch (DCInputsReaderException e)
{
throw new ServletException(e);
}
} }
public void addPageMeta(PageMeta pageMeta) throws SAXException, WingException, public void addPageMeta(PageMeta pageMeta) throws SAXException, WingException,
UIException, SQLException, IOException, AuthorizeException UIException, SQLException, IOException, AuthorizeException
{ {
int collectionID = submission.getCollection().getID();
pageMeta.addMetadata("choice", "collection").addContent(String.valueOf(collectionID));
String jumpTo = submissionInfo.getJumpToField(); String jumpTo = submissionInfo.getJumpToField();
if (jumpTo != null) if (jumpTo != null)
pageMeta.addMetadata("page","jumpTo").addContent(jumpTo); pageMeta.addMetadata("page","jumpTo").addContent(jumpTo);
@@ -181,7 +198,7 @@ public class DescribeStep extends AbstractSubmissionStep
inputSet = getInputsReader().getInputs(submission.getCollection().getHandle()); inputSet = getInputsReader().getInputs(submission.getCollection().getHandle());
inputs = inputSet.getPageRows(getPage()-1, submission.hasMultipleTitles(), submission.isPublishedBefore()); inputs = inputSet.getPageRows(getPage()-1, submission.hasMultipleTitles(), submission.isPublishedBefore());
} }
catch (ServletException se) catch (DCInputsReaderException se)
{ {
throw new UIException(se); throw new UIException(se);
} }
@@ -212,9 +229,18 @@ public class DescribeStep extends AbstractSubmissionStep
DCValue[] dcValues = item.getMetadata(schema, element, qualifier, Item.ANY); DCValue[] dcValues = item.getMetadata(schema, element, qualifier, Item.ANY);
String fieldName = FlowUtils.getFieldName(dcInput); String fieldName = FlowUtils.getFieldName(dcInput);
String inputType = dcInput.getInputType(); String inputType = dcInput.getInputType();
if (inputType.equals("name"))
// if this field is configured as choice control and its
// presentation format is SELECT, render it as select field:
String fieldKey = MetadataAuthorityManager.makeFieldKey(schema, element, qualifier);
ChoiceAuthorityManager cmgr = ChoiceAuthorityManager.getManager();
if (cmgr.isChoicesConfigured(fieldKey) &&
Params.PRESENTATION_SELECT.equals(cmgr.getPresentation(fieldKey)))
{
renderChoiceSelectField(form, fieldName, collection, dcInput, dcValues, readonly);
}
else if (inputType.equals("name"))
{ {
renderNameField(form, fieldName, dcInput, dcValues, readonly); renderNameField(form, fieldName, dcInput, dcValues, readonly);
} }
@@ -311,11 +337,12 @@ public class DescribeStep extends AbstractSubmissionStep
{ {
inputSet = getInputsReader().getInputs(submission.getCollection().getHandle()); inputSet = getInputsReader().getInputs(submission.getCollection().getHandle());
} }
catch (ServletException se) catch (DCInputsReaderException se)
{ {
throw new UIException(se); throw new UIException(se);
} }
MetadataAuthorityManager mam = MetadataAuthorityManager.getManager();
DCInput[] inputs = inputSet.getPageRows(getPage()-1, submission.hasMultipleTitles(), submission.isPublishedBefore()); DCInput[] inputs = inputSet.getPageRows(getPage()-1, submission.hasMultipleTitles(), submission.isPublishedBefore());
for (DCInput input : inputs) for (DCInput input : inputs)
@@ -369,7 +396,18 @@ public class DescribeStep extends AbstractSubmissionStep
//Only display this field if we have a value to display //Only display this field if we have a value to display
if (displayValue!=null && displayValue.length()>0) if (displayValue!=null && displayValue.length()>0)
{ {
describeSection.addLabel(input.getLabel()); describeSection.addLabel(input.getLabel());
if (mam.isAuthorityControlled(value.schema, value.element, value.qualifier))
{
String confidence = (value.authority != null && value.authority.length() > 0) ?
Choices.getConfidenceText(value.confidence).toLowerCase() :
"blank";
org.dspace.app.xmlui.wing.element.Item authItem =
describeSection.addItem("submit-review-field-with-authority", "ds-authority-confidence cf-"+confidence);
authItem.addContent(displayValue);
}
else
describeSection.addItem(displayValue); describeSection.addItem(displayValue);
} }
} // For each DCValue } // For each DCValue
@@ -414,6 +452,19 @@ public class DescribeStep extends AbstractSubmissionStep
fullName.enableAddOperation(); fullName.enableAddOperation();
if ((dcInput.isRepeatable() || dcValues.length > 1) && !readonly) if ((dcInput.isRepeatable() || dcValues.length > 1) && !readonly)
fullName.enableDeleteOperation(); fullName.enableDeleteOperation();
String fieldKey = MetadataAuthorityManager.makeFieldKey(dcInput.getSchema(), dcInput.getElement(), dcInput.getQualifier());
boolean isAuthorityControlled = MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey);
if (isAuthorityControlled)
{
fullName.setAuthorityControlled();
fullName.setAuthorityRequired(MetadataAuthorityManager.getManager().isAuthorityRequired(fieldKey));
}
if (ChoiceAuthorityManager.getManager().isChoicesConfigured(fieldKey))
{
fullName.setChoices(fieldKey);
fullName.setChoicesPresentation(ChoiceAuthorityManager.getManager().getPresentation(fieldKey));
fullName.setChoicesClosed(ChoiceAuthorityManager.getManager().isClosed(fieldKey));
}
// Setup the first and last name // Setup the first and last name
lastName.setLabel(T_last_name_help); lastName.setLabel(T_last_name_help);
@@ -435,17 +486,32 @@ public class DescribeStep extends AbstractSubmissionStep
lastName.addInstance().setValue(dpn.getLastName()); lastName.addInstance().setValue(dpn.getLastName());
firstName.addInstance().setValue(dpn.getFirstNames()); firstName.addInstance().setValue(dpn.getFirstNames());
fullName.addInstance().setValue(dcValue.value); Instance fi = fullName.addInstance();
fi.setValue(dcValue.value);
if (isAuthorityControlled)
{
if (dcValue.authority == null || dcValue.authority.equals(""))
fi.setAuthorityValue("", "blank");
else
fi.setAuthorityValue(dcValue.authority, Choices.getConfidenceText(dcValue.confidence));
} }
} }
}
else if (dcValues.length == 1) else if (dcValues.length == 1)
{ {
DCPersonName dpn = new DCPersonName(dcValues[0].value); DCPersonName dpn = new DCPersonName(dcValues[0].value);
lastName.setValue(dpn.getLastName()); lastName.setValue(dpn.getLastName());
firstName.setValue(dpn.getFirstNames()); firstName.setValue(dpn.getFirstNames());
if (isAuthorityControlled)
{
if (dcValues[0].authority == null || dcValues[0].authority.equals(""))
lastName.setAuthorityValue("", "blank");
else
lastName.setAuthorityValue(dcValues[0].authority, Choices.getConfidenceText(dcValues[0].confidence));
} }
} }
}
/** /**
* Render a date field to the DRI document. The date field consists of * Render a date field to the DRI document. The date field consists of
@@ -694,6 +760,19 @@ public class DescribeStep extends AbstractSubmissionStep
// Setup the text area // Setup the text area
textArea.setLabel(dcInput.getLabel()); textArea.setLabel(dcInput.getLabel());
textArea.setHelp(cleanHints(dcInput.getHints())); textArea.setHelp(cleanHints(dcInput.getHints()));
String fieldKey = MetadataAuthorityManager.makeFieldKey(dcInput.getSchema(), dcInput.getElement(), dcInput.getQualifier());
boolean isAuth = MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey);
if (isAuth)
{
textArea.setAuthorityControlled();
textArea.setAuthorityRequired(MetadataAuthorityManager.getManager().isAuthorityRequired(fieldKey));
}
if (ChoiceAuthorityManager.getManager().isChoicesConfigured(fieldKey))
{
textArea.setChoices(fieldKey);
textArea.setChoicesPresentation(ChoiceAuthorityManager.getManager().getPresentation(fieldKey));
textArea.setChoicesClosed(ChoiceAuthorityManager.getManager().isClosed(fieldKey));
}
if (dcInput.isRequired()) if (dcInput.isRequired())
textArea.setRequired(); textArea.setRequired();
if (isFieldInError(fieldName)) if (isFieldInError(fieldName))
@@ -713,12 +792,87 @@ public class DescribeStep extends AbstractSubmissionStep
{ {
for (DCValue dcValue : dcValues) for (DCValue dcValue : dcValues)
{ {
textArea.addInstance().setValue(dcValue.value); Instance ti = textArea.addInstance();
ti.setValue(dcValue.value);
if (isAuth)
{
if (dcValue.authority == null || dcValue.authority.equals(""))
ti.setAuthorityValue("", "blank");
else
ti.setAuthorityValue(dcValue.authority, Choices.getConfidenceText(dcValue.confidence));
} }
} }
}
else if (dcValues.length == 1) else if (dcValues.length == 1)
{ {
textArea.setValue(dcValues[0].value); textArea.setValue(dcValues[0].value);
if (isAuth)
{
if (dcValues[0].authority == null || dcValues[0].authority.equals(""))
textArea.setAuthorityValue("", "blank");
else
textArea.setAuthorityValue(dcValues[0].authority, Choices.getConfidenceText(dcValues[0].confidence));
}
}
}
/**
* Render a dropdown field for a choice-controlled input of the
* 'select' presentation to the DRI document. The dropdown field
* consists of an HTML select box.
*
* @param form
* The form list to add the field too
* @param fieldName
* The field's name.
* @param dcInput
* The field's input deffinition
* @param dcValues
* The field's pre-existing values.
*/
private void renderChoiceSelectField(List form, String fieldName, Collection coll, DCInput dcInput, DCValue[] dcValues, boolean readonly) throws WingException
{
String fieldKey = MetadataAuthorityManager.makeFieldKey(dcInput.getSchema(), dcInput.getElement(), dcInput.getQualifier());
if (MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey))
throw new WingException("Field "+fieldKey+" has choice presentation of type \""+Params.PRESENTATION_SELECT+"\", it may NOT be authority-controlled.");
// Plain old select list.
Select select = form.addItem().addSelect(fieldName,"submit-select");
//Setup the select field
select.setLabel(dcInput.getLabel());
select.setHelp(cleanHints(dcInput.getHints()));
if (dcInput.isRequired())
select.setRequired();
if (isFieldInError(fieldName))
select.addError(T_required_field);
if (dcInput.isRepeatable() || dcValues.length > 1)
{
// Use the multiple functionality from the HTML
// widget instead of DRI's version.
select.setMultiple();
select.setSize(6);
}
else
select.setSize(1);
if (readonly)
{
select.setDisabled();
}
Choices cs = ChoiceAuthorityManager.getManager().getMatches(fieldKey, "", coll.getID(), 0, 0, null);
if (dcValues.length == 0)
select.addOption(true, "", "");
for (Choice c : cs.values)
{
select.addOption(c.value, c.label);
}
// Setup the field's pre-selected values
for (DCValue dcValue : dcValues)
{
select.setOptionSelected(dcValue.value);
} }
} }
@@ -879,6 +1033,20 @@ public class DescribeStep extends AbstractSubmissionStep
// Setup the select field // Setup the select field
text.setLabel(dcInput.getLabel()); text.setLabel(dcInput.getLabel());
text.setHelp(cleanHints(dcInput.getHints())); text.setHelp(cleanHints(dcInput.getHints()));
String fieldKey = MetadataAuthorityManager.makeFieldKey(dcInput.getSchema(), dcInput.getElement(), dcInput.getQualifier());
boolean isAuth = MetadataAuthorityManager.getManager().isAuthorityControlled(fieldKey);
if (isAuth)
{
text.setAuthorityControlled();
text.setAuthorityRequired(MetadataAuthorityManager.getManager().isAuthorityRequired(fieldKey));
}
if (ChoiceAuthorityManager.getManager().isChoicesConfigured(fieldKey))
{
text.setChoices(fieldKey);
text.setChoicesPresentation(ChoiceAuthorityManager.getManager().getPresentation(fieldKey));
text.setChoicesClosed(ChoiceAuthorityManager.getManager().isClosed(fieldKey));
}
if (dcInput.isRequired()) if (dcInput.isRequired())
text.setRequired(); text.setRequired();
if (isFieldInError(fieldName)) if (isFieldInError(fieldName))
@@ -898,14 +1066,29 @@ public class DescribeStep extends AbstractSubmissionStep
{ {
for (DCValue dcValue : dcValues) for (DCValue dcValue : dcValues)
{ {
text.addInstance().setValue(dcValue.value); Instance ti = text.addInstance();
ti.setValue(dcValue.value);
if (isAuth)
{
if (dcValue.authority == null || dcValue.authority.equals(""))
ti.setAuthorityValue("", "blank");
else
ti.setAuthorityValue(dcValue.authority, Choices.getConfidenceText(dcValue.confidence));
} }
} }
}
else if (dcValues.length == 1) else if (dcValues.length == 1)
{ {
text.setValue(dcValues[0].value); text.setValue(dcValues[0].value);
if (isAuth)
{
if (dcValues[0].authority == null || dcValues[0].authority.equals(""))
text.setAuthorityValue("", "blank");
else
text.setAuthorityValue(dcValues[0].authority, Choices.getConfidenceText(dcValues[0].confidence));
} }
} }
}

View File

@@ -0,0 +1,126 @@
/*
* AJAXMenuGenerator.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.cocoon;
import java.io.IOException;
import java.sql.SQLException;
import org.apache.cocoon.ProcessingException;
import org.apache.cocoon.ResourceNotFoundException;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.generation.AbstractGenerator;
import org.dspace.app.xmlui.objectmanager.AbstractAdapter;
import org.dspace.app.xmlui.objectmanager.ContainerAdapter;
import org.dspace.app.xmlui.objectmanager.ItemAdapter;
import org.dspace.app.xmlui.objectmanager.RepositoryAdapter;
import org.dspace.app.xmlui.utils.ContextUtil;
import org.dspace.app.xmlui.wing.WingException;
import org.dspace.content.Collection;
import org.dspace.content.Community;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.authority.Choices;
import org.dspace.content.authority.Choice;
import org.dspace.content.authority.ChoiceAuthorityManager;
import org.dspace.content.authority.ChoicesXMLGenerator;
import org.dspace.content.crosswalk.CrosswalkException;
import org.dspace.core.ConfigurationManager;
import org.dspace.core.Context;
import org.dspace.handle.HandleManager;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.AttributesImpl;
import org.apache.log4j.Logger;
/**
* Generate XML description of Choice values to be used by
* AJAX UI client.
*
* @author Larry Stone
*/
public class AJAXMenuGenerator extends AbstractGenerator
{
private static Logger log = Logger.getLogger(AJAXMenuGenerator.class);
/**
* Generate the AJAX response Document.
*
* Looks for request paraemters:
* field - MD field key, i.e. form key, REQUIRED.
* start - index to start from, default 0.
* limit - max number of lines, default 1000.
* format - opt. result XML/XHTML format: "select", "ul", "xml"(default)
* locale - explicit locale, pass to choice plugin
*/
public void generate()
throws IOException, SAXException, ProcessingException
{
int start = 0;
int limit = 1000;
int collection = -1;
String format = parameters.getParameter("format",null);
String field = parameters.getParameter("field",null);
String sstart = parameters.getParameter("start",null);
if (sstart != null && sstart.length() > 0)
start = Integer.parseInt(sstart);
String slimit = parameters.getParameter("limit",null);
if (slimit != null && slimit.length() > 0)
limit = Integer.parseInt(slimit);
String scoll = parameters.getParameter("collection",null);
if (scoll != null && scoll.length() > 0)
collection = Integer.parseInt(scoll);
String query = parameters.getParameter("query",null);
// localization
String locale = parameters.getParameter("locale",null);
log.debug("AJAX menu generator: field="+field+", query="+query+", start="+sstart+", limit="+slimit+", format="+format+", field="+field+", query="+query+", start="+sstart+", limit="+slimit+", format="+format+", locale = "+locale);
Choices result =
ChoiceAuthorityManager.getManager().getMatches(field, query, collection, start, limit, locale);
log.debug("Result count = "+result.values.length+", default="+result.defaultSelected);
ChoicesXMLGenerator.generate(result, format, contentHandler);
}
}

View File

@@ -46,6 +46,7 @@ import org.dspace.content.Bitstream;
import org.dspace.content.Bundle; import org.dspace.content.Bundle;
import org.dspace.content.DCValue; import org.dspace.content.DCValue;
import org.dspace.content.Item; import org.dspace.content.Item;
import org.dspace.content.authority.Choices;
import org.dspace.content.crosswalk.CrosswalkException; import org.dspace.content.crosswalk.CrosswalkException;
import org.dspace.content.crosswalk.DisseminationCrosswalk; import org.dspace.content.crosswalk.DisseminationCrosswalk;
import org.dspace.core.ConfigurationManager; import org.dspace.core.ConfigurationManager;
@@ -125,7 +126,7 @@ public class ItemAdapter extends AbstractAdapter
/** Return the item */ /** Return the item */
public Item getItem() public Item getItem()
{ {
return this.item; return this.item;
} }
@@ -145,9 +146,9 @@ public class ItemAdapter extends AbstractAdapter
*/ */
protected String getMETSOBJID() protected String getMETSOBJID()
{ {
if (item.getHandle() != null) if (item.getHandle() != null)
return contextPath+"/handle/" + item.getHandle(); return contextPath+"/handle/" + item.getHandle();
return null; return null;
} }
/** /**
@@ -164,9 +165,9 @@ public class ItemAdapter extends AbstractAdapter
protected String getMETSID() protected String getMETSID()
{ {
if (item.getHandle() == null) if (item.getHandle() == null)
return "item:"+item.getID(); return "item:"+item.getID();
else else
return "hdl:"+item.getHandle(); return "hdl:"+item.getHandle();
} }
/** /**
@@ -174,7 +175,7 @@ public class ItemAdapter extends AbstractAdapter
*/ */
protected String getMETSProfile() throws WingException protected String getMETSProfile() throws WingException
{ {
return "DSPACE METS SIP Profile 1.0"; return "DSPACE METS SIP Profile 1.0";
} }
/** /**
@@ -190,7 +191,7 @@ public class ItemAdapter extends AbstractAdapter
*/ */
protected String getFileID(Bitstream bitstream) protected String getFileID(Bitstream bitstream)
{ {
return "file_" + bitstream.getID(); return "file_" + bitstream.getID();
} }
/** /**
@@ -198,7 +199,7 @@ public class ItemAdapter extends AbstractAdapter
*/ */
protected String getGroupFileID(Bitstream bitstream) protected String getGroupFileID(Bitstream bitstream)
{ {
return "group_file_" + bitstream.getID(); return "group_file_" + bitstream.getID();
} }
/** /**
@@ -229,144 +230,148 @@ public class ItemAdapter extends AbstractAdapter
*/ */
protected void renderDescriptiveSection() throws WingException, SAXException, CrosswalkException, IOException, SQLException protected void renderDescriptiveSection() throws WingException, SAXException, CrosswalkException, IOException, SQLException
{ {
AttributeMap attributes; AttributeMap attributes;
String groupID = getGenericID("group_dmd_"); String groupID = getGenericID("group_dmd_");
dmdSecIDS = new StringBuffer(); dmdSecIDS = new StringBuffer();
// Add DIM descriptive metadata if it was requested or if no metadata types // Add DIM descriptive metadata if it was requested or if no metadata types
// were specified. Further more since this is the default type we also use a // were specified. Further more since this is the default type we also use a
// faster rendering method that the crosswalk API. // faster rendering method that the crosswalk API.
if(dmdTypes.size() == 0 || dmdTypes.contains("DIM")) if(dmdTypes.size() == 0 || dmdTypes.contains("DIM"))
{ {
// Metadata element's ID // Metadata element's ID
String dmdID = getGenericID("dmd_"); String dmdID = getGenericID("dmd_");
// Keep track of all descriptive sections // Keep track of all descriptive sections
dmdSecIDS.append("" + dmdID); dmdSecIDS.append("" + dmdID);
//////////////////////////////// ////////////////////////////////
// Start a metadata wrapper // Start a metadata wrapper
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("ID", dmdID); attributes.put("ID", dmdID);
attributes.put("GROUPID", groupID); attributes.put("GROUPID", groupID);
startElement(METS, "dmdSec", attributes); startElement(METS, "dmdSec", attributes);
//////////////////////////////// ////////////////////////////////
// Start a metadata wrapper // Start a metadata wrapper
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("MDTYPE","OTHER"); attributes.put("MDTYPE","OTHER");
attributes.put("OTHERMDTYPE", "DIM"); attributes.put("OTHERMDTYPE", "DIM");
startElement(METS,"mdWrap",attributes); startElement(METS,"mdWrap",attributes);
// //////////////////////////////// // ////////////////////////////////
// Start the xml data // Start the xml data
startElement(METS,"xmlData"); startElement(METS,"xmlData");
// /////////////////////////////// // ///////////////////////////////
// Start the DIM element // Start the DIM element
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("dspaceType", Constants.typeText[item.getType()]); attributes.put("dspaceType", Constants.typeText[item.getType()]);
if (item.isWithdrawn()) if (item.isWithdrawn())
attributes.put("withdrawn", "y"); attributes.put("withdrawn", "y");
startElement(DIM,"dim",attributes); startElement(DIM,"dim",attributes);
DCValue[] dcvs = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); DCValue[] dcvs = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY);
for (DCValue dcv : dcvs) for (DCValue dcv : dcvs)
{ {
// /////////////////////////////// // ///////////////////////////////
// Field element for each metadata field. // Field element for each metadata field.
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("mdschema",dcv.schema); attributes.put("mdschema",dcv.schema);
attributes.put("element", dcv.element); attributes.put("element", dcv.element);
if (dcv.qualifier != null) if (dcv.qualifier != null)
attributes.put("qualifier", dcv.qualifier); attributes.put("qualifier", dcv.qualifier);
if (dcv.language != null) if (dcv.language != null)
attributes.put("language", dcv.language); attributes.put("language", dcv.language);
if (dcv.authority != null || dcv.confidence != Choices.CF_UNSET)
{
attributes.put("authority", dcv.authority);
attributes.put("confidence", Choices.getConfidenceText(dcv.confidence));
}
startElement(DIM,"field",attributes);
sendCharacters(dcv.value);
endElement(DIM,"field");
}
startElement(DIM,"field",attributes); // ///////////////////////////////
sendCharacters(dcv.value); // End the DIM element
endElement(DIM,"field"); endElement(DIM,"dim");
}
// /////////////////////////////// // ////////////////////////////////
// End the DIM element // End elements
endElement(DIM,"dim"); endElement(METS,"xmlData");
endElement(METS,"mdWrap");
endElement(METS, "dmdSec");
// //////////////////////////////// }
// End elements
endElement(METS,"xmlData");
endElement(METS,"mdWrap");
endElement(METS, "dmdSec");
}
// Add any extra crosswalks that may configured. // Add any extra crosswalks that may configured.
for (String dmdType : dmdTypes) for (String dmdType : dmdTypes)
{ {
// If DIM was requested then it was generated above without using // If DIM was requested then it was generated above without using
// the crosswalk API. So we can skip this one. // the crosswalk API. So we can skip this one.
if ("DIM".equals(dmdType)) if ("DIM".equals(dmdType))
continue; continue;
DisseminationCrosswalk crosswalk = getDisseminationCrosswalk(dmdType); DisseminationCrosswalk crosswalk = getDisseminationCrosswalk(dmdType);
if (crosswalk == null) if (crosswalk == null)
continue; continue;
String dmdID = getGenericID("dmd_"); String dmdID = getGenericID("dmd_");
// Add our id to the list. // Add our id to the list.
dmdSecIDS.append(" " + dmdID); dmdSecIDS.append(" " + dmdID);
//////////////////////////////// ////////////////////////////////
// Start a metadata wrapper // Start a metadata wrapper
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("ID", dmdID); attributes.put("ID", dmdID);
attributes.put("GROUPID", groupID); attributes.put("GROUPID", groupID);
startElement(METS, "dmdSec", attributes); startElement(METS, "dmdSec", attributes);
//////////////////////////////// ////////////////////////////////
// Start a metadata wrapper // Start a metadata wrapper
attributes = new AttributeMap(); attributes = new AttributeMap();
if (isDefinedMETStype(dmdType)) if (isDefinedMETStype(dmdType))
{ {
attributes.put("MDTYPE", dmdType); attributes.put("MDTYPE", dmdType);
} }
else else
{ {
attributes.put("MDTYPE","OTHER"); attributes.put("MDTYPE","OTHER");
attributes.put("OTHERMDTYPE", dmdType); attributes.put("OTHERMDTYPE", dmdType);
} }
startElement(METS,"mdWrap",attributes); startElement(METS,"mdWrap",attributes);
// //////////////////////////////// // ////////////////////////////////
// Start the xml data // Start the xml data
startElement(METS,"xmlData"); startElement(METS,"xmlData");
// /////////////////////////////// // ///////////////////////////////
// Send the actual XML content // Send the actual XML content
try { try {
Element dissemination = crosswalk.disseminateElement(item); Element dissemination = crosswalk.disseminateElement(item);
SAXFilter filter = new SAXFilter(contentHandler, lexicalHandler, namespaces); SAXFilter filter = new SAXFilter(contentHandler, lexicalHandler, namespaces);
// Allow the basics for XML // Allow the basics for XML
filter.allowElements().allowIgnorableWhitespace().allowCharacters().allowCDATA().allowPrefixMappings(); filter.allowElements().allowIgnorableWhitespace().allowCharacters().allowCDATA().allowPrefixMappings();
SAXOutputter outputter = new SAXOutputter(); SAXOutputter outputter = new SAXOutputter();
outputter.setContentHandler(filter); outputter.setContentHandler(filter);
outputter.setLexicalHandler(filter); outputter.setLexicalHandler(filter);
outputter.output(dissemination); outputter.output(dissemination);
} }
catch (JDOMException jdome) catch (JDOMException jdome)
{ {
throw new WingException(jdome); throw new WingException(jdome);
} }
catch (AuthorizeException ae) catch (AuthorizeException ae)
{ {
// just ignore the authorize exception and continue on with // just ignore the authorize exception and continue on with
//out parsing the xml document. //out parsing the xml document.
} }
// //////////////////////////////// // ////////////////////////////////
@@ -374,78 +379,78 @@ public class ItemAdapter extends AbstractAdapter
endElement(METS,"xmlData"); endElement(METS,"xmlData");
endElement(METS,"mdWrap"); endElement(METS,"mdWrap");
endElement(METS, "dmdSec"); endElement(METS, "dmdSec");
} }
// Check to see if there is an in-line MODS document // Check to see if there is an in-line MODS document
// stored as a bitstream. If there is then we should also // stored as a bitstream. If there is then we should also
// include these metadata in our METS document. However // include these metadata in our METS document. However
// we don't really know what the document describes, so we // we don't really know what the document describes, so we
// but it in it's own dmd group. // but it in it's own dmd group.
Boolean include = ConfigurationManager.getBooleanProperty("xmlui.bitstream.mods"); Boolean include = ConfigurationManager.getBooleanProperty("xmlui.bitstream.mods");
if (include && dmdTypes.contains("MODS")) if (include && dmdTypes.contains("MODS"))
{ {
// Generate a second group id for any extra metadata added. // Generate a second group id for any extra metadata added.
String groupID2 = getGenericID("group_dmd_"); String groupID2 = getGenericID("group_dmd_");
Bundle[] bundles = item.getBundles("METADATA"); Bundle[] bundles = item.getBundles("METADATA");
for (Bundle bundle : bundles) for (Bundle bundle : bundles)
{ {
Bitstream bitstream = bundle.getBitstreamByName("MODS.xml"); Bitstream bitstream = bundle.getBitstreamByName("MODS.xml");
if (bitstream == null) if (bitstream == null)
continue; continue;
String dmdID = getGenericID("dmd_"); String dmdID = getGenericID("dmd_");
//////////////////////////////// ////////////////////////////////
// Start a metadata wrapper // Start a metadata wrapper
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("ID", dmdID); attributes.put("ID", dmdID);
attributes.put("GROUPID", groupID2); attributes.put("GROUPID", groupID2);
startElement(METS, "dmdSec", attributes); startElement(METS, "dmdSec", attributes);
//////////////////////////////// ////////////////////////////////
// Start a metadata wrapper // Start a metadata wrapper
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("MDTYPE", "MODS"); attributes.put("MDTYPE", "MODS");
startElement(METS,"mdWrap",attributes); startElement(METS,"mdWrap",attributes);
// //////////////////////////////// // ////////////////////////////////
// Start the xml data // Start the xml data
startElement(METS,"xmlData"); startElement(METS,"xmlData");
// /////////////////////////////// // ///////////////////////////////
// Send the actual XML content // Send the actual XML content
SAXFilter filter = new SAXFilter(contentHandler, lexicalHandler, namespaces); SAXFilter filter = new SAXFilter(contentHandler, lexicalHandler, namespaces);
// Allow the basics for XML // Allow the basics for XML
filter.allowElements().allowIgnorableWhitespace().allowCharacters().allowCDATA().allowPrefixMappings(); filter.allowElements().allowIgnorableWhitespace().allowCharacters().allowCDATA().allowPrefixMappings();
XMLReader reader = XMLReaderFactory.createXMLReader(); XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setContentHandler(filter); reader.setContentHandler(filter);
reader.setProperty("http://xml.org/sax/properties/lexical-handler", filter); reader.setProperty("http://xml.org/sax/properties/lexical-handler", filter);
try { try {
InputStream is = bitstream.retrieve(); InputStream is = bitstream.retrieve();
reader.parse(new InputSource(is)); reader.parse(new InputSource(is));
} }
catch (AuthorizeException ae) catch (AuthorizeException ae)
{ {
// just ignore the authorize exception and continue on with // just ignore the authorize exception and continue on with
//out parsing the xml document. //out parsing the xml document.
} }
// //////////////////////////////// // ////////////////////////////////
// End elements // End elements
endElement(METS,"xmlData"); endElement(METS,"xmlData");
endElement(METS,"mdWrap"); endElement(METS,"mdWrap");
endElement(METS, "dmdSec"); endElement(METS, "dmdSec");
} }
} }
} }
@@ -464,12 +469,12 @@ public class ItemAdapter extends AbstractAdapter
protected void renderAdministrativeSection() throws WingException, SAXException, CrosswalkException, IOException, SQLException protected void renderAdministrativeSection() throws WingException, SAXException, CrosswalkException, IOException, SQLException
{ {
AttributeMap attributes; AttributeMap attributes;
String groupID; String groupID;
//Only create an <amdSec>, if we have amdTypes (or sub-sections) specified... //Only create an <amdSec>, if we have amdTypes (or sub-sections) specified...
// (this keeps our METS file small, by default, and hides all our admin metadata) // (this keeps our METS file small, by default, and hides all our admin metadata)
if(amdTypes.size() > 0) if(amdTypes.size() > 0)
{ {
//////////////////////////////// ////////////////////////////////
// Start an administrative wrapper // Start an administrative wrapper
@@ -484,8 +489,8 @@ public class ItemAdapter extends AbstractAdapter
} }
// For each administrative metadata section specified // For each administrative metadata section specified
for (String amdSecName : amdTypes.keySet()) for (String amdSecName : amdTypes.keySet())
{ {
//get a list of metadata crosswalks which will be used to build //get a list of metadata crosswalks which will be used to build
// this administrative metadata section // this administrative metadata section
List<String> mdTypes = amdTypes.get(amdSecName); List<String> mdTypes = amdTypes.get(amdSecName);
@@ -528,7 +533,7 @@ public class ItemAdapter extends AbstractAdapter
}//end for each amdSec }//end for each amdSec
if(amdTypes.size() > 0) if(amdTypes.size() > 0)
{ {
////////////////////////////////// //////////////////////////////////
// End administrative section // End administrative section
endElement(METS,"amdSec"); endElement(METS,"amdSec");
@@ -652,17 +657,17 @@ public class ItemAdapter extends AbstractAdapter
*/ */
protected void renderFileSection() throws SQLException, SAXException protected void renderFileSection() throws SQLException, SAXException
{ {
AttributeMap attributes; AttributeMap attributes;
// ////////////////////// // //////////////////////
// Start a new file section // Start a new file section
startElement(METS,"fileSec"); startElement(METS,"fileSec");
// Check if the user is requested a specific bundle or // Check if the user is requested a specific bundle or
// the all bundles. // the all bundles.
List<Bundle> bundles = findEnabledBundles(); List<Bundle> bundles = findEnabledBundles();
// Loop over all requested bundles // Loop over all requested bundles
for (Bundle bundle : bundles) for (Bundle bundle : bundles)
{ {
@@ -690,13 +695,13 @@ public class ItemAdapter extends AbstractAdapter
for (Bitstream bitstream : bundle.getBitstreams()) for (Bitstream bitstream : bundle.getBitstreams())
{ {
// ////////////////////////////// // //////////////////////////////
// Determine the file's IDs // Determine the file's IDs
String fileID = getFileID(bitstream); String fileID = getFileID(bitstream);
Bitstream originalBitstream = null; Bitstream originalBitstream = null;
if (isDerivedBundle) if (isDerivedBundle)
originalBitstream = findOriginalBitstream(item, bitstream); originalBitstream = findOriginalBitstream(item, bitstream);
String groupID = getGroupFileID((originalBitstream == null) ? bitstream : originalBitstream ); String groupID = getGroupFileID((originalBitstream == null) ? bitstream : originalBitstream );
//Check if there were administrative metadata sections corresponding to this file //Check if there were administrative metadata sections corresponding to this file
@@ -724,7 +729,7 @@ public class ItemAdapter extends AbstractAdapter
// ////////////////////// // //////////////////////
// End the file section // End the file section
endElement(METS,"fileSec"); endElement(METS,"fileSec");
} }
@@ -743,70 +748,70 @@ public class ItemAdapter extends AbstractAdapter
*/ */
protected void renderStructureMap() throws SQLException, SAXException protected void renderStructureMap() throws SQLException, SAXException
{ {
AttributeMap attributes; AttributeMap attributes;
// /////////////////////// // ///////////////////////
// Start a new structure map // Start a new structure map
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("TYPE", "LOGICAL"); attributes.put("TYPE", "LOGICAL");
attributes.put("LABEL", "DSpace"); attributes.put("LABEL", "DSpace");
startElement(METS,"structMap",attributes); startElement(METS,"structMap",attributes);
// //////////////////////////////// // ////////////////////////////////
// Start the special first division // Start the special first division
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("TYPE", "DSpace Item"); attributes.put("TYPE", "DSpace Item");
// add references to the Descriptive metadata // add references to the Descriptive metadata
if (dmdSecIDS != null) if (dmdSecIDS != null)
attributes.put("DMDID", dmdSecIDS.toString()); attributes.put("DMDID", dmdSecIDS.toString());
// add references to the Administrative metadata // add references to the Administrative metadata
if (amdSecIDS != null) if (amdSecIDS != null)
attributes.put("AMDID", amdSecIDS.toString()); attributes.put("AMDID", amdSecIDS.toString());
startElement(METS,"div",attributes); startElement(METS,"div",attributes);
// add a fptr pointer to the primary bitstream. // add a fptr pointer to the primary bitstream.
if (primaryBitstream != null) if (primaryBitstream != null)
{ {
// //////////////////////////////// // ////////////////////////////////
// Start & end a refrence to the primary bistream. // Start & end a refrence to the primary bistream.
attributes = new AttributeMap(); attributes = new AttributeMap();
String fileID = getFileID(primaryBitstream); String fileID = getFileID(primaryBitstream);
attributes.put("FILEID", fileID); attributes.put("FILEID", fileID);
startElement(METS,"fptr",attributes); startElement(METS,"fptr",attributes);
endElement(METS,"fptr"); endElement(METS,"fptr");
} }
for (Bitstream bitstream : contentBitstreams) for (Bitstream bitstream : contentBitstreams)
{ {
// //////////////////////////////////// // ////////////////////////////////////
// Start a div for each publicaly viewable bitstream // Start a div for each publicaly viewable bitstream
attributes = new AttributeMap(); attributes = new AttributeMap();
attributes.put("ID", getGenericID("div_")); attributes.put("ID", getGenericID("div_"));
attributes.put("TYPE", "DSpace Content Bitstream"); attributes.put("TYPE", "DSpace Content Bitstream");
startElement(METS,"div",attributes); startElement(METS,"div",attributes);
// //////////////////////////////// // ////////////////////////////////
// Start a the actualy pointer to the bitstream // Start a the actualy pointer to the bitstream
attributes = new AttributeMap(); attributes = new AttributeMap();
String fileID = getFileID(bitstream); String fileID = getFileID(bitstream);
attributes.put("FILEID", fileID); attributes.put("FILEID", fileID);
startElement(METS,"fptr",attributes); startElement(METS,"fptr",attributes);
endElement(METS,"fptr"); endElement(METS,"fptr");
// /////////////////////////////// // ///////////////////////////////
// End the div // End the div
endElement(METS,"div"); endElement(METS,"div");
} }
// //////////////////////////////// // ////////////////////////////////
// End the special first division // End the special first division
endElement(METS,"div"); endElement(METS,"div");
// /////////////////////// // ///////////////////////
// End the structure map // End the structure map
endElement(METS,"structMap"); endElement(METS,"structMap");
} }
@@ -818,43 +823,43 @@ public class ItemAdapter extends AbstractAdapter
*/ */
protected void renderExtraSections() throws SAXException, SQLException, IOException protected void renderExtraSections() throws SAXException, SQLException, IOException
{ {
Boolean include = ConfigurationManager.getBooleanProperty("xmlui.bitstream.mets"); Boolean include = ConfigurationManager.getBooleanProperty("xmlui.bitstream.mets");
if (!include) if (!include)
return; return;
Bundle[] bundles = item.getBundles("METADATA"); Bundle[] bundles = item.getBundles("METADATA");
for (Bundle bundle : bundles) for (Bundle bundle : bundles)
{ {
Bitstream bitstream = bundle.getBitstreamByName("METS.xml"); Bitstream bitstream = bundle.getBitstreamByName("METS.xml");
if (bitstream == null) if (bitstream == null)
continue; continue;
// /////////////////////////////// // ///////////////////////////////
// Send the actual XML content // Send the actual XML content
try { try {
SAXFilter filter = new SAXFilter(contentHandler, lexicalHandler, namespaces); SAXFilter filter = new SAXFilter(contentHandler, lexicalHandler, namespaces);
// Allow the basics for XML // Allow the basics for XML
filter.allowIgnorableWhitespace().allowCharacters().allowCDATA().allowPrefixMappings(); filter.allowIgnorableWhitespace().allowCharacters().allowCDATA().allowPrefixMappings();
// Special option, only allow elements below the second level to pass through. This // Special option, only allow elements below the second level to pass through. This
// will trim out the METS declaration and only leave the actual METS parts to be // will trim out the METS declaration and only leave the actual METS parts to be
// included. // included.
filter.allowElements(1); filter.allowElements(1);
XMLReader reader = XMLReaderFactory.createXMLReader(); XMLReader reader = XMLReaderFactory.createXMLReader();
reader.setContentHandler(filter); reader.setContentHandler(filter);
reader.setProperty("http://xml.org/sax/properties/lexical-handler", filter); reader.setProperty("http://xml.org/sax/properties/lexical-handler", filter);
reader.parse(new InputSource(bitstream.retrieve())); reader.parse(new InputSource(bitstream.retrieve()));
} }
catch (AuthorizeException ae) catch (AuthorizeException ae)
{ {
// just ignore the authorize exception and continue on with // just ignore the authorize exception and continue on with
//out parsing the xml document. //out parsing the xml document.
} }
} }
} }
@@ -867,21 +872,21 @@ public class ItemAdapter extends AbstractAdapter
protected List<Bundle> findEnabledBundles() throws SQLException protected List<Bundle> findEnabledBundles() throws SQLException
{ {
// Check if the user is requested a specific bundle or // Check if the user is requested a specific bundle or
// the all bundles. // the all bundles.
List<Bundle> bundles; List<Bundle> bundles;
if (fileGrpTypes.size() == 0) if (fileGrpTypes.size() == 0)
bundles = Arrays.asList(item.getBundles()); bundles = Arrays.asList(item.getBundles());
else else
{ {
bundles = new ArrayList<Bundle>(); bundles = new ArrayList<Bundle>();
for (String fileGrpType : fileGrpTypes) for (String fileGrpType : fileGrpTypes)
{ {
for (Bundle newBundle : item.getBundles(fileGrpType)) for (Bundle newBundle : item.getBundles(fileGrpType))
{ {
bundles.add(newBundle); bundles.add(newBundle);
} }
} }
} }
return bundles; return bundles;
} }

View File

@@ -112,6 +112,7 @@ to administer DSpace.
<map:transformer name="ControlPanel" src="org.dspace.app.xmlui.aspect.administrative.ControlPanel" /> <map:transformer name="ControlPanel" src="org.dspace.app.xmlui.aspect.administrative.ControlPanel" />
<map:transformer name="WithdrawnItems" src="org.dspace.app.xmlui.aspect.administrative.WithdrawnItems" /> <map:transformer name="WithdrawnItems" src="org.dspace.app.xmlui.aspect.administrative.WithdrawnItems" />
<map:transformer name="ItemExport" src="org.dspace.app.xmlui.aspect.administrative.ItemExport"/> <map:transformer name="ItemExport" src="org.dspace.app.xmlui.aspect.administrative.ItemExport"/>
<map:transformer name="ChoiceLookup" src="org.dspace.app.xmlui.aspect.general.ChoiceLookupTransformer"/>
</map:transformers> </map:transformers>
<map:matchers default="wildcard"> <map:matchers default="wildcard">
@@ -885,6 +886,34 @@ to administer DSpace.
</map:select> </map:select>
</map:match> </map:match>
<!-- choice value lookup popup -->
<map:match pattern="admin/lookup">
<map:transform type="ChoiceLookup">
<map:parameter name="field" value="{request-param:field}"/>
<map:parameter name="formID" value="{request-param:formID}"/>
<map:parameter name="value" value="{request-param:value}"/>
<map:parameter name="valueInput" value="{request-param:valueInput}"/>
<map:parameter name="authorityInput" value="{request-param:authorityInput}"/>
<map:parameter name="isName" value="{request-param:isName}"/>
<map:parameter name="isRepeating" value="{request-param:isRepeating}"/>
<map:parameter name="confIndicatorID" value="{request-param:confIndicatorID}"/>
<map:parameter name="start" value="{request-param:start}"/>
<map:parameter name="limit" value="{request-param:limit}"/>
<map:parameter name="collection" value="{request-param:collection}"/>
</map:transform>
</map:match>
<map:match pattern="admin/**">
<map:transform type="IncludePageMeta">
<!-- javascript libraries and utils for the choice and authority-control -->
<map:parameter name="javascript.static#1" value="static/js/scriptaculous/prototype.js"/>
<map:parameter name="javascript.static#2" value="static/js/scriptaculous/effects.js"/>
<map:parameter name="javascript.static#3" value="static/js/scriptaculous/builder.js"/>
<map:parameter name="javascript.static#4" value="static/js/scriptaculous/controls.js"/>
<map:parameter name="javascript.static#5" value="static/js/choice-support.js"/>
</map:transform>
</map:match>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:pipeline> </map:pipeline>
</map:pipelines> </map:pipelines>

View File

@@ -73,6 +73,7 @@
<map:matchers default="wildcard"> <map:matchers default="wildcard">
<map:matcher name="HandleTypeMatcher" src="org.dspace.app.xmlui.aspect.general.HandleTypeMatcher"/> <map:matcher name="HandleTypeMatcher" src="org.dspace.app.xmlui.aspect.general.HandleTypeMatcher"/>
<map:matcher name="HandleAuthorizedMatcher" src="org.dspace.app.xmlui.aspect.general.HandleAuthorizedMatcher"/> <map:matcher name="HandleAuthorizedMatcher" src="org.dspace.app.xmlui.aspect.general.HandleAuthorizedMatcher"/>
<map:matcher name="regexp" src="org.apache.cocoon.matching.RegexpURIMatcher"/>
</map:matchers> </map:matchers>
<map:actions> <map:actions>
@@ -297,6 +298,17 @@
</map:match> <!-- flow match--> </map:match> <!-- flow match-->
<!-- javascript libraries and utils for choice/authority-control -->
<map:match type="regexp" pattern="(^submit)|(^handle/.*/submit)|(^handle/.*/workflow)">
<map:transform type="IncludePageMeta">
<map:parameter name="javascript.static#1" value="static/js/scriptaculous/prototype.js"/>
<map:parameter name="javascript.static#2" value="static/js/scriptaculous/effects.js"/>
<map:parameter name="javascript.static#3" value="static/js/scriptaculous/builder.js"/>
<map:parameter name="javascript.static#4" value="static/js/scriptaculous/controls.js"/>
<map:parameter name="javascript.static#5" value="static/js/choice-support.js"/>
</map:transform>
</map:match>
<map:serialize type="xml"/> <map:serialize type="xml"/>
</map:when> </map:when>

View File

@@ -128,6 +128,12 @@
<artifactId>dspace-xmlui-api</artifactId> <artifactId>dspace-xmlui-api</artifactId>
</dependency> </dependency>
<!-- Shared JS code for Choice/Authority control -->
<dependency>
<groupId>org.dspace</groupId>
<artifactId>dspace-ui-shared</artifactId>
<type>war</type>
</dependency>
</dependencies> </dependencies>
</project> </project>

Some files were not shown because too many files have changed in this diff Show More