diff --git a/Dspace_participatorio_DB_additions.xml b/Dspace_participatorio_DB_additions.xml deleted file mode 100644 index cc8d8ac95032a3d287d67d6b19d79341ec3efebe..0000000000000000000000000000000000000000 --- a/Dspace_participatorio_DB_additions.xml +++ /dev/null @@ -1,141 +0,0 @@ -<!-- Metadados DublinCore adicionados ao Dspace Participatorio --> -<!-- ${DSPACEDIR}/bin/dspace dsrun org.dspace.administer.MetadataImporter -f ${THIS_FILE} --> -<dspace-dc-types> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier></qualifier> - <scope_note>Affiliation</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>publicationplace</qualifier> - <scope_note>Place of Publication</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>edition</qualifier> - <scope_note>Release Edition</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>numberofpages</qualifier> - <scope_note>Number of Pages</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>grade</qualifier> - <scope_note>Grade</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>supervisor</qualifier> - <scope_note>Supervisor</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>cosupervisor</qualifier> - <scope_note>Co-Supervisor</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>jurymembers</qualifier> - <scope_note>Members of the jury</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>defenselocation</qualifier> - <scope_note>Location where the defense took place</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>defensedate</qualifier> - <scope_note>Date on which the defense occurred</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>defenceinstitution</qualifier> - <scope_note>Institution where the defense took place</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>defensedepartment</qualifier> - <scope_note>Department where the defense took place</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>programme</qualifier> - <scope_note>Programme</scope_note> - </dc-type> - -<!--Feito da maneira que foi pedido: - - Diretor (dc.creator.director); - - Roteirista (dc.creator.screenplay); - - Produção (dc.creator.production); - - Tempo de Duração (dc.coverage.temporal); - - Sistema de Cor (dc.type.color) - - Categoria (dc.xxxx.xxxx); - - Formato da Cópia (dc.xxxx.xxxx); - - Tratamento (dc.format.material); - --> - <dc-type> - <schema>dc</schema> - <element>creator</element> - <qualifier>director</qualifier> - <scope_note>Director</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>creator</element> - <qualifier>screenplay</qualifier> - <scope_note>Screenplay</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>creator</element> - <qualifier>production</qualifier> - <scope_note>Production</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>coverage</element> - <qualifier>temporal</qualifier> - <scope_note>Temporal</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>type</element> - <qualifier>color</qualifier> - <scope_note>Color system</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>category</qualifier> - <scope_note>Category</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>description</element> - <qualifier>copyformat</qualifier> - <scope_note>Copy format</scope_note> - </dc-type> - <dc-type> - <schema>dc</schema> - <element>format</element> - <qualifier>material</qualifier> - <scope_note>Material</scope_note> - </dc-type> -</dspace-dc-types> diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 79882c7e59aa20d9ea2125af972e0cb4672df5db..0000000000000000000000000000000000000000 --- a/LICENSE +++ /dev/null @@ -1,40 +0,0 @@ -DSpace source code license: - - -Copyright (c) 2002-2012, DuraSpace. 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 DuraSpace nor 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. - - -DSpace uses third-party libraries which may be distributed under -different licenses to the above. Information about these licenses -is detailed in the LICENSES_THIRD_PARTY file at the root of the source -tree. You must agree to the terms of these licenses, in addition to -the above DSpace source code license, in order to use this software. diff --git a/LICENSES_THIRD_PARTY b/LICENSES_THIRD_PARTY deleted file mode 100644 index ce4b326810e207875e34108be63c0b606f752156..0000000000000000000000000000000000000000 --- a/LICENSES_THIRD_PARTY +++ /dev/null @@ -1,144 +0,0 @@ -DSpace uses third-party libraries which may be distributed under different -licenses. We have attempted to list all of these third party libraries and -their licenses below (however the most up-to-date information can be found -via Maven, see NOTE #2 at bottom of this page). - -You must agree to the terms of these licenses, in addition to the DSpace -source code license, in order to use this software. - --------------------------------------------------- -Third party Java libraries listed by License type -[Format: Name (Maven Project) - URL] --------------------------------------------------- - -Apache Software License, Version 2.0 (http://opensource.org/licenses/apache2.0) - * Ant-Contrib Tasks (ant-contrib:*) - http://ant-contrib.sourceforge.net/ - * Apache Abdera (org.apache.abdera::*) - http://projects.apache.org/projects/abdera.html - * Apache Ant (org.apache.ant:*) - http://ant.apache.org/ - * Apache Axis (axis:*) - http://axis.apache.org/axis/ - * Apache Cocoon (org.apache.cocoon:*) - http://cocoon.apache.org/2.2/license.html - * Apache Commons BeanUtils (commons-beanutils:*) - http://commons.apache.org/beanutils/ - * Apache Commons CLI (commons-cli:*) - http://commons.apache.org/cli/license.html - * Apache Commons Codec (commons-codec:*) - http://commons.apache.org/codec/license.html - * Apache Commons Collections (commons-collections:*) - http://commons.apache.org/collections/license.html - * Apache Commons Configuration (commons-configuration:*) - http://commons.apache.org/configuration/license.html - * Apache Commons DBCP (commons-dbcp:*) - http://commons.apache.org/dbcp/license.html - * Apache Commons Digester (commons-digester:*) - http://commons.apache.org/digester/ - * Apache Commons Discovery (commons-discovery:*) - http://commons.apache.org/discovery/license.html - * Apache Commons FileUpload (commons-fileupload:*) - http://commons.apache.org/fileupload/license.html - * Apache Commons HTTP Client (commons-httpclient:*) - http://commons.apache.org/httpclient/license.html - * Apache Commons IO (commons-io:*) - http://commons.apache.org/io/license.html - * Apache Commons JXPath (commons-jxpath:*) - http://commons.apache.org/jxpath/license.html - * Apache Commons Lang (commons-lang:*) - http://commons.apache.org/lang/license.html - * Apache Commons Logging (commons-logging:*) - http://commons.apache.org/logging/license.html - * Apache Commons Pool (commons-pool:*) - http://commons.apache.org/pool/license.html - * Apache Commons Validator (commons-validator:*) - http://commons.apache.org/validator/license.html - * Apache Geronimo (org.apache.geronimo.specs:*) - http://geronimo.apache.org/ - * Apache HTTPComponents (org.apache.httpcomponents:*) - http://hc.apache.org/ - * Apache Jakarta ORO (oro:*) - http://svn.apache.org/repos/asf/jakarta/oro/trunk/LICENSE - * Apache Jakarta Regexp (jakarta-regexp:*) - http://jakarta.apache.org/regexp/ - * Apache JaxMe (jaxme:jaxme-api) - http://ws.apache.org/old/jaxme-old/license.html - * Apache Jena (com.hp.hpl.jena:*) - http://jena.apache.org/ - * Apache log4j (log4j:*) : http://logging.apache.org/log4j/ - * Apache Lucene (org.apache.lucene:*) - http://lucene.apache.org/ - * Apache PDFBox (org.apache.pdfbox:*) - http://pdfbox.apache.org/ - * Apache POI (org.apache.poi:*) - http://poi.apache.org/ - * Apache Solr (org.apache.solr:*) - http://lucene.apache.org/solr/ - * Apache Xerces (xerces:*) - http://xerces.apache.org/ - * Apache XML Commons (xml-apis:*) - http://xerces.apache.org/xml-commons/licenses.html - * Apache XML Project (xalan:*) - http://xml.apache.org/xalan-j/#license - * Apache XMLBeans (org.apache.xmlbeans:*) - http://xmlbeans.apache.org/ - * Apache ZooKeeper (org.apache.zookeeper:*) - http://zookeeper.apache.org/ - * Databene ContiPerf (org.databene:contiperf) - http://databene.org/contiperf - * Ehcache (net.sf.ehcache:*) - http://ehcache.org/about/license - * ElasticSearch (org.elasticsearch:*) - http://www.elasticsearch.org/ - * flexjson (net.sf.flexjson:*) - http://sourceforge.net/projects/flexjson/ - * Google GSON (com.google.code.gson:*) - http://code.google.com/p/google-gson/ - * Google Guava (com.google.guava:*) - http://code.google.com/p/guava-libraries/ - * Jetty (org.mortbay.jetty:*) - http://jetty.codehaus.org/jetty/license.html - * Lyncode XOAI (com.lyncode:xoai) - http://www.lyncode.com/ - * OpenCSV (net.sf.opencsv:*) - http://opencsv.sourceforge.net/ - * Rome (net.java.dev.rome:*, org.rometools:*, rome:*) - http://rometools.org/ - * Spring Framework (org.springframework:*) - http://www.springsource.org/spring-framework - * SWORD Libraries (org.swordapp:*) - http://mvnrepository.com/artifact/org.swordapp/server/2.0 - * Woodstox (org.codehaus.woodstox:*) - http://woodstox.codehaus.org/Download - -BSD License (http://www.opensource.org/licenses/BSD-3-Clause) - * Biblio Transformation Engine (gr.ekt:biblio-transformation-engine) - http://code.google.com/p/biblio-transformation-engine/ - * DNSJava (org.dspace.dnsjava:dnsjava)- http://www.xbill.org/dnsjava/dnsjava-current/README - * dom4j (dom4j:*, maven:dom4j) - http://dom4j.sourceforge.net/dom4j-1.6.1/license.html - * Foresite Toolkit (com.googlecode.foresite-toolkit:*) - http://code.google.com/p/foresite-toolkit/ - * Java BibTeX Parser (org.jbibtex:*) - https://code.google.com/p/java-bibtex/ - * Jaxen (jaxen:*) - http://jaxen.codehaus.org/license.html - * JLine (jline:*) - http://jline.sourceforge.net/ - * JUnitPerf (junitperf:*) - http://www.clarkware.com/software/JUnitPerf.html#license - * MSV (msv:*) - http://msv.java.net/ - * StAX (Streaming API for XML) (stax:*) - http://stax.codehaus.org/ - * XMLUnit (xmlunit:*) - http://xmlunit.sourceforge.net/ - * YUI (com.yahoo.platform.yui:*) - http://yuilibrary.com/license/ - -Common Development and Distribution License (CDDL) v1.0 (http://www.opensource.org/licenses/CDDL-1.0) - * JavaBeans Activation Framework (javax.activation:*) - http://www.opensource.org/licenses/CDDL-1.0 - * Java Mail (javax.mail:*) - http://www.opensource.org/licenses/CDDL-1.0 - * JAX-RPC (javax.xml:jaxrpc-api) - http://java.net/projects/jax-rpc/ - * JAXB (com.sun.xml.bind:jaxb-impl) - http://jaxb.java.net/ - -Common Public License v1.0 (http://www.opensource.org/licenses/cpl1.0) - * JUnit (junit:*) - http://junit.org/license - * WSDL4J (wsdl4j:*) - http://sourceforge.net/projects/wsdl4j/ - -Lesser GPL (http://www.opensource.org/licenses/LGPL-2.1) - * JExcelAPI (net.sourceforge.jexcelapi:*) - http://sourceforge.net/projects/jexcelapi/ - * MaxMind GeoIP (org.dspace.dependencies:dspace-geoip) - http://geoip.cvs.sourceforge.net/viewvc/geoip/java/LICENSE - * Text-mining (org.dspace.dependencies:dspace-tm-extractors) - http://code.google.com/p/text-mining/ - * XOM (xom:*) - http://www.xom.nu/ - -MIT / X11 License (or adaptations) (http://www.opensource.org/licenses/MIT) - * Bouncy Castle (org.bouncycastle:*) - http://www.bouncycastle.org/licence.html - * jmockit (org.dspace.dependencies.jmockit:dspace-jmockit) - http://code.google.com/p/jmockit/ - * SLF4J (org.slf4j:*) - http://www.slf4j.org/license.html - -Mozilla Public License (http://www.opensource.org/licenses/MPL-2.0) - * H2 database (com.h2database:*) - http://www.h2database.com/html/license.html - -Other Open Source Licenses: - * AOP Alliance (aopalliance:*) - Public Domain: http://aopalliance.sourceforge.net/ - * ICU4J (com.ibm.icu:icu4j) - ICU License : http://source.icu-project.org/repos/icu/icu/trunk/license.html - * JDOM (jdom:*) - JDOM License : https://github.com/hunterhacker/jdom/blob/master/LICENSE.txt - * PostgreSQL (postgresql:*) - PostgreSQL License (BSD-based): http://www.postgresql.org/about/licence/ - * Pull-parser / XPP3 (pull-parser:*, xpp3:*) - Indiana University Extreme! Lab Software License (BSD-based): http://www.extreme.indiana.edu/xgws/xsoap/xpp/download/PullParser2/LICENSE.txt - ----- -NOTE #1: Some individual web application files in DSpace (e.g. Javascript -libraries, CSS Frameworks) may have their own open source license. In that -scenario, we place a copy of the full text of the license alongside the -licensed files. You can locate these additional licenses in our codebase -by searching for files with a ".LICENSE" file extension. - -For example, on Linux you can use the 'find' command from the source directory: - -find . -type f -name "*.LICENSE" ----- - ----- -NOTE #2: Although we try to keep this libraries list current, the latest -information about DSpace third party libraries can be found by running the -following Maven command(s): - -mvn project-info-reports:dependencies - -This generates a "[project]/target/site/dependencies.html" report under every -DSpace project directory. This report lists all dependencies and their license -(if it can be determined by Maven). - -Additionally, you may wish to run: - -mvn project-info-reports:dependency-convergence - -This generates a summary report at -"[dspace]/target/site/dependency-convergence.html" which lists all dependencies -of all DSpace projects (though it does not list license information) - -For more information see the maven-project-info-reports-plugin: -http://maven.apache.org/plugins/maven-project-info-reports-plugin/ ----- diff --git a/LICENSE_HEADER b/LICENSE_HEADER deleted file mode 100644 index 6b4f12ec44b6ceccca2399b086d6722b62b69f39..0000000000000000000000000000000000000000 --- a/LICENSE_HEADER +++ /dev/null @@ -1,5 +0,0 @@ -The contents of this file are subject to the license and copyright -detailed in the LICENSE and NOTICE files at the root of the source -tree and available online at - -http://www.dspace.org/license/ \ No newline at end of file diff --git a/NOTICE b/NOTICE deleted file mode 100644 index ffb52242070cffafd5d5c4df977a44a49ddf573f..0000000000000000000000000000000000000000 --- a/NOTICE +++ /dev/null @@ -1,15 +0,0 @@ - -Licensing Notice - -Fedora Commons joined with the DSpace Foundation and began operating under -the new name DuraSpace in July 2009. DuraSpace holds the copyrights of -the DSpace Foundation, Inc. - -The DSpace Foundation, Inc. is a 501(c)3 corporation established in July 2007 -with a mission to promote and advance the dspace platform enabling management, -access and preservation of digital works. The Foundation was able to transfer -the legal copyright from Hewlett-Packard Company (HP) and Massachusetts -Institute of Technology (MIT) to the DSpace Foundation in October 2007. Many -of the files in the source code may contain a copyright statement stating HP -and MIT possess the copyright, in these instances please note that the copy -right has transferred to the DSpace foundation, and subsequently to DuraSpace. diff --git a/README b/README deleted file mode 100644 index 0490692d6c92103b022e3468ca829aa28cba84e5..0000000000000000000000000000000000000000 --- a/README +++ /dev/null @@ -1,54 +0,0 @@ -Installation instructions are included in this release package under - - - dspace/docs/DSpace-Manual.pdf - -DSpace version information can be viewed online at - - https://wiki.duraspace.org/display/DSDOC/ - -Documentation for the most recent stable release(s) may be downloaded -or viewed online at - - http://www.dspace.org/latest-release/ - - https://wiki.duraspace.org/display/DSDOC/ - -In addition, a listing of all known contributors to DSpace software can be -found online at: -https://wiki.duraspace.org/display/DSPACE/DSpaceContributors - -Installation instructions for other versions may be different, so you -are encouraged to obtain the appropriate version of the Documentation -(from the links above or from the source repository). - -To obtain files from the repository and build, please see: - - - https://github.com/DSpace/DSpace/ - -or just: - - - git clone git://github.com/DSpace/DSpace.git - -Please refer any further problems to the dspace-tech@lists.sourceforge.net -mailing list. - - - http://sourceforge.net/mail/?group_id=19984 - - -Detailed Issue Tracking for DSpace is done on our JIRA Issue Tracker - - - https://jira.duraspace.org/browse/DS - - -To contribute to DSpace, please see: - - - https://wiki.duraspace.org/display/DSPACE/How+to+Contribute+to+DSpace - - -For more details about DSpace, including a list of service providers, -places to seek help, news articles and lists of other users, please see: - - - http://www.dspace.org/ - - -DSpace source code licensing information available online at: - - http://www.dspace.org/license/ - -Copyright (c) 2002-2012, DuraSpace. All rights reserved. diff --git a/build.properties b/build.properties deleted file mode 100644 index 382044af1d89b14da34a50683bd84356a6749270..0000000000000000000000000000000000000000 --- a/build.properties +++ /dev/null @@ -1,151 +0,0 @@ -# DSpace build.properties -# This file should be customised to suit your build environment. -# Note that not all configuration is handled here, only the most common -# properties that tend to differ between build environments. -# For adjusting global settings or more complex settings, edit the relevant config file. -# -# IMPORTANT: Do not remove or comment out settings in build.properties -# When you edit the "build.properties" file (or a custom *.properties file), -# take care not to remove or comment out any settings. Doing so, may cause -# your final "dspace.cfg" file to be misconfigured with regards to that -# particular setting. Instead, if you wish to remove/disable a particular -# setting, just clear out its value. For example, if you don't want to be -# notified of new user registrations, ensure the "mail.registration.notify" -# setting has no value, e.g. "mail.registration.notify=" -# - -########################## -# SERVER CONFIGURATION # -########################## - -# DSpace installation directory. This is the location where you want -# to install DSpace. NOTE: this value will be copied over to the -# "dspace.dir" setting in the final "dspace.cfg" file. It can be -# modified later on in your "dspace.cfg", if needed. -dspace.install.dir=/home/dspace/install_dir - -# DSpace host name - should match base URL. Do not include port number -dspace.hostname = dspacesnj.c3sl.ufpr.br - -# DSpace base host URL. Include port number etc. -dspace.baseUrl = dspacesnj.c3sl.ufpr.br - -# Name of the site -dspace.name = DSpace Estacao Juventude - -# Solr server -solr.server=http://localhost/solr - -# Default language for metadata values -default.language = pt_BR - -########################## -# DATABASE CONFIGURATION # -########################## - -# Database name ("oracle", or "postgres") -db.name=postgres - -# Uncomment the appropriate block below for your database. -# postgres -db.driver=org.postgresql.Driver -db.url=jdbc:postgresql://localhost:5432/dspace -db.username=dspace -db.password=dspace - -# oracle -#db.driver= oracle.jdbc.OracleDriver -#db.url=jdbc:oracle:thin:@//localhost:1521/xe -#db.username=dspace -#db.password=dspace - -# Schema name - if your database contains multiple schemas, you can avoid problems with -# retrieving the definitions of duplicate object names by specifying -# the schema name here that is used for DSpace by uncommenting the following entry -db.schema = - -# Maximum number of DB connections in pool -db.maxconnections = 30 - -# Maximum time to wait before giving up if all connections in pool are busy (milliseconds) -db.maxwait = 5000 - -# Maximum number of idle connections in pool (-1 = unlimited) -db.maxidle = -1 - -# Determine if prepared statement should be cached. (default is true) -db.statementpool = true - -# Specify a name for the connection pool (useful if you have multiple applications sharing Tomcat's dbcp) -# If not specified, defaults to 'dspacepool' -db.poolname = dspacepool - -####################### -# EMAIL CONFIGURATION # -####################### - -# SMTP mail server -mail.server = smtp.c3sl.ufpr.br - -# SMTP mail server authentication username and password (if required) -# mail.server.username = myusername -# mail.server.password = mypassword -mail.server.username= -mail.server.password= - -# SMTP mail server alternate port (defaults to 25) -mail.server.port = 25 - -# From address for mail -mail.from.address = dsparticipatorio@c3sl.ufpr.br - -# Currently limited to one recipient! -mail.feedback.recipient = dsparticipatorio@c3sl.ufpr.br - -# General site administration (Webmaster) e-mail -mail.admin = dsparticipatorio@c3sl.ufpr.br - -# Recipient for server errors and alerts -#mail.alert.recipient = email-address-here -mail.alert.recipient=dsparticipatorio@c3sl.ufpr.br - -# Recipient for new user registration emails -#mail.registration.notify = email-address-here -mail.registration.notify=dsparticipatorio@c3sl.ufpr.br - - -######################## -# HANDLE CONFIGURATION # -######################## - -# Canonical Handle URL prefix -# -# By default, DSpace is configured to use http://hdl.handle.net/ -# as the canonical URL prefix when generating dc.identifier.uri -# during submission, and in the 'identifier' displayed in JSPUI -# item record pages. -# -# If you do not subscribe to CNRI's handle service, you can change this -# to match the persistent URL service you use, or you can force DSpace -# to use your site's URL, eg. -#handle.canonical.prefix = ${dspace.url}/handle/ -# -# Note that this will not alter dc.identifer.uri metadata for existing -# items (only for subsequent submissions), but it will alter the URL -# in JSPUI's 'identifier' message on item record pages for existing items. -# -# If omitted, the canonical URL prefix will be http://hdl.handle.net/ -handle.canonical.prefix = http://hdl.handle.net/ - -# CNRI Handle prefix -handle.prefix = 123456789 - -####################### -# PROXY CONFIGURATION # -####################### -# uncomment and specify both properties if proxy server required -# proxy server for external http requests - use regular hostname without port number -http.proxy.host = - -# port number of proxy server -http.proxy.port = diff --git a/dspace-api/pom.xml b/dspace-api/pom.xml index 7c5b5148e78053d6140d9c0871ec1f23cbfbaac7..35c5a79272870a2532b46636303e0225f0e5c0cb 100644 --- a/dspace-api/pom.xml +++ b/dspace-api/pom.xml @@ -12,7 +12,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> @@ -25,6 +25,24 @@ Runtime and Compile Time dependencies for DSpace. --> <build> + <resources> + <resource> + <directory>src/main/resources</directory> + <includes> + <include>maven.properties</include> + <include>scm.properties</include> + </includes> + <filtering>true</filtering> + </resource> + <resource> + <directory>src/main/resources</directory> + <excludes> + <exclude>maven.properties</exclude> + <exclude>scm.properties</exclude> + </excludes> + <filtering>false</filtering> + </resource> + </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> @@ -78,6 +96,18 @@ </execution> </executions> </plugin> + <plugin> + <groupId>com.mycila.maven-license-plugin</groupId> + <artifactId>maven-license-plugin</artifactId> + <configuration> + <excludes> + <exclude>**/src/test/resources/**</exclude> + <exclude>**/src/test/data/**</exclude> + <exclude>**/.gitignore</exclude> + <exclude>src/test/data/dspaceFolder/config/spiders/**</exclude> + </excludes> + </configuration> + </plugin> <!-- This plugin allows us to run a Groovy script in our Maven POM (see: http://gmaven.codehaus.org/Executing+Groovy+Code ) We are generating a OS-agnostic version (agnostic.build.dir) of @@ -154,9 +184,9 @@ <execution> <phase>process-test-resources</phase> <configuration> - <tasks> + <target> <copy file="${agnostic.build.dir}/testing/dspace.cfg.woven" tofile="${agnostic.build.dir}/testing/dspace/config/dspace.cfg" /> - </tasks> + </target> </configuration> <goals> <goal>run</goal> @@ -177,6 +207,34 @@ </systemPropertyVariables> </configuration> </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>1.7</version> + <executions> + <execution> + <phase>validate</phase> + <goals> + <goal>maven-version</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>buildnumber-maven-plugin</artifactId> + <version>1.2</version> + <executions> + <execution> + <phase>validate</phase> + <goals> + <goal>create</goal> + </goals> + </execution> + </executions> + </plugin> </plugins> </build> @@ -203,7 +261,11 @@ </dependency> <dependency> <groupId>org.apache.lucene</groupId> - <artifactId>lucene-analyzers</artifactId> + <artifactId>lucene-analyzers-common</artifactId> + </dependency> + <dependency> + <groupId>org.apache.lucene</groupId> + <artifactId>lucene-queryparser</artifactId> </dependency> <dependency> <groupId>commons-cli</groupId> @@ -243,6 +305,10 @@ <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> </dependency> + <dependency> + <groupId>commons-validator</groupId> + <artifactId>commons-validator</artifactId> + </dependency> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> @@ -368,24 +434,24 @@ <version>1.0</version> </dependency> <dependency> - <groupId>gr.ekt</groupId> - <artifactId>biblio-transformation-engine</artifactId> - <version>0.82</version> + <groupId>gr.ekt.bte</groupId> + <artifactId>bte-core</artifactId> + <version>0.9.2.3</version> </dependency> <dependency> - <groupId>net.sf.opencsv</groupId> - <artifactId>opencsv</artifactId> - <version>2.3</version> + <groupId>gr.ekt.bte</groupId> + <artifactId>bte-io</artifactId> + <version>0.9.2.3</version> </dependency> <dependency> - <groupId>org.jbibtex</groupId> - <artifactId>jbibtex</artifactId> - <version>1.0.0</version> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.2.1</version> </dependency> <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> - <version>${lucene.version}</version> + <version>${solr.version}</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> @@ -420,7 +486,7 @@ <dependency> <groupId>org.elasticsearch</groupId> <artifactId>elasticsearch</artifactId> - <version>0.18.6</version> + <version>0.90.3</version> </dependency> <dependency> @@ -428,12 +494,11 @@ <artifactId>coverity-escapers</artifactId> <version>1.1.1</version> </dependency> - + <!-- Gson: Java to Json conversion --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> - <version>2.2.1</version> <scope>compile</scope> </dependency> @@ -441,7 +506,17 @@ <groupId>postgresql</groupId> <artifactId>postgresql</artifactId> </dependency> - + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + + <dependency> + <groupId>backport-util-concurrent</groupId> + <artifactId>backport-util-concurrent</artifactId> + <version>3.1</version> + </dependency> </dependencies> </project> diff --git a/dspace-api/src/main/java/org/dspace/administer/CreateAdministrator.java b/dspace-api/src/main/java/org/dspace/administer/CreateAdministrator.java index 0a325a00656e98e7aaf6270d364b110c35ed9071..4e653167bf71a9c074aef620c0b82613d49c57bb 100644 --- a/dspace-api/src/main/java/org/dspace/administer/CreateAdministrator.java +++ b/dspace-api/src/main/java/org/dspace/administer/CreateAdministrator.java @@ -45,7 +45,7 @@ import org.dspace.eperson.Group; public final class CreateAdministrator { /** DSpace Context object */ - private Context context; + private final Context context; /** * For invoking via the command line. If called with no command line arguments, @@ -123,10 +123,15 @@ public final class CreateAdministrator System.out.flush(); email = input.readLine(); - if (email != null) + if (!StringUtils.isBlank(email)) { email = email.trim(); } + else + { + System.out.println("Please provide an email address."); + continue; + } System.out.print("First name: "); System.out.flush(); diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java index c73d5b5f852d79420bacf29e0f34cc739eb27ed4..2dc3780eb80a0c0185a2f5d212989afe62f02acc 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/DSpaceCSV.java @@ -45,19 +45,19 @@ public class DSpaceCSV implements Serializable /** The value separator (defaults to double pipe '||') */ protected static String valueSeparator; - /** The value separator in an escaped form for using in regexs */ + /** The value separator in an escaped form for using in regexes */ protected static String escapedValueSeparator; /** The field separator (defaults to comma) */ protected static String fieldSeparator; - /** The field separator in an escaped form for using in regexs */ + /** The field separator in an escaped form for using in regexes */ protected static String escapedFieldSeparator; - /** The authority separator (defaults to dobule colon '::') */ + /** The authority separator (defaults to double colon '::') */ protected static String authoritySeparator; - /** The authority separator in an escaped form for using in regexs */ + /** The authority separator in an escaped form for using in regexes */ protected static String escapedAuthoritySeparator; @@ -385,6 +385,12 @@ public class DSpaceCSV implements Serializable */ public final void addItem(Item i) throws Exception { + // If the item does not have an "owningCollection" the the below "getHandle()" call will fail + // This should not happen but is here for safety. + if (i.getOwningCollection() == null) { + return; + } + // Create the CSV line DSpaceCSVLine line = new DSpaceCSVLine(i.getID()); @@ -451,7 +457,7 @@ public class DSpaceCSV implements Serializable */ public final void addItem(String line) throws Exception { - // Check to see if the last character is a field separator, which hides the last empy column + // Check to see if the last character is a field separator, which hides the last empty column boolean last = false; if (line.endsWith(fieldSeparator)) { diff --git a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExport.java b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExport.java index 59ad0cb79895660237f6e47fc22b41310d16f784..70f2f44bab9d713c78e34b36398819bc557b0d99 100644 --- a/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExport.java +++ b/dspace-api/src/main/java/org/dspace/app/bulkedit/MetadataExport.java @@ -137,6 +137,9 @@ public class MetadataExport } catch (Exception e) { + // Something went wrong... + System.err.println("Error exporting to CSV:"); + e.printStackTrace(); return null; } } @@ -263,4 +266,4 @@ public class MetadataExport c.restoreAuthSystemState(); c.complete(); } -} \ No newline at end of file +} diff --git a/dspace-api/src/main/java/org/dspace/app/configuration/APISpringLoader.java b/dspace-api/src/main/java/org/dspace/app/configuration/APISpringLoader.java index 0d6f88cf2b957d6bd91517992649a91255e92e48..f2d84a045cf171cfe3662f77d6d3b095d4ae6762 100644 --- a/dspace-api/src/main/java/org/dspace/app/configuration/APISpringLoader.java +++ b/dspace-api/src/main/java/org/dspace/app/configuration/APISpringLoader.java @@ -14,9 +14,7 @@ import java.io.File; import java.net.MalformedURLException; /** - * User: kevin (kevin at atmire.com) - * Date: 3-aug-2011 - * Time: 11:31:21 + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class APISpringLoader implements SpringLoader { diff --git a/dspace-api/src/main/java/org/dspace/app/harvest/Harvest.java b/dspace-api/src/main/java/org/dspace/app/harvest/Harvest.java index d4974d11612b54b6e9b63912fde618bb1be1ec70..086b1ce81750a0257420453d6c6e4de8429786bc 100644 --- a/dspace-api/src/main/java/org/dspace/app/harvest/Harvest.java +++ b/dspace-api/src/main/java/org/dspace/app/harvest/Harvest.java @@ -37,7 +37,7 @@ import org.dspace.handle.HandleManager; */ public class Harvest { - private static Context context; + private static Context context; public static void main(String[] argv) throws Exception { @@ -251,6 +251,8 @@ public class Harvest System.out.println(" (run with -h flag for details)"); System.exit(1); } + + pingResponder(oaiSource, oaiSetID, metadataKey); } } @@ -435,49 +437,80 @@ public class Harvest System.out.println("Harvest complete. "); } - - + /** * Resets harvest_status and harvest_start_time flags for all collections that have a row in the harvested_collections table */ private static void resetHarvesting() { System.out.print("Resetting harvest status flag on all collections... "); - - try + + try { - List<Integer> cids = HarvestedCollection.findAll(context); - for (Integer cid : cids) - { - HarvestedCollection hc = HarvestedCollection.find(context, cid); - //hc.setHarvestResult(null,""); - hc.setHarvestStartTime(null); - hc.setHarvestStatus(HarvestedCollection.STATUS_READY); - hc.update(); - } - context.commit(); - System.out.println("success. "); + List<Integer> cids = HarvestedCollection.findAll(context); + for (Integer cid : cids) + { + HarvestedCollection hc = HarvestedCollection.find(context, cid); + //hc.setHarvestResult(null,""); + hc.setHarvestStartTime(null); + hc.setHarvestStatus(HarvestedCollection.STATUS_READY); + hc.update(); + } + context.commit(); + System.out.println("success. "); } catch (Exception ex) { - System.out.println("failed. "); - ex.printStackTrace(); + System.out.println("failed. "); + ex.printStackTrace(); } } - - + /** * Starts up the harvest scheduler. Terminating this process will stop the scheduler. */ private static void startHarvester() { - try - { - System.out.print("Starting harvest loop... "); - OAIHarvester.startNewScheduler(); - System.out.println("running. "); + try + { + System.out.print("Starting harvest loop... "); + OAIHarvester.startNewScheduler(); + System.out.println("running. "); } catch (Exception ex) { - ex.printStackTrace(); + ex.printStackTrace(); } } - + + /** + * See if the responder is alive and working. + * + * @param server address of the responder's host. + * @param set name of an item set. + * @param metadataFormat local prefix name, or null for "dc". + */ + private static void pingResponder(String server, String set, String metadataFormat) + { + List<String> errors; + + System.out.print("Testing basic PMH access: "); + errors = OAIHarvester.verifyOAIharvester(server, set, + (null != metadataFormat) ? metadataFormat : "dc", false); + if (errors.isEmpty()) + System.out.println("OK"); + else + { + for (String error : errors) + System.err.println(error); + } + + System.out.print("Testing ORE support: "); + errors = OAIHarvester.verifyOAIharvester(server, set, + (null != metadataFormat) ? metadataFormat : "dc", true); + if (errors.isEmpty()) + System.out.println("OK"); + else + { + for (String error : errors) + System.err.println(error); + } + } } diff --git a/dspace-api/src/main/java/org/dspace/app/itemexport/ItemExport.java b/dspace-api/src/main/java/org/dspace/app/itemexport/ItemExport.java index 5399479712391e1e0273ee6b04f369864b265221..f26e6ff6f9456dee00f00ce045cf0648e482289b 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemexport/ItemExport.java +++ b/dspace-api/src/main/java/org/dspace/app/itemexport/ItemExport.java @@ -21,9 +21,12 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; +import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Set; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -74,7 +77,7 @@ import org.dspace.handle.HandleManager; * <P> * Modified by David Little, UCSD Libraries 12/21/04 to allow the registration * of files (bitstreams) into DSpace. - * + * * @author David Little * @author Jay Paz */ @@ -86,12 +89,12 @@ public class ItemExport * used for export download */ public static final String COMPRESSED_EXPORT_MIME_TYPE = "application/zip"; - + /** log4j logger */ private static Logger log = Logger.getLogger(ItemExport.class); /* - * + * */ public static void main(String[] argv) throws Exception { @@ -390,7 +393,7 @@ public class ItemExport /** * Discover the different schemas in use and output a separate metadata XML * file for each schema. - * + * * @param c * @param i * @param destDir @@ -561,7 +564,7 @@ public class ItemExport * were originally registered will be marked in the contents file as such. * However, the export directory will contain actual copies of the content * files being exported. - * + * * @param c * the DSpace context * @param i @@ -720,7 +723,7 @@ public class ItemExport /** * Convenience methot to create export a single Community, Collection, or * Item - * + * * @param dso * - the dspace object to export * @param context @@ -740,7 +743,7 @@ public class ItemExport /** * Convenience method to export a List of dspace objects (Community, * Collection or Item) - * + * * @param dsObjects * - List containing dspace objects * @param context @@ -758,7 +761,7 @@ public class ItemExport /** * Convenience methot to create export a single Community, Collection, or * Item - * + * * @param dso * - the dspace object to export * @param context @@ -778,7 +781,7 @@ public class ItemExport /** * Convenience method to export a List of dspace objects (Community, * Collection or Item) - * + * * @param dsObjects * - List containing dspace objects * @param context @@ -797,7 +800,7 @@ public class ItemExport * Does the work creating a List with all the Items in the Community or * Collection It then kicks off a new Thread to export the items, zip the * export directory and send confirmation email - * + * * @param dsObjects * - List of dspace objects to process * @param context @@ -821,16 +824,17 @@ public class ItemExport // items // it will be checked against the config file entry double size = 0; - final ArrayList<Integer> items = new ArrayList<Integer>(); + final HashMap<String, List<Integer>> itemsMap = new HashMap<String, List<Integer>>(); for (DSpaceObject dso : dsObjects) { if (dso.getType() == Constants.COMMUNITY) { Community community = (Community) dso; // get all the collections in the community - Collection[] collections = community.getCollections(); + Collection[] collections = community.getAllCollections(); for (Collection collection : collections) { + ArrayList<Integer> items = new ArrayList<Integer>(); // get all the items in each collection ItemIterator iitems = collection.getItems(); try @@ -859,12 +863,18 @@ public class ItemExport { iitems.close(); } + if (items.size() > 0) + { + itemsMap.put("collection_"+collection.getID(), items); + } } } } else if (dso.getType() == Constants.COLLECTION) { Collection collection = (Collection) dso; + ArrayList<Integer> items = new ArrayList<Integer>(); + // get all the items in the collection ItemIterator iitems = collection.getItems(); try @@ -893,6 +903,10 @@ public class ItemExport { iitems.close(); } + if (items.size() > 0) + { + itemsMap.put("collection_"+collection.getID(), items); + } } } else if (dso.getType() == Constants.ITEM) @@ -910,7 +924,9 @@ public class ItemExport size += bit.getSize(); } } + ArrayList<Integer> items = new ArrayList<Integer>(); items.add(item.getID()); + itemsMap.put("item_"+item.getID(), items); } else { @@ -941,8 +957,8 @@ public class ItemExport } } - // if we have any items to process then kick off annonymous thread - if (items.size() > 0) + // if we have any items to process then kick off anonymous thread + if (itemsMap.size() > 0) { Thread go = new Thread() { @@ -955,40 +971,52 @@ public class ItemExport // create a new dspace context context = new Context(); // ignore auths - context.setIgnoreAuthorization(true); - iitems = new ItemIterator(context, items); + context.turnOffAuthorisationSystem(); String fileName = assembleFileName("item", eperson, new Date()); - String workDir = getExportWorkDirectory() + String workParentDir = getExportWorkDirectory() + System.getProperty("file.separator") + fileName; String downloadDir = getExportDownloadDirectory(eperson .getID()); - - File wkDir = new File(workDir); - if (!wkDir.exists() && !wkDir.mkdirs()) - { - log.error("Unable to create working directory"); - } - File dnDir = new File(downloadDir); if (!dnDir.exists() && !dnDir.mkdirs()) { log.error("Unable to create download directory"); } - // export the items using normal export method - exportItem(context, iitems, workDir, 1, migrate); + Iterator<String> iter = itemsMap.keySet().iterator(); + while(iter.hasNext()) + { + String keyName = iter.next(); + iitems = new ItemIterator(context, itemsMap.get(keyName)); + + String workDir = workParentDir + + System.getProperty("file.separator") + + keyName; + + File wkDir = new File(workDir); + if (!wkDir.exists() && !wkDir.mkdirs()) + { + log.error("Unable to create working directory"); + } + + + // export the items using normal export method + exportItem(context, iitems, workDir, 1, migrate); + iitems.close(); + } + // now zip up the export directory created above - zip(workDir, downloadDir + zip(workParentDir, downloadDir + System.getProperty("file.separator") + fileName + ".zip"); // email message letting user know the file is ready for // download emailSuccessMessage(context, eperson, fileName + ".zip"); // return to enforcing auths - context.setIgnoreAuthorization(false); + context.restoreAuthSystemState(); } catch (Exception e1) { @@ -1008,7 +1036,7 @@ public class ItemExport { iitems.close(); } - + // Make sure the database connection gets closed in all conditions. try { context.complete(); @@ -1023,11 +1051,16 @@ public class ItemExport go.isDaemon(); go.start(); } + else + { + Locale supportedLocale = I18nUtil.getEPersonLocale(eperson); + emailErrorMessage(eperson, I18nUtil.getMessage("org.dspace.app.itemexport.no-result", supportedLocale)); + } } /** * Create a file name based on the date and eperson - * + * * @param eperson * - eperson who requested export and will be able to download it * @param date @@ -1061,7 +1094,7 @@ public class ItemExport /** * Use config file entry for org.dspace.app.itemexport.download.dir and id * of the eperson to create a download directory name - * + * * @param ePersonID * - id of the eperson who requested export archive * @return String representing a directory in the form of @@ -1085,7 +1118,7 @@ public class ItemExport /** * Returns config file entry for org.dspace.app.itemexport.work.dir - * + * * @return String representing config file entry for * org.dspace.app.itemexport.work.dir * @throws Exception @@ -1104,7 +1137,7 @@ public class ItemExport /** * Used to read the export archived. Inteded for download. - * + * * @param fileName * the name of the file to download * @param eperson @@ -1129,7 +1162,7 @@ public class ItemExport /** * Get the file size of the export archive represented by the file name. - * + * * @param fileName * name of the file to get the size. * @throws Exception @@ -1175,7 +1208,7 @@ public class ItemExport * The file name of the export archive contains the eperson id of the person * who created it When requested for download this method can check if the * person requesting it is the same one that created it - * + * * @param context * dspace context * @param fileName @@ -1208,7 +1241,7 @@ public class ItemExport /** * Reads the download directory for the eperson to see if any export * archives are available - * + * * @param eperson * @return a list of file names representing export archives that have been * processed @@ -1245,7 +1278,7 @@ public class ItemExport * A clean up method that is ran before a new export archive is created. It * uses the config file entry 'org.dspace.app.itemexport.life.span.hours' to * determine if the current exports are too old and need pruging - * + * * @param epersonID * - the id of the eperson to clean up * @throws Exception @@ -1328,7 +1361,7 @@ public class ItemExport * with calling method about success or failure. We accomplis this * communication with email instead. Send a success email once the export * archive is complete and ready for download - * + * * @param context * - the current Context * @param eperson @@ -1344,7 +1377,7 @@ public class ItemExport try { Locale supportedLocale = I18nUtil.getEPersonLocale(eperson); - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(supportedLocale, "export_success")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "export_success")); email.addRecipient(eperson.getEmail()); email.addArgument(ConfigurationManager.getProperty("dspace.url") + "/exportdownload/" + fileName); email.addArgument(ConfigurationManager.getProperty("org.dspace.app.itemexport.life.span.hours")); @@ -1362,7 +1395,7 @@ public class ItemExport * with calling method about success or failure. We accomplis this * communication with email instead. Send an error email if the export * archive fails - * + * * @param eperson * - EPerson to send the error message to * @param error @@ -1376,7 +1409,7 @@ public class ItemExport try { Locale supportedLocale = I18nUtil.getEPersonLocale(eperson); - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(supportedLocale, "export_error")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "export_error")); email.addRecipient(eperson.getEmail()); email.addArgument(error); email.addArgument(ConfigurationManager.getProperty("dspace.url") + "/feedback"); @@ -1461,7 +1494,7 @@ public class ItemExport // byte[] b = new byte[ (int)(cpFile.length()) ]; - cpFileInputStream = new FileInputStream(cpFile); + cpFileInputStream = new FileInputStream(cpFile); ZipEntry cpZipEntry = new ZipEntry(strZipEntryName); cpZipOutputStream.putNextEntry(cpZipEntry); diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/DataLoaderService.java b/dspace-api/src/main/java/org/dspace/app/itemimport/DataLoaderService.java deleted file mode 100644 index 99cb0f9f95e189b79ba2cd59d85a04c292844fe9..0000000000000000000000000000000000000000 --- a/dspace-api/src/main/java/org/dspace/app/itemimport/DataLoaderService.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.itemimport; - -import java.util.HashMap; -import java.util.Map; - -import gr.ekt.transformationengine.core.DataLoader; - - - - -/** - * This class acts as a Service in the procedure ot batch import using the Biblio-Transformation-Engine - */ -public class DataLoaderService -{ - - Map<String, DataLoader> dataLoaders = new HashMap<String, DataLoader>(); - - /** - * Default constructor - */ - public DataLoaderService() - { - super(); - } - - /** - * Setter method for dataLoaders parameter - * @param dataLoaders - */ - public void setDataLoaders(Map<String, DataLoader> dataLoaders) - { - this.dataLoaders = dataLoaders; - } - - /** - * - * @return the map of DataLoaders - */ - public Map<String, DataLoader> getDataLoaders() - { - return dataLoaders; - } - -} diff --git a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImport.java b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImport.java index dce235d9497e9613bf99b88dfe83eaa8ea9fb1d6..1a4602af166ed071e906731be0f7d3e1101da214 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImport.java +++ b/dspace-api/src/main/java/org/dspace/app/itemimport/ItemImport.java @@ -7,20 +7,22 @@ */ package org.dspace.app.itemimport; -import gr.ekt.transformationengine.core.DataLoader; -import gr.ekt.transformationengine.core.TransformationEngine; -import gr.ekt.transformationengine.exceptions.UnimplementedAbstractMethod; -import gr.ekt.transformationengine.exceptions.UnknownClassifierException; -import gr.ekt.transformationengine.exceptions.UnknownInputFileType; -import gr.ekt.transformationengine.exceptions.UnsupportedComparatorMode; -import gr.ekt.transformationengine.exceptions.UnsupportedCriterion; +import gr.ekt.bte.core.DataLoader; +import gr.ekt.bte.core.TransformationEngine; +import gr.ekt.bte.core.TransformationResult; +import gr.ekt.bte.core.TransformationSpec; +import gr.ekt.bte.dataloader.FileDataLoader; +import gr.ekt.bteio.generators.DSpaceOutputGenerator; +import gr.ekt.bteio.loaders.OAIPMHDataLoader; import java.io.*; import java.sql.SQLException; +import java.text.SimpleDateFormat; import java.util.*; import java.util.zip.ZipFile; import java.util.zip.ZipEntry; +import javax.mail.MessagingException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -31,9 +33,11 @@ import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.PosixParser; +import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.xpath.XPathAPI; +import org.dspace.app.itemexport.ItemExportException; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeManager; import org.dspace.authorize.ResourcePolicy; @@ -41,19 +45,26 @@ import org.dspace.content.Bitstream; import org.dspace.content.BitstreamFormat; import org.dspace.content.Bundle; import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DSpaceObject; import org.dspace.content.FormatIdentifier; import org.dspace.content.InstallItem; import org.dspace.content.Item; +import org.dspace.content.ItemIterator; import org.dspace.content.MetadataField; import org.dspace.content.MetadataSchema; import org.dspace.content.WorkspaceItem; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; +import org.dspace.core.Email; +import org.dspace.core.I18nUtil; +import org.dspace.core.LogManager; import org.dspace.eperson.EPerson; import org.dspace.eperson.Group; import org.dspace.handle.HandleManager; import org.dspace.search.DSIndexer; +import org.dspace.utils.DSpace; import org.dspace.workflow.WorkflowManager; import org.dspace.xmlworkflow.XmlWorkflowManager; import org.w3c.dom.Document; @@ -62,7 +73,6 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; -import org.dspace.utils.DSpace; /** * Import items into DSpace. The conventional use is upload files by copying @@ -206,7 +216,7 @@ public class ItemImport if (line.hasOption('i')) { - bteInputType = line.getOptionValue('i');; + bteInputType = line.getOptionValue('i'); } if (line.hasOption('w')) @@ -314,13 +324,7 @@ public class ItemImport } else if ("add-bte".equals(command)) { - if (sourcedir == null) - { - System.out - .println("Error - a source file containing items must be set"); - System.out.println(" (run with -h flag for details)"); - System.exit(1); - } + //Source dir can be null, the user can specify the parameters for his loader in the Spring XML configuration file if (mapfile == null) { @@ -572,7 +576,7 @@ public class ItemImport } else if ("add-bte".equals(command)) { - myloader.addBTEItems(c, mycollections, sourcedir, mapfile, template, bteInputType); + myloader.addBTEItems(c, mycollections, sourcedir, mapfile, template, bteInputType, null); } // complete all transactions @@ -631,47 +635,97 @@ public class ItemImport System.exit(status); } + /** + * In this method, the BTE is instantiated. THe workflow generates the DSpace files + * necessary for the upload, and the default item import method is called + * @param c The contect + * @param mycollections The collections the items are inserted to + * @param sourceDir The filepath to the file to read data from + * @param mapFile The filepath to mapfile to be generated + * @param template + * @param inputType The type of the input data (bibtex, csv, etc.) + * @param workingDir The path to create temporary files (for command line or UI based) + * @throws Exception + */ private void addBTEItems(Context c, Collection[] mycollections, - String sourceDir, String mapFile, boolean template, String inputType) throws Exception + String sourceDir, String mapFile, boolean template, String inputType, String workingDir) throws Exception { - TransformationEngine te = new DSpace().getSingletonService(TransformationEngine.class); - - DataLoaderService dls = new DSpace().getSingletonService(DataLoaderService.class); + //Determine the folder where BTE will output the results + String outputFolder = null; + if (workingDir == null){ //This indicates a command line import, create a random path + File importDir = new File(ConfigurationManager.getProperty("org.dspace.app.batchitemimport.work.dir")); + if (!importDir.exists()){ + boolean success = importDir.mkdir(); + if (!success) { + log.info("Cannot create batch import directory!"); + throw new Exception("Cannot create batch import directory!"); + } + } + //Get a random folder in case two admins batch import data at the same time + outputFolder = importDir + File.separator + generateRandomFilename(true); + } + else { //This indicates a UI import, working dir is preconfigured + outputFolder = workingDir + File.separator + ".bte_output_dspace"; + } + + BTEBatchImportService dls = new DSpace().getSingletonService(BTEBatchImportService.class); DataLoader dataLoader = dls.getDataLoaders().get(inputType); + Map<String, String> outputMap = dls.getOutputMap(); + TransformationEngine te = dls.getTransformationEngine(); + + if (dataLoader==null){ + System.out.println("ERROR: The key used in -i parameter must match a valid DataLoader in the BTE Spring XML configuration file!"); + return; + } + + if (outputMap==null){ + System.out.println("ERROR: The key used in -i parameter must match a valid outputMapping in the BTE Spring XML configuration file!"); + return; + } + if (dataLoader instanceof FileDataLoader){ + FileDataLoader fdl = (FileDataLoader) dataLoader; + if (!StringUtils.isBlank(sourceDir)) { + System.out.println("INFO: Dataloader will load data from the file specified in the command prompt (and not from the Spring XML configuration file)"); + fdl.setFilename(sourceDir); + } + } + else if (dataLoader instanceof OAIPMHDataLoader){ + OAIPMHDataLoader fdl = (OAIPMHDataLoader) dataLoader; + System.out.println(sourceDir); + if (!StringUtils.isBlank(sourceDir)){ + System.out.println("INFO: Dataloader will load data from the address specified in the command prompt (and not from the Spring XML configuration file)"); + fdl.setServerAddress(sourceDir); + } + } if (dataLoader!=null){ System.out.println("INFO: Dataloader " + dataLoader.toString()+" will be used for the import!"); - - dataLoader.setFileName(sourceDir); - te.setDataLoader(dataLoader); - try { - te.transform(); - } catch (UnknownClassifierException e) { - e.printStackTrace(); - } catch (UnknownInputFileType e) { - e.printStackTrace(); - } catch (UnimplementedAbstractMethod e) { - e.printStackTrace(); - } catch (UnsupportedComparatorMode e) { - e.printStackTrace(); - } catch (UnsupportedCriterion e) { - e.printStackTrace(); - } + te.setDataLoader(dataLoader); + + DSpaceOutputGenerator outputGenerator = new DSpaceOutputGenerator(outputMap); + outputGenerator.setOutputDirectory(outputFolder); + + te.setOutputGenerator(outputGenerator); + + try { + TransformationResult res = te.transform(new TransformationSpec()); + List<String> output = res.getOutput(); + outputGenerator.writeOutput(output); + } catch (Exception e) { + System.err.println("Exception"); + e.printStackTrace(); + throw e; + } - ItemImport myloader = new ItemImport(); - myloader.addItems(c, mycollections, "./bte_output_dspace", mapFile, template); + ItemImport myloader = new ItemImport(); + myloader.addItems(c, mycollections, outputFolder, mapFile, template); - //remove files from output generator - deleteDirectory(new File("./bte_output_dspace")); - } - else { - System.out.println("Error: The key used in -i parameter must match a valid DataLoader in the BTE Spring XML configuration file!"); - return; + //remove files from output generator + deleteDirectory(new File(outputFolder)); } } - private void addItems(Context c, Collection[] mycollections, String sourceDir, String mapFile, boolean template) throws Exception { @@ -708,8 +762,7 @@ public class ItemImport if (d == null || !d.isDirectory()) { - System.out.println("Error, cannot open source directory " + sourceDir); - System.exit(1); + throw new Exception("Error, cannot open source directory " + sourceDir); } String[] dircontents = d.list(directoryFilter); @@ -739,9 +792,8 @@ public class ItemImport if (d == null || !d.isDirectory()) { - System.out.println("Error, cannot open source directory " + throw new Exception("Error, cannot open source directory " + sourceDir); - System.exit(1); } // read in HashMap first, to get list of handles & source dirs @@ -1287,11 +1339,33 @@ public class ItemImport + sRegistrationLine); continue; } - registerBitstream(c, i, iAssetstore, sFilePath, sBundle); + + // look for descriptions + boolean descriptionExists = false; + String descriptionMarker = "\tdescription:"; + int dMarkerIndex = line.indexOf(descriptionMarker); + int dEndIndex = 0; + if (dMarkerIndex > 0) + { + dEndIndex = line.indexOf("\t", dMarkerIndex + 1); + if (dEndIndex == -1) + { + dEndIndex = line.length(); + } + descriptionExists = true; + } + String sDescription = ""; + if (descriptionExists) + { + sDescription = line.substring(dMarkerIndex, dEndIndex); + sDescription = sDescription.replaceFirst("description:", ""); + } + + registerBitstream(c, i, iAssetstore, sFilePath, sBundle, sDescription); System.out.println("\tRegistering Bitstream: " + sFilePath + "\tAssetstore: " + iAssetstore + "\tBundle: " + sBundle - + "\tDescription: " + sBundle); + + "\tDescription: " + sDescription); continue; // process next line in contents file } @@ -1518,7 +1592,7 @@ public class ItemImport * @throws AuthorizeException */ private void registerBitstream(Context c, Item i, int assetstore, - String bitstreamPath, String bundleName ) + String bitstreamPath, String bundleName, String description ) throws SQLException, IOException, AuthorizeException { // TODO validate assetstore number @@ -1546,7 +1620,7 @@ public class ItemImport // find the bundle Bundle[] bundles = i.getBundles(newBundleName); Bundle targetBundle = null; - + if( bundles.length < 1 ) { // not found, create a new one @@ -1557,19 +1631,20 @@ public class ItemImport // put bitstreams into first bundle targetBundle = bundles[0]; } - + // now add the bitstream bs = targetBundle.registerBitstream(assetstore, bitstreamPath); - + // set the name to just the filename int iLastSlash = bitstreamPath.lastIndexOf('/'); bs.setName(bitstreamPath.substring(iLastSlash + 1)); - + // Identify the format // FIXME - guessing format guesses license.txt incorrectly as a text file format! BitstreamFormat bf = FormatIdentifier.guessFormat(c, bs); bs.setFormat(bf); - + bs.setDescription(description); + bs.update(); } } @@ -1876,4 +1951,193 @@ public class ItemImport boolean pathDeleted = path.delete(); return (pathDeleted); } + + /** + * Generate a random filename based on current time + * @param hidden: add . as a prefix to make the file hidden + * @return the filename + */ + private static String generateRandomFilename(boolean hidden) + { + String filename = String.format("%s", RandomStringUtils.randomAlphanumeric(8)); + SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmm"); + String datePart = sdf.format(new Date()); + filename = datePart+"_"+filename; + + return filename; + } + + /** + * Given an uploaded file, this method calls the method to instantiate a BTE instance to + * transform the input data and batch import them to DSpace + * @param file The input file to read data from + * @param collections The collections the created items will be inserted to + * @param bteInputType The input type of the data (bibtex, csv, etc.) + * @param context The context + * @throws Exception + */ + public static void processUploadableImport(File file, Collection[] collections, + String bteInputType, Context context) throws Exception + { + final EPerson eperson = context.getCurrentUser(); + final File myFile = file; + final Collection[] mycollections = collections; + final String myBteInputType = bteInputType; + + // if the file exists + if (file.exists()) + { + Thread go = new Thread() + { + public void run() + { + Context context = null; + ItemIterator iitems = null; + try + { + // create a new dspace context + context = new Context(); + context.setCurrentUser(eperson); + context.setIgnoreAuthorization(true); + + File importDir = new File(ConfigurationManager.getProperty("org.dspace.app.batchitemimport.work.dir")); + if (!importDir.exists()){ + boolean success = importDir.mkdir(); + if (!success) { + log.info("Cannot create batch import directory!"); + throw new Exception(); + } + } + //Generate a random filename for the subdirectory of the specific import in case + //more that one batch imports take place at the same time + String subDirName = generateRandomFilename(false); + String workingDir = importDir.getAbsolutePath() + File.separator + subDirName; + + //Create the import working directory + boolean success = (new File(workingDir)).mkdir(); + if (!success) { + log.info("Cannot create batch import working directory!"); + throw new Exception(); + } + + //Create random mapfile; + String mapfile = workingDir + File.separator+ "mapfile"; + + ItemImport myloader = new ItemImport(); + myloader.addBTEItems(context, mycollections, myFile.getAbsolutePath(), mapfile, template, myBteInputType, workingDir); + + // email message letting user know the file is ready for + // download + emailSuccessMessage(context, eperson, mapfile); + + // return to enforcing auths + context.setIgnoreAuthorization(false); + } + catch (Exception e1) + { + try + { + emailErrorMessage(eperson, e1.getMessage()); + } + catch (Exception e) + { + // wont throw here + } + throw new IllegalStateException(e1); + } + finally + { + if (iitems != null) + { + iitems.close(); + } + + // close the mapfile writer + if (mapOut != null) + { + mapOut.close(); + } + + // Make sure the database connection gets closed in all conditions. + try { + context.complete(); + } catch (SQLException sqle) { + context.abort(); + } + } + } + + }; + + go.isDaemon(); + go.start(); + } + else { + log.error("Unable to find the uploadable file"); + } + } + + /** + * Since the BTE batch import is done in a new thread we are unable to communicate + * with calling method about success or failure. We accomplish this + * communication with email instead. Send a success email once the batch + * import is complete + * + * @param context + * - the current Context + * @param eperson + * - eperson to send the email to + * @param fileName + * - the filepath to the mapfile created by the batch import + * @throws MessagingException + */ + public static void emailSuccessMessage(Context context, EPerson eperson, + String fileName) throws MessagingException + { + try + { + Locale supportedLocale = I18nUtil.getEPersonLocale(eperson); + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "bte_batch_import_success")); + email.addRecipient(eperson.getEmail()); + email.addArgument(fileName); + + email.send(); + } + catch (Exception e) + { + log.warn(LogManager.getHeader(context, "emailSuccessMessage", "cannot notify user of export"), e); + } + } + + /** + * Since the BTE batch import is done in a new thread we are unable to communicate + * with calling method about success or failure. We accomplis this + * communication with email instead. Send an error email if the batch + * import fails + * + * @param eperson + * - EPerson to send the error message to + * @param error + * - the error message + * @throws MessagingException + */ + public static void emailErrorMessage(EPerson eperson, String error) + throws MessagingException + { + log.warn("An error occured during item export, the user will be notified. " + error); + try + { + Locale supportedLocale = I18nUtil.getEPersonLocale(eperson); + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "bte_batch_import_error")); + email.addRecipient(eperson.getEmail()); + email.addArgument(error); + email.addArgument(ConfigurationManager.getProperty("dspace.url") + "/feedback"); + + email.send(); + } + catch (Exception e) + { + log.warn("error during item export error notification", e); + } + } } diff --git a/dspace-api/src/main/java/org/dspace/app/itemupdate/ItemUpdate.java b/dspace-api/src/main/java/org/dspace/app/itemupdate/ItemUpdate.java index cce1bb00b7a62494d1af9f45c93ba30bb9051139..b3636628a6929bb3927e7f62714712f29380d8b4 100644 --- a/dspace-api/src/main/java/org/dspace/app/itemupdate/ItemUpdate.java +++ b/dspace-api/src/main/java/org/dspace/app/itemupdate/ItemUpdate.java @@ -515,7 +515,7 @@ public class ItemUpdate { private File initUndoArchive(File sourceDir) throws FileNotFoundException, IOException { - File parentDir = sourceDir.getAbsoluteFile().getParentFile(); + File parentDir = sourceDir.getCanonicalFile().getParentFile(); if (parentDir == null) { throw new FileNotFoundException("Parent directory of archive directory not found; unable to write UndoArchive; no processing performed"); @@ -533,8 +533,8 @@ public class ItemUpdate { // create root directory if (!undoDir.mkdir()) { - pr("ERROR creating Undo Archive directory "); - throw new IOException("ERROR creating Undo Archive directory "); + pr("ERROR creating Undo Archive directory " + undoDir.getCanonicalPath()); + throw new IOException("ERROR creating Undo Archive directory " + undoDir.getCanonicalPath()); } //Undo is suppressed to prevent undo of undo diff --git a/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java b/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java index e912038b8989369b9e55b9f398c8fc1994640420..202c877346516c3dfd3a2c9506176359455f3753 100644 --- a/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java +++ b/dspace-api/src/main/java/org/dspace/app/launcher/ScriptLauncher.java @@ -7,6 +7,10 @@ */ package org.dspace.app.launcher; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.List; import org.dspace.core.ConfigurationManager; import org.dspace.servicemanager.DSpaceKernelImpl; import org.dspace.servicemanager.DSpaceKernelInit; @@ -14,8 +18,6 @@ import org.dspace.services.RequestService; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; -import java.util.List; -import java.lang.reflect.Method; /** * A DSpace script launcher. @@ -28,12 +30,16 @@ public class ScriptLauncher /** The service manager kernel */ private static transient DSpaceKernelImpl kernelImpl; + /** Definitions of all commands. */ + private static final Document commandConfigs = getConfig(); + /** * Execute the DSpace script launcher * * @param args Any parameters required to be passed to the scripts it executes */ public static void main(String[] args) + throws FileNotFoundException, IOException { // Check that there is at least one argument if (args.length < 1) @@ -66,168 +72,176 @@ public class ScriptLauncher throw new IllegalStateException(message, e); } - // Parse the configuration file looking for the command entered - Document doc = getConfig(); + // Look up command in the configuration, and execute. + int status; + status = runOneCommand(args); + + // Destroy the service kernel if it is still alive + if (kernelImpl != null) + { + kernelImpl.destroy(); + kernelImpl = null; + } + + System.exit(status); + } + + /** + * Recognize and execute a single command. + * @param doc + * @param args + */ + static int runOneCommand(String[] args) + { String request = args[0]; - Element root = doc.getRootElement(); + Element root = commandConfigs.getRootElement(); List<Element> commands = root.getChildren("command"); - for (Element command : commands) + Element command = null; + for (Element candidate : commands) { - if (request.equalsIgnoreCase(command.getChild("name").getValue())) + if (request.equalsIgnoreCase(candidate.getChild("name").getValue())) { - // Run each step - List<Element> steps = command.getChildren("step"); - for (Element step : steps) - { - // Instantiate the class - Class target = null; - - // Is it the special case 'dsrun' where the user provides the class name? - String className; - if ("dsrun".equals(request)) - { - if (args.length < 2) - { - System.err.println("Error in launcher.xml: Missing class name"); - System.exit(1); - } - className = args[1]; - } - else { - className = step.getChild("class").getValue(); - } - try - { - target = Class.forName(className, - true, - Thread.currentThread().getContextClassLoader()); - } - catch (ClassNotFoundException e) - { - System.err.println("Error in launcher.xml: Invalid class name: " + className); - System.exit(1); - } - - // Strip the leading argument from the args, and add the arguments - // Set <passargs>false</passargs> if the arguments should not be passed on - String[] useargs = args.clone(); - Class[] argTypes = {useargs.getClass()}; - boolean passargs = true; - if ((step.getAttribute("passuserargs") != null) && - ("false".equalsIgnoreCase(step.getAttribute("passuserargs").getValue()))) - { - passargs = false; - } - if ((args.length == 1) || (("dsrun".equals(request)) && (args.length == 2)) || (!passargs)) - { - useargs = new String[0]; - } - else - { - // The number of arguments to ignore - // If dsrun is the command, ignore the next, as it is the class name not an arg - int x = 1; - if ("dsrun".equals(request)) - { - x = 2; - } - String[] argsnew = new String[useargs.length - x]; - for (int i = x; i < useargs.length; i++) - { - argsnew[i - x] = useargs[i]; - } - useargs = argsnew; - } - - // Add any extra properties - List<Element> bits = step.getChildren("argument"); - if (step.getChild("argument") != null) - { - String[] argsnew = new String[useargs.length + bits.size()]; - int i = 0; - for (Element arg : bits) - { - argsnew[i++] = arg.getValue(); - } - for (; i < bits.size() + useargs.length; i++) - { - argsnew[i] = useargs[i - bits.size()]; - } - useargs = argsnew; - } - - // Establish the request service startup - RequestService requestService = kernelImpl.getServiceManager().getServiceByName(RequestService.class.getName(), RequestService.class); - if (requestService == null) { - throw new IllegalStateException("Could not get the DSpace RequestService to start the request transaction"); - } + command = candidate; + break; + } + } - // Establish a request related to the current session - // that will trigger the various request listeners - requestService.startRequest(); + if (null == command) + { + // The command wasn't found + System.err.println("Command not found: " + args[0]); + display(); + return 1; + } - // Run the main() method - try - { - Object[] arguments = {useargs}; + // Run each step + List<Element> steps = command.getChildren("step"); + for (Element step : steps) + { + // Instantiate the class + Class target = null; - // Useful for debugging, so left in the code... - /**System.out.print("About to execute: " + className); - for (String param : useargs) - { - System.out.print(" " + param); - } - System.out.println("");**/ + // Is it the special case 'dsrun' where the user provides the class name? + String className; + if ("dsrun".equals(request)) + { + if (args.length < 2) + { + System.err.println("Error in launcher.xml: Missing class name"); + return 1; + } + className = args[1]; + } + else { + className = step.getChild("class").getValue(); + } + try + { + target = Class.forName(className, + true, + Thread.currentThread().getContextClassLoader()); + } + catch (ClassNotFoundException e) + { + System.err.println("Error in launcher.xml: Invalid class name: " + className); + return 1; + } - Method main = target.getMethod("main", argTypes); - main.invoke(null, arguments); + // Strip the leading argument from the args, and add the arguments + // Set <passargs>false</passargs> if the arguments should not be passed on + String[] useargs = args.clone(); + Class[] argTypes = {useargs.getClass()}; + boolean passargs = true; + if ((step.getAttribute("passuserargs") != null) && + ("false".equalsIgnoreCase(step.getAttribute("passuserargs").getValue()))) + { + passargs = false; + } + if ((args.length == 1) || (("dsrun".equals(request)) && (args.length == 2)) || (!passargs)) + { + useargs = new String[0]; + } + else + { + // The number of arguments to ignore + // If dsrun is the command, ignore the next, as it is the class name not an arg + int x = 1; + if ("dsrun".equals(request)) + { + x = 2; + } + String[] argsnew = new String[useargs.length - x]; + for (int i = x; i < useargs.length; i++) + { + argsnew[i - x] = useargs[i]; + } + useargs = argsnew; + } - // ensure we close out the request (happy request) - requestService.endRequest(null); - } - catch (Exception e) - { - // Failure occurred in the request so we destroy it - requestService.endRequest(e); + // Add any extra properties + List<Element> bits = step.getChildren("argument"); + if (step.getChild("argument") != null) + { + String[] argsnew = new String[useargs.length + bits.size()]; + int i = 0; + for (Element arg : bits) + { + argsnew[i++] = arg.getValue(); + } + for (; i < bits.size() + useargs.length; i++) + { + argsnew[i] = useargs[i - bits.size()]; + } + useargs = argsnew; + } - if (kernelImpl != null) - { - kernelImpl.destroy(); - kernelImpl = null; - } + // Establish the request service startup + RequestService requestService = kernelImpl.getServiceManager().getServiceByName( + RequestService.class.getName(), RequestService.class); + if (requestService == null) + { + throw new IllegalStateException( + "Could not get the DSpace RequestService to start the request transaction"); + } - // Exceptions from the script are reported as a 'cause' - Throwable cause = e.getCause(); - System.err.println("Exception: " + cause.getMessage()); - cause.printStackTrace(); - System.exit(1); - } + // Establish a request related to the current session + // that will trigger the various request listeners + requestService.startRequest(); - } + // Run the main() method + try + { + Object[] arguments = {useargs}; - // Destroy the service kernel - if (kernelImpl != null) + // Useful for debugging, so left in the code... + /**System.out.print("About to execute: " + className); + for (String param : useargs) { - kernelImpl.destroy(); - kernelImpl = null; + System.out.print(" " + param); } + System.out.println("");**/ + + Method main = target.getMethod("main", argTypes); + main.invoke(null, arguments); - // Everything completed OK - System.exit(0); + // ensure we close out the request (happy request) + requestService.endRequest(null); } - } + catch (Exception e) + { + // Failure occurred in the request so we destroy it + requestService.endRequest(e); - // Destroy the service kernel if it is still alive - if (kernelImpl != null) - { - kernelImpl.destroy(); - kernelImpl = null; + // Exceptions from the script are reported as a 'cause' + Throwable cause = e.getCause(); + System.err.println("Exception: " + cause.getMessage()); + cause.printStackTrace(); + return 1; + } } - // The command wasn't found - System.err.println("Command not found: " + args[0]); - display(); - System.exit(1); + // Everything completed OK + return 0; } /** @@ -261,8 +275,7 @@ public class ScriptLauncher */ private static void display() { - Document doc = getConfig(); - List<Element> commands = doc.getRootElement().getChildren("command"); + List<Element> commands = commandConfigs.getRootElement().getChildren("command"); System.out.println("Usage: dspace [command-name] {parameters}"); for (Element command : commands) { diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/BrandedPreviewJPEGFilter.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/BrandedPreviewJPEGFilter.java index b6c9e157a3c9c3bc379470bb7359c56857d4f40d..6221692f2684a7e62aeec48108fe7601355f8188 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/BrandedPreviewJPEGFilter.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/BrandedPreviewJPEGFilter.java @@ -8,7 +8,10 @@ package org.dspace.app.mediafilter; import java.awt.Graphics2D; -import java.awt.image.BufferedImage; +import java.awt.Color; +import java.awt.image.*; +import java.awt.RenderingHints; +import java.awt.Transparency; import java.awt.Font; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -22,6 +25,8 @@ import org.dspace.core.ConfigurationManager; * Filter image bitstreams, scaling the image to be within the bounds of * thumbnail.maxwidth, thumbnail.maxheight, the size we want our thumbnail to be * no bigger than. Creates only JPEGs. + * + * @author Jason Sherman <jsherman@usao.edu> */ public class BrandedPreviewJPEGFilter extends MediaFilter { @@ -73,6 +78,10 @@ public class BrandedPreviewJPEGFilter extends MediaFilter .getIntProperty("webui.preview.maxwidth"); float ymax = (float) ConfigurationManager .getIntProperty("webui.preview.maxheight"); + boolean blurring = (boolean) ConfigurationManager + .getBooleanProperty("webui.preview.blurring"); + boolean hqscaling = (boolean) ConfigurationManager + .getBooleanProperty("webui.preview.hqscaling"); int brandHeight = ConfigurationManager.getIntProperty("webui.preview.brand.height"); String brandFont = ConfigurationManager.getProperty("webui.preview.brand.font"); int brandFontPoint = ConfigurationManager.getIntProperty("webui.preview.brand.fontpoint"); @@ -137,6 +146,23 @@ public class BrandedPreviewJPEGFilter extends MediaFilter BufferedImage branded = new BufferedImage((int) xsize, (int) ysize + brandHeight, BufferedImage.TYPE_INT_RGB); + // Use blurring if selected in config. + // a little blur before scaling does wonders for keeping moire in check. + if (blurring) + { + // send the buffered image off to get blurred. + buf = getBlurredInstance((BufferedImage) buf); + } + + // Use high quality scaling method if selected in config. + // this has a definite performance penalty. + if (hqscaling) + { + // send the buffered image off to get an HQ downscale. + buf = getScaledInstance((BufferedImage) buf, (int) xsize, (int) ysize, + (Object) RenderingHints.VALUE_INTERPOLATION_BICUBIC, (boolean) true); + } + // now render the image into the preview buffer Graphics2D g2d = branded.createGraphics(); g2d.drawImage(buf, 0, 0, (int) xsize, (int) ysize, null); @@ -158,4 +184,113 @@ public class BrandedPreviewJPEGFilter extends MediaFilter return bais; // hope this gets written out before its garbage collected! } + + public BufferedImage getNormalizedInstance(BufferedImage buf) + { + int type = (buf.getTransparency() == Transparency.OPAQUE) ? + BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB_PRE; + int w, h; + w = buf.getWidth(); + h = buf.getHeight(); + BufferedImage normal = new BufferedImage(w, h, type); + Graphics2D g2d = normal.createGraphics(); + g2d.drawImage(buf, 0, 0, w, h, Color.WHITE, null); + g2d.dispose(); + return normal; + } + + public BufferedImage getBlurredInstance(BufferedImage buf) + { + /** + * Convenience method that returns a blurred instance of the + * provided {@code BufferedImage}. + * + */ + + buf = getNormalizedInstance(buf); + + // kernel for blur op + float[] matrix = { + 0.111f, 0.111f, 0.111f, + 0.111f, 0.111f, 0.111f, + 0.111f, 0.111f, 0.111f, + }; + + // perform the blur and return the blurred version. + BufferedImageOp blur = new ConvolveOp( new Kernel(3, 3, matrix) ); + BufferedImage blurbuf = blur.filter(buf, null); + return blurbuf; + } + + /** + * Convenience method that returns a scaled instance of the + * provided {@code BufferedImage}. + * + * @param buf the original image to be scaled + * @param targetWidth the desired width of the scaled instance, + * in pixels + * @param targetHeight the desired height of the scaled instance, + * in pixels + * @param hint one of the rendering hints that corresponds to + * {@code RenderingHints.KEY_INTERPOLATION} (e.g. + * {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR}, + * {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR}, + * {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC}) + * @param higherQuality if true, this method will use a multi-step + * scaling technique that provides higher quality than the usual + * one-step technique (only useful in downscaling cases, where + * {@code targetWidth} or {@code targetHeight} is + * smaller than the original dimensions, and generally only when + * the {@code BILINEAR} hint is specified) + * @return a scaled version of the original {@code BufferedImage} + */ + public BufferedImage getScaledInstance(BufferedImage buf, + int targetWidth, + int targetHeight, + Object hint, + boolean higherQuality) + { + int type = (buf.getTransparency() == Transparency.OPAQUE) ? + BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; + BufferedImage scalebuf = (BufferedImage)buf; + int w, h; + if (higherQuality) { + // Use multi-step technique: start with original size, then + // scale down in multiple passes with drawImage() + // until the target size is reached + w = buf.getWidth(); + h = buf.getHeight(); + } else { + // Use one-step technique: scale directly from original + // size to target size with a single drawImage() call + w = targetWidth; + h = targetHeight; + } + + do { + if (higherQuality && w > targetWidth) { + w /= 2; + if (w < targetWidth) { + w = targetWidth; + } + } + + if (higherQuality && h > targetHeight) { + h /= 2; + if (h < targetHeight) { + h = targetHeight; + } + } + + BufferedImage tmp = new BufferedImage(w, h, type); + Graphics2D g2d = tmp.createGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); + g2d.drawImage(scalebuf, 0, 0, w, h, Color.WHITE, null); + g2d.dispose(); + + scalebuf = tmp; + } while (w != targetWidth || h != targetHeight); + + return scalebuf; + } } diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/JPEGFilter.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/JPEGFilter.java index c5ce549ffc3f4ffc8a1d861a1e9f618ca6971939..e8c4879c664051a66598171435cfaa3f8bac1c4f 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/JPEGFilter.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/JPEGFilter.java @@ -8,7 +8,10 @@ package org.dspace.app.mediafilter; import java.awt.Graphics2D; -import java.awt.image.BufferedImage; +import java.awt.Color; +import java.awt.image.*; +import java.awt.RenderingHints; +import java.awt.Transparency; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; @@ -21,6 +24,8 @@ import org.dspace.core.ConfigurationManager; * Filter image bitstreams, scaling the image to be within the bounds of * thumbnail.maxwidth, thumbnail.maxheight, the size we want our thumbnail to be * no bigger than. Creates only JPEGs. + * + * @author Jason Sherman <jsherman@usao.edu> */ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats { @@ -71,6 +76,10 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats .getIntProperty("thumbnail.maxwidth"); float ymax = (float) ConfigurationManager .getIntProperty("thumbnail.maxheight"); + boolean blurring = (boolean) ConfigurationManager + .getBooleanProperty("thumbnail.blurring"); + boolean hqscaling = (boolean) ConfigurationManager + .getBooleanProperty("thumbnail.hqscaling"); // now get the image dimensions float xsize = (float) buf.getWidth(null); @@ -131,6 +140,23 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats BufferedImage thumbnail = new BufferedImage((int) xsize, (int) ysize, BufferedImage.TYPE_INT_RGB); + // Use blurring if selected in config. + // a little blur before scaling does wonders for keeping moire in check. + if (blurring) + { + // send the buffered image off to get blurred. + buf = getBlurredInstance((BufferedImage) buf); + } + + // Use high quality scaling method if selected in config. + // this has a definite performance penalty. + if (hqscaling) + { + // send the buffered image off to get an HQ downscale. + buf = getScaledInstance((BufferedImage) buf, (int) xsize, (int) ysize, + (Object) RenderingHints.VALUE_INTERPOLATION_BICUBIC, (boolean) true); + } + // now render the image into the thumbnail buffer Graphics2D g2d = thumbnail.createGraphics(); g2d.drawImage(buf, 0, 0, (int) xsize, (int) ysize, null); @@ -163,4 +189,113 @@ public class JPEGFilter extends MediaFilter implements SelfRegisterInputFormats // return ImageIO.getReaderFileSuffixes(); return null; } + + public BufferedImage getNormalizedInstance(BufferedImage buf) + { + int type = (buf.getTransparency() == Transparency.OPAQUE) ? + BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB_PRE; + int w, h; + w = buf.getWidth(); + h = buf.getHeight(); + BufferedImage normal = new BufferedImage(w, h, type); + Graphics2D g2d = normal.createGraphics(); + g2d.drawImage(buf, 0, 0, w, h, Color.WHITE, null); + g2d.dispose(); + return normal; + } + + public BufferedImage getBlurredInstance(BufferedImage buf) + { + /** + * Convenience method that returns a blurred instance of the + * provided {@code BufferedImage}. + * + */ + + buf = getNormalizedInstance(buf); + + // kernel for blur op + float[] matrix = { + 0.111f, 0.111f, 0.111f, + 0.111f, 0.111f, 0.111f, + 0.111f, 0.111f, 0.111f, + }; + + // perform the blur and return the blurred version. + BufferedImageOp blur = new ConvolveOp( new Kernel(3, 3, matrix) ); + BufferedImage blurbuf = blur.filter(buf, null); + return blurbuf; + } + + /** + * Convenience method that returns a scaled instance of the + * provided {@code BufferedImage}. + * + * @param buf the original image to be scaled + * @param targetWidth the desired width of the scaled instance, + * in pixels + * @param targetHeight the desired height of the scaled instance, + * in pixels + * @param hint one of the rendering hints that corresponds to + * {@code RenderingHints.KEY_INTERPOLATION} (e.g. + * {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR}, + * {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR}, + * {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC}) + * @param higherQuality if true, this method will use a multi-step + * scaling technique that provides higher quality than the usual + * one-step technique (only useful in downscaling cases, where + * {@code targetWidth} or {@code targetHeight} is + * smaller than the original dimensions, and generally only when + * the {@code BILINEAR} hint is specified) + * @return a scaled version of the original {@code BufferedImage} + */ + public BufferedImage getScaledInstance(BufferedImage buf, + int targetWidth, + int targetHeight, + Object hint, + boolean higherQuality) + { + int type = (buf.getTransparency() == Transparency.OPAQUE) ? + BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; + BufferedImage scalebuf = (BufferedImage)buf; + int w, h; + if (higherQuality) { + // Use multi-step technique: start with original size, then + // scale down in multiple passes with drawImage() + // until the target size is reached + w = buf.getWidth(); + h = buf.getHeight(); + } else { + // Use one-step technique: scale directly from original + // size to target size with a single drawImage() call + w = targetWidth; + h = targetHeight; + } + + do { + if (higherQuality && w > targetWidth) { + w /= 2; + if (w < targetWidth) { + w = targetWidth; + } + } + + if (higherQuality && h > targetHeight) { + h /= 2; + if (h < targetHeight) { + h = targetHeight; + } + } + + BufferedImage tmp = new BufferedImage(w, h, type); + Graphics2D g2d = tmp.createGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); + g2d.drawImage(scalebuf, 0, 0, w, h, Color.WHITE, null); + g2d.dispose(); + + scalebuf = tmp; + } while (w != targetWidth || h != targetHeight); + + return scalebuf; + } } diff --git a/dspace-api/src/main/java/org/dspace/app/mediafilter/XPDF2Thumbnail.java b/dspace-api/src/main/java/org/dspace/app/mediafilter/XPDF2Thumbnail.java index e6fbe590123b749e20788f47ac5a71c4792e51a8..dc6768a189c3e56845e3a5e80d3d6cad9b95e006 100644 --- a/dspace-api/src/main/java/org/dspace/app/mediafilter/XPDF2Thumbnail.java +++ b/dspace-api/src/main/java/org/dspace/app/mediafilter/XPDF2Thumbnail.java @@ -8,7 +8,10 @@ package org.dspace.app.mediafilter; import java.awt.Graphics2D; -import java.awt.image.BufferedImage; +import java.awt.Color; +import java.awt.image.*; +import java.awt.RenderingHints; +import java.awt.Transparency; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -88,10 +91,10 @@ public class XPDF2Thumbnail extends MediaFilter "^Page\\s+\\d+\\s+MediaBox:\\s+([\\.\\d-]+)\\s+([\\.\\d-]+)\\s+([\\.\\d-]+)\\s+([\\.\\d-]+)"); // also from thumbnail.maxwidth in config - private int maxwidth = 0; + private int xmax = 0; // backup default for size, on the large side. - private static final int DEFAULT_MAXWIDTH = 500; + private static final int DEFAULT_XMAX = 500; public String getFilteredName(String oldFilename) { @@ -117,6 +120,16 @@ public class XPDF2Thumbnail extends MediaFilter public InputStream getDestinationStream(InputStream sourceStream) throws Exception { + // get config params + float xmax = (float) ConfigurationManager + .getIntProperty("thumbnail.maxwidth"); + float ymax = (float) ConfigurationManager + .getIntProperty("thumbnail.maxheight"); + boolean blurring = (boolean) ConfigurationManager + .getBooleanProperty("thumbnail.blurring"); + boolean hqscaling = (boolean) ConfigurationManager + .getBooleanProperty("thumbnail.hqscaling"); + // sanity check: xpdf paths are required. can cache since it won't change if (pdftoppmPath == null || pdfinfoPath == null) { @@ -130,10 +143,10 @@ public class XPDF2Thumbnail extends MediaFilter { throw new IllegalStateException("No value for key \"xpdf.path.pdfinfo\" in DSpace configuration! Should be path to XPDF pdfinfo executable."); } - maxwidth = ConfigurationManager.getIntProperty("thumbnail.maxwidth"); - if (maxwidth == 0) + + if (xmax == 0) { - maxwidth = DEFAULT_MAXWIDTH; + xmax = DEFAULT_XMAX; } } @@ -278,41 +291,224 @@ public class XPDF2Thumbnail extends MediaFilter { throw new IOException("Unknown failure while transforming file to preview: no image produced."); } + + // read in bitstream's image + BufferedImage buf = source; - // Scale image and return in-memory stream - BufferedImage toenail = scaleImage(source, maxwidth*3/4, maxwidth); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(toenail, "jpeg", baos); - return new ByteArrayInputStream(baos.toByteArray()); - } + // now get the image dimensions + float xsize = (float) buf.getWidth(null); + float ysize = (float) buf.getHeight(null); + + // if verbose flag is set, print out dimensions + // to STDOUT + if (MediaFilterManager.isVerbose) + { + System.out.println("original size: " + xsize + "," + ysize); + } + + // scale by x first if needed + if (xsize > xmax) + { + // calculate scaling factor so that xsize * scale = new size (max) + float scale_factor = xmax / xsize; - // scale the image, preserving aspect ratio, if at least one - // dimension is not between min and max. - private static BufferedImage scaleImage(BufferedImage source, - int min, int max) - { - int xsize = source.getWidth(null); - int ysize = source.getHeight(null); - int msize = Math.max(xsize, ysize); - BufferedImage result = null; - - // scale the image if it's outside of requested range. - // ALSO pass through if min and max are both 0 - if ((min == 0 && max == 0) || - (msize >= min && Math.min(xsize, ysize) <= max)) + // if verbose flag is set, print out extracted text + // to STDOUT + if (MediaFilterManager.isVerbose) + { + System.out.println("x scale factor: " + scale_factor); + } + + // now reduce x size + // and y size + xsize = xsize * scale_factor; + ysize = ysize * scale_factor; + + // if verbose flag is set, print out extracted text + // to STDOUT + if (MediaFilterManager.isVerbose) + { + System.out.println("new size: " + xsize + "," + ysize); + } + } + + // scale by y if needed + if (ysize > ymax) + { + float scale_factor = ymax / ysize; + + // now reduce x size + // and y size + xsize = xsize * scale_factor; + ysize = ysize * scale_factor; + } + + // if verbose flag is set, print details to STDOUT + if (MediaFilterManager.isVerbose) + { + System.out.println("created thumbnail size: " + xsize + ", " + + ysize); + } + + // create an image buffer for the thumbnail with the new xsize, ysize + BufferedImage thumbnail = new BufferedImage((int) xsize, (int) ysize, + BufferedImage.TYPE_INT_RGB); + + // Use blurring if selected in config. + // a little blur before scaling does wonders for keeping moire in check. + if (blurring) { - return source; + // send the buffered image off to get blurred. + buf = getBlurredInstance((BufferedImage) buf); } - else + + // Use high quality scaling method if selected in config. + // this has a definite performance penalty. + if (hqscaling) { - int xnew = xsize * max / msize; - int ynew = ysize * max / msize; - result = new BufferedImage(xnew, ynew, BufferedImage.TYPE_INT_RGB); - Graphics2D g2d = result.createGraphics(); - g2d.drawImage(source, 0, 0, xnew, ynew, null); - return result; + // send the buffered image off to get an HQ downscale. + buf = getScaledInstance((BufferedImage) buf, (int) xsize, (int) ysize, + (Object) RenderingHints.VALUE_INTERPOLATION_BICUBIC, (boolean) true); } + + // now render the image into the thumbnail buffer + Graphics2D g2d = thumbnail.createGraphics(); + g2d.drawImage(buf, 0, 0, (int) xsize, (int) ysize, null); + + // now create an input stream for the thumbnail buffer and return it + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + ImageIO.write(thumbnail, "jpeg", baos); + + // now get the array + ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + + return bais; // hope this gets written out before its garbage collected! } -} + + public String[] getInputMIMETypes() + { + return ImageIO.getReaderMIMETypes(); + } + + public String[] getInputDescriptions() + { + return null; + } + + public String[] getInputExtensions() + { + // Temporarily disabled as JDK 1.6 only + // return ImageIO.getReaderFileSuffixes(); + return null; + } + + public BufferedImage getNormalizedInstance(BufferedImage buf) + { + int type = (buf.getTransparency() == Transparency.OPAQUE) ? + BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB_PRE; + int w, h; + w = buf.getWidth(); + h = buf.getHeight(); + BufferedImage normal = new BufferedImage(w, h, type); + Graphics2D g2d = normal.createGraphics(); + g2d.drawImage(buf, 0, 0, w, h, Color.WHITE, null); + g2d.dispose(); + return normal; + } + + public BufferedImage getBlurredInstance(BufferedImage buf) + { + /** + * Convenience method that returns a blurred instance of the + * provided {@code BufferedImage}. + * + */ + + buf = getNormalizedInstance(buf); + + // kernel for blur op + float[] matrix = { + 0.111f, 0.111f, 0.111f, + 0.111f, 0.111f, 0.111f, + 0.111f, 0.111f, 0.111f, + }; - + // perform the blur and return the blurred version. + BufferedImageOp blur = new ConvolveOp( new Kernel(3, 3, matrix) ); + BufferedImage blurbuf = blur.filter(buf, null); + return blurbuf; + } + + /** + * Convenience method that returns a scaled instance of the + * provided {@code BufferedImage}. + * + * @param buf the original image to be scaled + * @param targetWidth the desired width of the scaled instance, + * in pixels + * @param targetHeight the desired height of the scaled instance, + * in pixels + * @param hint one of the rendering hints that corresponds to + * {@code RenderingHints.KEY_INTERPOLATION} (e.g. + * {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR}, + * {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR}, + * {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC}) + * @param higherQuality if true, this method will use a multi-step + * scaling technique that provides higher quality than the usual + * one-step technique (only useful in downscaling cases, where + * {@code targetWidth} or {@code targetHeight} is + * smaller than the original dimensions, and generally only when + * the {@code BILINEAR} hint is specified) + * @return a scaled version of the original {@code BufferedImage} + */ + public BufferedImage getScaledInstance(BufferedImage buf, + int targetWidth, + int targetHeight, + Object hint, + boolean higherQuality) + { + int type = (buf.getTransparency() == Transparency.OPAQUE) ? + BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB; + BufferedImage scalebuf = (BufferedImage)buf; + int w, h; + if (higherQuality) { + // Use multi-step technique: start with original size, then + // scale down in multiple passes with drawImage() + // until the target size is reached + w = buf.getWidth(); + h = buf.getHeight(); + } else { + // Use one-step technique: scale directly from original + // size to target size with a single drawImage() call + w = targetWidth; + h = targetHeight; + } + + do { + if (higherQuality && w > targetWidth) { + w /= 2; + if (w < targetWidth) { + w = targetWidth; + } + } + + if (higherQuality && h > targetHeight) { + h /= 2; + if (h < targetHeight) { + h = targetHeight; + } + } + + BufferedImage tmp = new BufferedImage(w, h, type); + Graphics2D g2d = tmp.createGraphics(); + g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint); + g2d.drawImage(scalebuf, 0, 0, w, h, Color.WHITE, null); + g2d.dispose(); + + scalebuf = tmp; + } while (w != targetWidth || h != targetHeight); + + return scalebuf; + } +} diff --git a/dspace-api/src/main/java/org/dspace/app/sfx/SFXFileReader.java b/dspace-api/src/main/java/org/dspace/app/sfx/SFXFileReader.java index 1b37a0954579ea2af301893edc97e623db963650..ae86947bfd96e63800dfb14a6ac472aa76b5b3ef 100644 --- a/dspace-api/src/main/java/org/dspace/app/sfx/SFXFileReader.java +++ b/dspace-api/src/main/java/org/dspace/app/sfx/SFXFileReader.java @@ -29,6 +29,20 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; +/** + * XML configuration file reader for DSpace metadata fields (DC) mapping + * to OpenURL parameters. + * <p> + * This class reads the [dspace]/config/sfx.xml configuration file, which + * contains pairs of DSpace item metadata values and OpenURL parameter names. + * Then it takes an item and constructs an OpenURL for it with values of + * parameters filled in from the paired metadata fields. + * </p> + * + * @author Stuart Lewis + * @author Graham Triggs + * @version $Revision$ + */ public class SFXFileReader { @@ -40,17 +54,17 @@ public class SFXFileReader { /** - * Loads the SFX configuraiton file + * Loads the SFX configuration file * * @param fileName The name of the SFX configuration file - * @param item The item to process + * @param item The item to process, from which metadata values will be taken * * @return the SFX string * @throws IOException */ public static String loadSFXFile(String fileName, Item item) throws IOException { - // Parse XML file -> XML document will be build + // Parse XML file -> XML document will be built if (doc == null) { doc = parseFile(fileName); @@ -62,7 +76,7 @@ public class SFXFileReader { /** Parses XML file and returns XML document. * @param fileName XML file to parse - * @return XML document or <B>null</B> if error occured + * @return XML document or <B>null</B> if error occured. The error is caught and logged. */ public static Document parseFile(String fileName) { @@ -94,10 +108,11 @@ public class SFXFileReader { } /** - * Process the item. + * Process the item, mapping each of its metadata fields defined in the + * configuration file to an OpenURL parameter * - * @param node - * @param item + * @param node DOM node of the mapping pair in the XML file (field element) + * @param item The item to process, from which metadata values will be taken * @return processed fields. * @throws IOException */ @@ -135,11 +150,12 @@ public class SFXFileReader { } /** - * Process the fields. + * Process the field nodes, mapping each metadata field defined in the + * configuration file to an OpenURL parameter * - * @param e - * @param item - * @return assembled query. + * @param e DOM node of the mapping pair in the XML file (field element) + * @param item The item to process, from which metadata values will be taken + * @return assembled OpenURL query. * @throws IOException */ private static String processFields(Node e, Item item) throws IOException diff --git a/dspace-api/src/main/java/org/dspace/app/sitemap/GenerateSitemaps.java b/dspace-api/src/main/java/org/dspace/app/sitemap/GenerateSitemaps.java index fbfd55ff2113db05cc6c6de0e30cb4afdceaf1c7..906574db43eeaba08ddcf24be6fe430a1afeb680 100644 --- a/dspace-api/src/main/java/org/dspace/app/sitemap/GenerateSitemaps.java +++ b/dspace-api/src/main/java/org/dspace/app/sitemap/GenerateSitemaps.java @@ -25,6 +25,7 @@ import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.apache.commons.cli.PosixParser; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.dspace.content.Collection; import org.dspace.content.Community; @@ -316,8 +317,8 @@ public class GenerateSitemaps throws MalformedURLException, UnsupportedEncodingException { // Set up HTTP proxy - if ((ConfigurationManager.getProperty("http.proxy.host") != null) - && (ConfigurationManager.getProperty("http.proxy.port") != null)) + if ((StringUtils.isNotBlank(ConfigurationManager.getProperty("http.proxy.host"))) + && (StringUtils.isNotBlank(ConfigurationManager.getProperty("http.proxy.port")))) { System.setProperty("proxySet", "true"); System.setProperty("proxyHost", ConfigurationManager diff --git a/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java b/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java index e8a3bd0df27e301b49be353229e9a5d0fdf7a9a8..6b4a6d6e47c712ee49e9a4ad19968437410cbea2 100644 --- a/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java +++ b/dspace-api/src/main/java/org/dspace/app/statistics/LogAnalyser.java @@ -7,6 +7,7 @@ */ package org.dspace.app.statistics; +import org.dspace.content.MetadataSchema; import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; import org.dspace.core.LogManager; @@ -18,17 +19,9 @@ import java.sql.SQLException; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Date; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.StringTokenizer; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -161,10 +154,10 @@ public class LogAnalyser private static Pattern logRegex = null; /** pattern to match commented out lines from the config file */ - private static Pattern comment = Pattern.compile("^#"); + private static final Pattern comment = Pattern.compile("^#"); /** pattern to match genuine lines from the config file */ - private static Pattern real = Pattern.compile("^(.+)=(.+)"); + private static final Pattern real = Pattern.compile("^(.+)=(.+)"); /** pattern to match all search types */ private static Pattern typeRX = null; @@ -1031,7 +1024,8 @@ public class LogAnalyser public static String unParseDate(Date date) { // Use SimpleDateFormat - SimpleDateFormat sdf = new SimpleDateFormat("yyyy'-'MM'-'dd"); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy'-'MM'-'dd'T'hh:mm:ss'Z'"); + sdf.setTimeZone(TimeZone.getTimeZone("UTC")); return sdf.format(date); } @@ -1172,8 +1166,12 @@ public class LogAnalyser "AND metadata_field_id = (" + " SELECT metadata_field_id " + " FROM metadatafieldregistry " + - " WHERE element = 'type' " + - " AND qualifier IS NULL) "; + " WHERE metadata_schema_id = (" + + " SELECT metadata_schema_id" + + " FROM MetadataSchemaRegistry" + + " WHERE short_id = '" + MetadataSchema.DC_SCHEMA + "')" + + " AND element = 'type' " + + " AND qualifier IS NULL) "; } // start the date constraint query buffer @@ -1191,8 +1189,12 @@ public class LogAnalyser "WHERE metadata_field_id = (" + " SELECT metadata_field_id " + " FROM metadatafieldregistry " + - " WHERE element = 'date' " + - " AND qualifier = 'accessioned') "); + " WHERE metadata_schema_id = (" + + " SELECT metadata_schema_id" + + " FROM MetadataSchemaRegistry" + + " WHERE short_id = '" + MetadataSchema.DC_SCHEMA + "')" + + " AND element = 'date' " + + " AND qualifier = 'accessioned') "); // Verifies that the metadata contains a valid date, otherwise the // postgres queries blow up when doing the ::timestamp cast. @@ -1205,28 +1207,33 @@ public class LogAnalyser if (oracle) { dateQuery.append(" AND TO_TIMESTAMP( TO_CHAR(text_value), "+ - "'yyyy-mm-dd\"T\"hh24:mi:ss\"Z\"' ) > TO_DATE('" + - unParseDate(startDate) + "', 'yyyy-MM-dd') "); + "'yyyy-mm-dd\"T\"hh24:mi:ss\"Z\"' ) >= TO_DATE('" + + unParseDate(startDate) + "', 'yyyy-MM-dd\"T\"hh24:mi:ss\"Z\"') "); } else { - dateQuery.append(" AND text_value::timestamp > '" + + dateQuery.append(" AND text_value::timestamp >= '" + unParseDate(startDate) + "'::timestamp "); } } if (endDate != null) { + // adjust end date to account for timestamp comparison + GregorianCalendar realEndDate = new GregorianCalendar(); + realEndDate.setTime(endDate); + realEndDate.add(Calendar.DAY_OF_MONTH, 1); + Date queryEndDate = realEndDate.getTime(); if (oracle) { dateQuery.append(" AND TO_TIMESTAMP( TO_CHAR(text_value), "+ "'yyyy-mm-dd\"T\"hh24:mi:ss\"Z\"' ) < TO_DATE('" + - unParseDate(endDate) + "', 'yyyy-MM-dd') "); + unParseDate(queryEndDate) + "', 'yyyy-MM-dd\"T\"hh24:mi:ss\"Z\"') "); } else { dateQuery.append(" AND text_value::timestamp < '" + - unParseDate(endDate) + "'::timestamp "); + unParseDate(queryEndDate) + "'::timestamp "); } } diff --git a/dspace-api/src/main/java/org/dspace/app/util/DSpaceContextListener.java b/dspace-api/src/main/java/org/dspace/app/util/DSpaceContextListener.java index 47f285058a3b1813dc583e141f9f74089c9c89d2..102af41e1a493e5d4253c191bff574d66fd10c9b 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DSpaceContextListener.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DSpaceContextListener.java @@ -23,22 +23,24 @@ import java.util.Enumeration; /** * Class to initialize / cleanup resources used by DSpace when the web application - * is started or stopped + * is started or stopped. */ public class DSpaceContextListener implements ServletContextListener { private static Logger log = Logger.getLogger(DSpaceContextListener.class); /** - * The DSpace config parameter, this is where the path to the DSpace - * configuration file can be obtained + * Name of the context parameter giving the path to the DSpace configuration file. */ public static final String DSPACE_CONFIG_PARAMETER = "dspace-config"; - + + private AbstractDSpaceWebapp webApp; + /** - * Initialize any resources required by the application + * Initialize any resources required by the application. * @param event */ + @Override public void contextInitialized(ServletContextEvent event) { @@ -114,6 +116,23 @@ public class DSpaceContextListener implements ServletContextListener "either the local servlet or global context.\n\n",e); } + /** + * Stage 3 + * + * Register that this application is running. + */ + + try { + Class webappClass = Class.forName("org.dspace.utils.DSpaceWebapp"); + webApp = (AbstractDSpaceWebapp) webappClass.newInstance(); + webApp.register(); + } catch (ClassNotFoundException ex) { + event.getServletContext().log("Can't create webapp MBean: " + ex.getMessage()); + } catch (InstantiationException ex) { + event.getServletContext().log("Can't create webapp MBean: " + ex.getMessage()); + } catch (IllegalAccessException ex) { + event.getServletContext().log("Can't create webapp MBean: " + ex.getMessage()); + } } /** @@ -121,8 +140,11 @@ public class DSpaceContextListener implements ServletContextListener * * @param event */ + @Override public void contextDestroyed(ServletContextEvent event) { + webApp.deregister(); + try { // Remove the database pool diff --git a/dspace-api/src/main/java/org/dspace/app/util/GoogleMetadata.java b/dspace-api/src/main/java/org/dspace/app/util/GoogleMetadata.java index 5559fd68bc2652d74d87dd5f8ac20b814f076373..691ba45b0e37e123ee251989100065fb7797e791 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/GoogleMetadata.java +++ b/dspace-api/src/main/java/org/dspace/app/util/GoogleMetadata.java @@ -8,6 +8,8 @@ package org.dspace.app.util; import java.sql.SQLException; + +import org.dspace.authorize.AuthorizeManager; import org.dspace.content.*; import java.io.IOException; @@ -1001,30 +1003,25 @@ public class GoogleMetadata private String getPDFSimpleUrl(Item item) { try { - Bundle[] contentBundles = item.getBundles("ORIGINAL"); - if (contentBundles.length > 0) { - Bitstream[] bitstreams = contentBundles[0].getBitstreams(); - if (bitstreams.length == 1) { - if (bitstreams[0].getFormat().getMIMEType().equals("application/pdf")) { - StringBuilder path = new StringBuilder(); - path.append(ConfigurationManager.getProperty("dspace.url")); - - if (item.getHandle() != null) { - path.append("/bitstream/"); - path.append(item.getHandle()); - path.append("/"); - path.append(bitstreams[0].getSequenceID()); - } else { - path.append("/retrieve/"); - path.append(bitstreams[0].getID()); - } - - path.append("/"); - path.append(Util.encodeBitstreamName(bitstreams[0].getName(), Constants.DEFAULT_ENCODING)); - return path.toString(); - } - } - } + Bitstream bitstream = findLinkableFulltext(item); + if (bitstream != null) { + StringBuilder path = new StringBuilder(); + path.append(ConfigurationManager.getProperty("dspace.url")); + + if (item.getHandle() != null) { + path.append("/bitstream/"); + path.append(item.getHandle()); + path.append("/"); + path.append(bitstream.getSequenceID()); + } else { + path.append("/retrieve/"); + path.append(bitstream.getID()); + } + + path.append("/"); + path.append(Util.encodeBitstreamName(bitstream.getName(), Constants.DEFAULT_ENCODING)); + return path.toString(); + } } catch (UnsupportedEncodingException ex) { log.debug(ex.getMessage()); } catch (SQLException ex) { @@ -1034,7 +1031,62 @@ public class GoogleMetadata return ""; } - /** + /** + * A bitstream is considered linkable fulltext when it is either + * <ul> + * <li>the item's only bitstream (in the ORIGINAL bundle); or</li> + * <li>the primary bitstream</li> + * </ul> + * Additionally, this bitstream must be publicly viewable. + * @param item + * @return + * @throws SQLException + */ + private Bitstream findLinkableFulltext(Item item) throws SQLException { + Bitstream bestSoFar = null; + int bitstreamCount = 0; + Bundle[] contentBundles = item.getBundles("ORIGINAL"); + for (Bundle bundle : contentBundles) { + int primaryBitstreamId = bundle.getPrimaryBitstreamID(); + Bitstream[] bitstreams = bundle.getBitstreams(); + for (Bitstream candidate : bitstreams) { + if (candidate.getID() == primaryBitstreamId) { // is primary -> use this one + if (isPublic(candidate)) { + return candidate; + } + } else if (bestSoFar == null) { + bestSoFar = candidate; + } + bitstreamCount++; + } + } + if (bitstreamCount > 1 || !isPublic(bestSoFar)) { + bestSoFar = null; + } + + return bestSoFar; + } + + private boolean isPublic(Bitstream bitstream) { + if (bitstream == null) { + return false; + } + boolean result = false; + Context context = null; + try { + context = new Context(); + result = AuthorizeManager.authorizeActionBoolean(context, bitstream, Constants.READ, true); + } catch (SQLException e) { + log.error("Cannot determine whether bitstream is public, assuming it isn't. bitstream_id=" + bitstream.getID(), e); + } finally { + if (context != null) { + context.abort(); + } + } + return result; + } + + /** * * * @param Field diff --git a/dspace-api/src/main/java/org/dspace/app/util/MetadataExposure.java b/dspace-api/src/main/java/org/dspace/app/util/MetadataExposure.java index abbe868b5d91c7e00aff18962ab6aeb8478dd602..9999a6556569960f793147e27a3e5ced184b9110 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/MetadataExposure.java +++ b/dspace-api/src/main/java/org/dspace/app/util/MetadataExposure.java @@ -64,6 +64,17 @@ public class MetadataExposure private static final String CONFIG_PREFIX = "metadata.hide."; + /** + * Returns whether the given metadata field should be exposed (visible). The metadata field is in the DSpace's DC notation: schema.element.qualifier + * + * @param context DSpace context + * @param schema metadata field schema (namespace), e.g. "dc" + * @param element metadata field element + * @param qualifier metadata field qualifier + * + * @return true (hidden) or false (exposed) + * @throws SQLException + */ public static boolean isHidden(Context context, String schema, String element, String qualifier) throws SQLException { @@ -98,12 +109,24 @@ public class MetadataExposure } } + /** + * Returns whether the maps from configuration have already been loaded + * into the hiddenElementSets property. + * + * @return true (initialized) or false (not initialized) + */ private static boolean isInitialized() { return hiddenElementSets != null; } - // load maps from configuration unless it's already done. + /** + * Loads maps from configuration unless it's already done. + * The configuration properties are a map starting with the + * "metadata.hide." prefix followed by schema, element and + * qualifier separated by dots and the value is true (hidden) + * or false (exposed). + */ private static synchronized void init() { if (!isInitialized()) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationManager.java b/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationManager.java index 47372e7cfba9018cd8b27ba8ea6af9b15e63d003..d95520cc97070a8ea9b7f6050632c0d944f0f077 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationManager.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/AuthenticationManager.java @@ -11,12 +11,16 @@ import javax.servlet.http.HttpServletRequest; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Date; import java.util.Iterator; import java.util.List; +import org.dspace.authorize.AuthorizeException; import org.dspace.core.Context; import org.dspace.core.PluginManager; import org.dspace.eperson.EPerson; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Access point for the stackable authentication methods. @@ -51,6 +55,9 @@ public class AuthenticationManager private static AuthenticationMethod methodStack[] = (AuthenticationMethod[])PluginManager.getPluginSequence("authentication", AuthenticationMethod.class); + /** SLF4J logging category */ + private static final Logger log = (Logger) LoggerFactory.getLogger(AuthenticationManager.class); + /** * Test credentials for authenticity. * Apply the given credentials to each authenticate() method in @@ -78,10 +85,10 @@ public class AuthenticationManager * SUCCESS, BAD_CREDENTIALS, CERT_REQUIRED, NO_SUCH_USER, BAD_ARGS * <p>Meaning: * <br>SUCCESS - authenticated OK. - * <br>BAD_CREDENTIALS - user exists, but credenitals (e.g. passwd) don't match + * <br>BAD_CREDENTIALS - user exists, but credentials (e.g. password) don't match * <br>CERT_REQUIRED - not allowed to login this way without X.509 cert. * <br>NO_SUCH_USER - user not found using this method. - * <br>BAD_ARGS - user/pw not appropriate for this method + * <br>BAD_ARGS - user/password not appropriate for this method */ public static int authenticate(Context context, String username, @@ -119,10 +126,10 @@ public class AuthenticationManager * SUCCESS, BAD_CREDENTIALS, CERT_REQUIRED, NO_SUCH_USER, BAD_ARGS * <p>Meaning: * <br>SUCCESS - authenticated OK. - * <br>BAD_CREDENTIALS - user exists, but credenitals (e.g. passwd) don't match + * <br>BAD_CREDENTIALS - user exists, but credentials (e.g. password) don't match * <br>CERT_REQUIRED - not allowed to login this way without X.509 cert. * <br>NO_SUCH_USER - user not found using this method. - * <br>BAD_ARGS - user/pw not appropriate for this method + * <br>BAD_ARGS - user/password not appropriate for this method */ public static int authenticateImplicit(Context context, String username, @@ -160,6 +167,18 @@ public class AuthenticationManager } if (ret == AuthenticationMethod.SUCCESS) { + EPerson me = context.getCurrentUser(); + me.setLastActive(new Date()); + try + { + me.update(); + } catch (SQLException ex) + { + log.error("Could not update last-active stamp", ex); + } catch (AuthorizeException ex) + { + log.error("Could not update last-active stamp", ex); + } return ret; } if (ret < bestRet) diff --git a/dspace-api/src/main/java/org/dspace/authenticate/IPMatcher.java b/dspace-api/src/main/java/org/dspace/authenticate/IPMatcher.java index 7df36fc0f28f2b096bddb5a92aeac14711a36178..854eb3979872b74c8b992148a68231347f218aeb 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/IPMatcher.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/IPMatcher.java @@ -7,6 +7,8 @@ */ package org.dspace.authenticate; +import org.apache.log4j.Logger; + import java.net.Inet6Address; import java.net.UnknownHostException; @@ -30,9 +32,13 @@ import java.net.UnknownHostException; * * @version $Revision$ * @author Robert Tansley + * @author Ben Bosman + * @author Roeland Dillen */ public class IPMatcher { + private static Logger log = Logger.getLogger(IPMatcher.class); + /** Network to match */ private byte[] network; @@ -139,13 +145,26 @@ public class IPMatcher netmask[1] = (byte) ((fullMask & 0x00FF0000) >>> 16); netmask[2] = (byte) ((fullMask & 0x0000FF00) >>> 8); netmask[3] = (byte) (fullMask & 0x000000FF); + ipToBytes(ipPart, network, mustHave4); + if (log.isDebugEnabled()) { + log.debug("fullMask: "+fullMask); + for (int i = 0; i < network.length; i++) { + log.debug("network[" + i + "]: "+network[i]); + } + for (int i = 0; i < netmask.length; i++) { + log.debug("netmask[" + i + "]: "+netmask[i]); + } + } } else { - // full subnet specified + // full netmask specified + ipToBytes(parts[0],network,true); ipToBytes(parts[1], netmask, true); } + break; + case 1: // Get IP for (int i = 0; i < netmask.length; i++) @@ -166,6 +185,14 @@ public class IPMatcher } network = ip4ToIp6(network); netmask = ip4MaskToIp6(netmask); + if (log.isDebugEnabled()) { + for (int i = 0; i < network.length; i++) { + log.debug("network[" + i + "]: "+network[i]); + } + for (int i = 0; i < netmask.length; i++) { + log.debug("netmask[" + i + "]: "+netmask[i]); + } + } } } @@ -236,6 +263,7 @@ public class IPMatcher */ public boolean match(String ipIn) throws IPMatcherException { + log.debug("ipIn: "+ipIn); byte[] candidate; if (ipIn.indexOf(':') < 0) @@ -258,6 +286,13 @@ public class IPMatcher { if ((candidate[i] & netmask[i]) != (network[i] & netmask[i])) { + if (log.isDebugEnabled()) { + log.debug("candidate[i]: "+candidate[i]); + log.debug("netmask[i]: "+netmask[i]); + log.debug("candidate[i] & netmask[i]: "+(candidate[i] & netmask[i])); + log.debug("network[i]: "+network[i]); + log.debug("network[i] & netmask[i]: "+(network[i] & netmask[i])); + } return false; } } diff --git a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java index 43e305452c26264ee441bac07ed607a7b9ada648..492dad166a3d2d137d4a141984161dd62306a855 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/LDAPAuthentication.java @@ -228,7 +228,7 @@ public class LDAPAuthentication context.setCurrentUser(eperson); // assign user to groups based on ldap dn - assignGroupsBasedOnLdapDn(dn, context); + assignGroups(dn, ldap.ldapGroup, context); log.info(LogManager .getHeader(context, "authenticate", "type=ldap")); @@ -252,13 +252,18 @@ public class LDAPAuthentication // If there is no email and the email domain is set, add it to the netid String email = ldap.ldapEmail; - if (((email == null) || ("".equals(email))) && - (!"".equals(ConfigurationManager.getProperty("authentication-ldap", "netid_email_domain")))) + + if ((StringUtils.isEmpty(email)) && + (StringUtils.isNotEmpty(ConfigurationManager.getProperty("authentication-ldap", "netid_email_domain")))) { email = netid + ConfigurationManager.getProperty("authentication-ldap", "netid_email_domain"); } + else + { + email = netid; + } - if ((email != null) && (!"".equals(email))) + if (StringUtils.isNotEmpty(email)) { try { @@ -275,7 +280,7 @@ public class LDAPAuthentication context.setCurrentUser(eperson); // assign user to groups based on ldap dn - assignGroupsBasedOnLdapDn(dn, context); + assignGroups(dn, ldap.ldapGroup, context); return SUCCESS; } @@ -288,19 +293,19 @@ public class LDAPAuthentication { context.setIgnoreAuthorization(true); eperson = EPerson.create(context); - if ((email != null) && (!"".equals(email))) + if (StringUtils.isNotEmpty(email)) { eperson.setEmail(email); } - if ((ldap.ldapGivenName!=null) && (!ldap.ldapGivenName.equals(""))) + if (StringUtils.isNotEmpty(ldap.ldapGivenName)) { eperson.setFirstName(ldap.ldapGivenName); } - if ((ldap.ldapSurname!=null) && (!ldap.ldapSurname.equals(""))) + if (StringUtils.isNotEmpty(ldap.ldapSurname)) { eperson.setLastName(ldap.ldapSurname); } - if ((ldap.ldapPhone!=null)&&(!ldap.ldapPhone.equals(""))) + if (StringUtils.isNotEmpty(ldap.ldapPhone)) { eperson.setMetadata("phone", ldap.ldapPhone); } @@ -312,7 +317,7 @@ public class LDAPAuthentication context.setCurrentUser(eperson); // assign user to groups based on ldap dn - assignGroupsBasedOnLdapDn(dn, context); + assignGroups(dn, ldap.ldapGroup, context); } catch (AuthorizeException e) { @@ -362,6 +367,7 @@ public class LDAPAuthentication protected String ldapGivenName = null; protected String ldapSurname = null; protected String ldapPhone = null; + protected String ldapGroup = null; /** LDAP settings */ String ldap_provider_url = ConfigurationManager.getProperty("authentication-ldap", "provider_url"); @@ -373,6 +379,7 @@ public class LDAPAuthentication String ldap_givenname_field = ConfigurationManager.getProperty("authentication-ldap", "givenname_field"); String ldap_surname_field = ConfigurationManager.getProperty("authentication-ldap", "surname_field"); String ldap_phone_field = ConfigurationManager.getProperty("authentication-ldap", "phone_field"); + String ldap_group_field = ConfigurationManager.getProperty("authentication-ldap", "login.groupmap.attribute"); SpeakerToLDAP(Logger thelog) { @@ -408,7 +415,7 @@ public class LDAPAuthentication if ((adminUser != null) && (!adminUser.trim().equals("")) && (adminPassword != null) && (!adminPassword.trim().equals(""))) { - // Use admin credencials for search// Authenticate + // Use admin credentials for search// Authenticate env.put(javax.naming.Context.SECURITY_AUTHENTICATION, "simple"); env.put(javax.naming.Context.SECURITY_PRINCIPAL, adminUser); env.put(javax.naming.Context.SECURITY_CREDENTIALS, adminPassword); @@ -448,7 +455,7 @@ public class LDAPAuthentication } String attlist[] = {ldap_email_field, ldap_givenname_field, - ldap_surname_field, ldap_phone_field}; + ldap_surname_field, ldap_phone_field, ldap_group_field}; Attributes atts = sr.getAttributes(); Attribute att; @@ -483,6 +490,14 @@ public class LDAPAuthentication ldapPhone = (String) att.get(); } } + + if (attlist[4] != null) { + att = atts.get(attlist[4]); + if (att != null) + { + ldapGroup = (String) att.get(); + } + } if (answer.hasMoreElements()) { // Oh dear - more than one match @@ -614,20 +629,29 @@ public class LDAPAuthentication * Add authenticated users to the group defined in dspace.cfg by * the authentication-ldap.login.groupmap.* key. */ - private void assignGroupsBasedOnLdapDn(String dn, Context context) + private void assignGroups(String dn, String group, Context context) { if (StringUtils.isNotBlank(dn)) { System.out.println("dn:" + dn); int i = 1; String groupMap = ConfigurationManager.getProperty("authentication-ldap", "login.groupmap." + i); + + boolean cmp; + while (groupMap != null) { String t[] = groupMap.split(":"); String ldapSearchString = t[0]; String dspaceGroupName = t[1]; + + if (group == null) { + cmp = StringUtils.containsIgnoreCase(dn, ldapSearchString + ","); + } else { + cmp = StringUtils.equalsIgnoreCase(group, ldapSearchString); + } - if (StringUtils.containsIgnoreCase(dn, ldapSearchString)) + if (cmp) { // assign user to this group try diff --git a/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java b/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java index 569265cf31f20b15f107ba033083b1d037f2c2e6..e027f0f32d4faa364550cceb949c77ee4ef121ea 100644 --- a/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java +++ b/dspace-api/src/main/java/org/dspace/authenticate/ShibAuthentication.java @@ -29,6 +29,7 @@ import java.util.Set; import javax.servlet.http.HttpServletResponse; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeException; @@ -186,9 +187,11 @@ public class ShibAuthentication implements AuthenticationMethod log.debug("Starting Shibboleth Authentication"); String message = "Received the following headers:\n"; + @SuppressWarnings("unchecked") Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); + @SuppressWarnings("unchecked") Enumeration<String> headerValues = request.getHeaders(headerName); while (headerValues.hasMoreElements()) { String headerValue = headerValues.nextElement(); @@ -301,7 +304,7 @@ public class ShibAuthentication implements AuthenticationMethod } // Get the Shib supplied affiliation or use the default affiliation - List<String> affiliations = findMultipleHeaders(request, roleHeader); + List<String> affiliations = findMultipleAttributes(request, roleHeader); if (affiliations == null) { if (defaultRoles != null) affiliations = Arrays.asList(defaultRoles.split(",")); @@ -336,7 +339,7 @@ public class ShibAuthentication implements AuthenticationMethod } if (groupNames == null) { - log.debug("Unable to find role mapping for the value, '"+affiliation+"', there should be a mapping in the dspace.cfg: authentication.shib.role."+affiliation+" = <some group name>"); + log.debug("Unable to find role mapping for the value, '"+affiliation+"', there should be a mapping in config/modules/authentication-shibboleth.cfg: role."+affiliation+" = <some group name>"); continue; } else { log.debug("Mapping role affiliation to DSpace group: '"+groupNames+"'"); @@ -482,7 +485,7 @@ public class ShibAuthentication implements AuthenticationMethod // Shibboleth authentication initiator if (shibURL == null || shibURL.length() == 0) shibURL = "/Shibboleth.sso/Login"; - shibURL.trim(); + shibURL = shibURL.trim(); // Determine the return URL, where shib will send the user after authenticating. We need it to go back // to DSpace's shibboleth-login url so the we will extract the user's information and locally @@ -577,7 +580,7 @@ public class ShibAuthentication implements AuthenticationMethod // 1) First, look for a netid header. if (netidHeader != null) { - String netid = findSingleHeader(request,netidHeader); + String netid = findSingleAttribute(request,netidHeader); if (netid != null) { foundNetID = true; @@ -592,7 +595,7 @@ public class ShibAuthentication implements AuthenticationMethod // 2) Second, look for an email header. if (eperson == null && emailHeader != null) { - String email = findSingleHeader(request,emailHeader); + String email = findSingleAttribute(request,emailHeader); if (email != null) { foundEmail = true; @@ -618,7 +621,7 @@ public class ShibAuthentication implements AuthenticationMethod if (email != null) { foundRemoteUser = true; - email.toLowerCase(); + email = email.toLowerCase(); eperson = EPerson.findByEmail(context, email); if (eperson == null) @@ -670,12 +673,12 @@ public class ShibAuthentication implements AuthenticationMethod String lnameHeader = ConfigurationManager.getProperty("authentication-shibboleth","lastname-header"); // Header values - String netid = findSingleHeader(request,netidHeader); - String email = findSingleHeader(request,emailHeader); - String fname = findSingleHeader(request,fnameHeader); - String lname = findSingleHeader(request,lnameHeader); + String netid = findSingleAttribute(request,netidHeader); + String email = findSingleAttribute(request,emailHeader); + String fname = findSingleAttribute(request,fnameHeader); + String lname = findSingleAttribute(request,lnameHeader); - if ( email == null || fname == null || lname == null) { + if ( email == null || (fnameHeader != null && fname == null) || (lnameHeader != null && lname == null)) { // We require that there be an email, first name, and last name. If we // don't have at least these three pieces of information then we fail. String message = "Unable to register new eperson because we are unable to find an email address along with first and last name for the user.\n"; @@ -689,11 +692,11 @@ public class ShibAuthentication implements AuthenticationMethod } // Truncate values of parameters that are too big. - if (fname.length() > NAME_MAX_SIZE) { + if (fname != null && fname.length() > NAME_MAX_SIZE) { log.warn("Truncating eperson's first name because it is longer than "+NAME_MAX_SIZE+": '"+fname+"'"); fname = fname.substring(0,NAME_MAX_SIZE); } - if (lname.length() > NAME_MAX_SIZE) { + if (lname != null && lname.length() > NAME_MAX_SIZE) { log.warn("Truncating eperson's last name because it is longer than "+NAME_MAX_SIZE+": '"+lname+"'"); lname = lname.substring(0,NAME_MAX_SIZE); } @@ -706,8 +709,10 @@ public class ShibAuthentication implements AuthenticationMethod if (netid != null) eperson.setNetid(netid); eperson.setEmail(email.toLowerCase()); - eperson.setFirstName(fname); - eperson.setLastName(lname); + if ( fname != null ) + eperson.setFirstName(fname); + if ( lname != null ) + eperson.setLastName(lname); eperson.setCanLogIn(true); // Commit the new eperson @@ -756,17 +761,17 @@ public class ShibAuthentication implements AuthenticationMethod String fnameHeader = ConfigurationManager.getProperty("authentication-shibboleth","firstname-header"); String lnameHeader = ConfigurationManager.getProperty("authentication-shibboleth","lastname-header"); - String netid = findSingleHeader(request,netidHeader); - String email = findSingleHeader(request,emailHeader); - String fname = findSingleHeader(request,fnameHeader); - String lname = findSingleHeader(request,lnameHeader); + String netid = findSingleAttribute(request,netidHeader); + String email = findSingleAttribute(request,emailHeader); + String fname = findSingleAttribute(request,fnameHeader); + String lname = findSingleAttribute(request,lnameHeader); // Truncate values of parameters that are too big. - if (fname.length() > NAME_MAX_SIZE) { + if (fname != null && fname.length() > NAME_MAX_SIZE) { log.warn("Truncating eperson's first name because it is longer than "+NAME_MAX_SIZE+": '"+fname+"'"); fname = fname.substring(0,NAME_MAX_SIZE); } - if (lname.length() > NAME_MAX_SIZE) { + if (lname != null && lname.length() > NAME_MAX_SIZE) { log.warn("Truncating eperson's last name because it is longer than "+NAME_MAX_SIZE+": '"+lname+"'"); lname = lname.substring(0,NAME_MAX_SIZE); } @@ -799,7 +804,7 @@ public class ShibAuthentication implements AuthenticationMethod for (String header : metadataHeaderMap.keySet()) { String field = metadataHeaderMap.get(header); - String value = findSingleHeader(request, header); + String value = findSingleAttribute(request, header); // Truncate values if (value == null) { @@ -1067,15 +1072,27 @@ public class ShibAuthentication implements AuthenticationMethod * This method will not interpret the header value in any way. * * - * @param request The HTTP request to look for headers values on. - * @param name The name of the header - * @return The value of the header requested, or null if none found. + * @param request The HTTP request to look for values in. + * @param name The name of the attribute or header + * @return The value of the attribute or header requested, or null if none found. */ - private String findHeader(HttpServletRequest request, String name) { - String value = request.getHeader(name); - if (value == null) + private String findAttribute(HttpServletRequest request, String name) { + if ( name == null ) { + return null; + } + // First try to get the value from the attribute + String value = (String) request.getAttribute(name); + if (StringUtils.isEmpty(value)) + value = (String) request.getAttribute(name.toLowerCase()); + if (StringUtils.isEmpty(value)) + value = (String) request.getAttribute(name.toUpperCase()); + + // Second try to get the value from the header + if (StringUtils.isEmpty(value)) + value = request.getHeader(name); + if (StringUtils.isEmpty(value)) value = request.getHeader(name.toLowerCase()); - if (value == null) + if (StringUtils.isEmpty(value)) value = request.getHeader(name.toUpperCase()); return value; @@ -1089,7 +1106,7 @@ public class ShibAuthentication implements AuthenticationMethod * * Shibboleth attributes may contain multiple values separated by a * semicolon. This method will return the first value in the attribute. If - * you need multiple values use findMultipleHeaders instead. + * you need multiple values use findMultipleAttributes instead. * * If no attribute is found then null is returned. * @@ -1097,9 +1114,12 @@ public class ShibAuthentication implements AuthenticationMethod * @param name The name of the header * @return The value of the header requested, or null if none found. */ - private String findSingleHeader(HttpServletRequest request, String name) { + private String findSingleAttribute(HttpServletRequest request, String name) { + if ( name == null) { + return null; + } - String value = findHeader(request, name); + String value = findAttribute(request, name); if (value != null) { @@ -1125,8 +1145,8 @@ public class ShibAuthentication implements AuthenticationMethod } /** - * Find a particular Shibboleth header value and return the all values. - * The header name uses a bit of fuzzy logic, so it will first try case + * Find a particular Shibboleth hattributeeader value and return the values. + * The attribute name uses a bit of fuzzy logic, so it will first try case * sensitive, then it will try lowercase, and finally it will try uppercase. * * Shibboleth attributes may contain multiple values separated by a @@ -1136,11 +1156,11 @@ public class ShibAuthentication implements AuthenticationMethod * If no attributes are found then null is returned. * * @param request The HTTP request to look for headers values on. - * @param name The name of the header + * @param name The name of the attribute * @return The list of values found, or null if none found. */ - private List<String> findMultipleHeaders(HttpServletRequest request, String name) { - String values = findHeader(request, name); + private List<String> findMultipleAttributes(HttpServletRequest request, String name) { + String values = findAttribute(request, name); if (values == null) return null; @@ -1158,7 +1178,7 @@ public class ShibAuthentication implements AuthenticationMethod // prevent an endless loop in an error condition. values = values.substring(1,values.length()); - } else if (idx > 0 && values.charAt(idx-1) != '\\' ) { + } else if (idx > 0 && values.charAt(idx-1) == '\\' ) { // The attribute starts with an escaped semicolon idx++; } else if ( idx > 0) { diff --git a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeManager.java b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeManager.java index 91ba46b06f45b327cbe1c45b2fc5767b0ecfd7d9..2dc8e69cf0f97e39ee785a24a117972d71b6ca0d 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/AuthorizeManager.java +++ b/dspace-api/src/main/java/org/dspace/authorize/AuthorizeManager.java @@ -965,7 +965,7 @@ public class AuthorizeManager * @param o * object * @param actionID - * ID of action frm <code>org.dspace.core.Constants</code> + * ID of action from <code>org.dspace.core.Constants</code> * @return array of <code>Group</code>s that can perform the specified * action on the specified object * @throws java.sql.SQLException @@ -1030,11 +1030,41 @@ public class AuthorizeManager } + /** + * Is a policy with the specified parameters already in place? + * + * @param c + * current context + * @param o + * object + * @param actionID + * ID of action from <code>org.dspace.core.Constants</code> + * @param policyID + * ID of an existing policy. If -1 is specified, this parameter will be ignored + * @return true if such a policy exists, false otherwise + * @throws java.sql.SQLException + * if there's a database problem + */ public static boolean isAnIdenticalPolicyAlreadyInPlace(Context c, DSpaceObject o, int groupID, int action, int policyID) throws SQLException { return isAnIdenticalPolicyAlreadyInPlace(c, o.getType(), o.getID(), groupID, action, policyID); } + /** + * Is a policy with the specified parameters already in place? + * + * @param c + * current context + * @param o + * ID of an object + * @param action + * ID of action from <code>org.dspace.core.Constants</code> + * @param policyID + * ID of an existing policy. If -1 is specified, this parameter will be ignored + * @return true if such a policy exists, false otherwise + * @throws java.sql.SQLException + * if there's a database problem + */ public static boolean isAnIdenticalPolicyAlreadyInPlace(Context c, int dsoType, int dsoID, int groupID, int action, int policyID) throws SQLException { diff --git a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java index 3ae3a0473c5ce60625cf96f238cf78af5b850d88..ce6a80835f53fb0f0d71312dff177cf805ffc206 100644 --- a/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java +++ b/dspace-api/src/main/java/org/dspace/authorize/ResourcePolicy.java @@ -196,7 +196,7 @@ public class ResourcePolicy } /** - * Get the e-person's internal identifier + * Get the ResourcePolicy's internal identifier * * @return the internal identifier */ diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseDAOFactory.java b/dspace-api/src/main/java/org/dspace/browse/BrowseDAOFactory.java index d8385dc7190e909e1734445a922e1fa99c2f8363..9521bd5de4544b7c4b310a80690701134b277775 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseDAOFactory.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseDAOFactory.java @@ -32,20 +32,8 @@ public class BrowseDAOFactory String className = ConfigurationManager.getProperty("browseDAO.class"); if (className == null) { - // For compatibility with previous versions - String db = ConfigurationManager.getProperty("db.name"); - if ("postgres".equals(db)) - { - return new BrowseDAOPostgres(context); - } - else if ("oracle".equals(db)) - { - return new BrowseDAOOracle(context); - } - else - { - throw new BrowseException("The configuration for db.name is either invalid, or contains an unrecognised database"); - } + // SOLR implementation is the default since DSpace 4.0 + return new SolrBrowseDAO(context); } try { @@ -73,20 +61,8 @@ public class BrowseDAOFactory String className = ConfigurationManager.getProperty("browseCreateDAO.class"); if (className == null) { - // For compatibility with previous versions - String db = ConfigurationManager.getProperty("db.name"); - if ("postgres".equals(db)) - { - return new BrowseCreateDAOPostgres(context); - } - else if ("oracle".equals(db)) - { - return new BrowseCreateDAOOracle(context); - } - else - { - throw new BrowseException("The configuration for db.name is either invalid, or contains an unrecognised database"); - } + // SOLR implementation is the default since DSpace 4.0 + return new SolrBrowseCreateDAO(context); } try { diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseDAOOracle.java b/dspace-api/src/main/java/org/dspace/browse/BrowseDAOOracle.java index 5de2a39ca2283295c768e9bf85e3709fa6106f90..4cfd5a9ee09dc360ae52408c8ecdd609178cd13c 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseDAOOracle.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseDAOOracle.java @@ -116,6 +116,7 @@ public class BrowseDAOOracle implements BrowseDAO /** flags for what the items represent */ private boolean itemsInArchive = true; private boolean itemsWithdrawn = false; + private boolean itemsDiscoverable = true; private boolean enableBrowseFrequencies = true; @@ -360,7 +361,8 @@ public class BrowseDAOOracle implements BrowseDAO TableRow row = tri.next(); BrowseItem browseItem = new BrowseItem(context, row.getIntColumn("item_id"), itemsInArchive, - itemsWithdrawn); + itemsWithdrawn, + itemsDiscoverable); results.add(browseItem); } @@ -682,11 +684,19 @@ public class BrowseDAOOracle implements BrowseDAO { itemsInArchive = false; itemsWithdrawn = true; + itemsDiscoverable = true; } - else + else if (table.equals(BrowseIndex.getPrivateBrowseIndex().getTableName())) + { + itemsInArchive = true; + itemsWithdrawn = false; + itemsDiscoverable = false; + } + else { itemsInArchive = true; itemsWithdrawn = false; + itemsDiscoverable = true; } this.rebuildQuery = true; diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseDAOPostgres.java b/dspace-api/src/main/java/org/dspace/browse/BrowseDAOPostgres.java index 092d791b590ae99eb40fc98cf0f2ba93e38cac5d..75a5ff2306ec40b90fefd7237a3d1380f326edaf 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseDAOPostgres.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseDAOPostgres.java @@ -116,6 +116,7 @@ public class BrowseDAOPostgres implements BrowseDAO /** flags for what the items represent */ private boolean itemsInArchive = true; private boolean itemsWithdrawn = false; + private boolean itemsDiscoverable = true; private boolean enableBrowseFrequencies = true; @@ -367,7 +368,8 @@ public class BrowseDAOPostgres implements BrowseDAO TableRow row = tri.next(); BrowseItem browseItem = new BrowseItem(context, row.getIntColumn("item_id"), itemsInArchive, - itemsWithdrawn); + itemsWithdrawn, + itemsDiscoverable); results.add(browseItem); } @@ -687,13 +689,22 @@ public class BrowseDAOPostgres implements BrowseDAO { itemsInArchive = false; itemsWithdrawn = true; + itemsDiscoverable = true; } - else + else if (table.equals(BrowseIndex.getPrivateBrowseIndex().getTableName())) + { + itemsInArchive = true; + itemsWithdrawn = false; + itemsDiscoverable = false; + } + else { itemsInArchive = true; itemsWithdrawn = false; + itemsDiscoverable = true; } + this.rebuildQuery = true; } diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseIndex.java b/dspace-api/src/main/java/org/dspace/browse/BrowseIndex.java index e0ca079ea6be826c4276b24869758c38dd17395f..1a6b5e850ff570aca63c112ecf499ef8ec4cffe8 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseIndex.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseIndex.java @@ -680,12 +680,10 @@ public final class BrowseIndex while ( ((definition = ConfigurationManager.getProperty("webui.browse.index." + idx))) != null) { BrowseIndex bi = new BrowseIndex(definition, idx); - - //Load the frequency configuration - String freqDefinition = ConfigurationManager.getProperty("webui.browse.metadata.show-freq." + idx); - if (freqDefinition!=null) - bi.displayFrequencies = Boolean.valueOf(freqDefinition); - + bi.displayFrequencies = Boolean.valueOf(ConfigurationManager + .getBooleanProperty("webui.browse.metadata.show-freq." + + idx, true)); + browseIndices.add(bi); idx++; } diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseItem.java b/dspace-api/src/main/java/org/dspace/browse/BrowseItem.java index 2f125f5dbcc83284181e87e7cdefea4ad97e9788..72043b830ab5994c5163e2b43eaf5f198cdea98c 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseItem.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseItem.java @@ -55,6 +55,9 @@ public class BrowseItem extends DSpaceObject /** is the item withdrawn */ private boolean withdrawn = false; + /** is the item discoverable */ + private boolean discoverable = true; + /** item handle */ private String handle = null; @@ -66,12 +69,13 @@ public class BrowseItem extends DSpaceObject * @param in_archive * @param withdrawn */ - public BrowseItem(Context context, int id, boolean in_archive, boolean withdrawn) + public BrowseItem(Context context, int id, boolean in_archive, boolean withdrawn, boolean discoverable) { this.context = context; this.id = id; this.in_archive = in_archive; this.withdrawn = withdrawn; + this.discoverable = discoverable; } /** @@ -404,4 +408,8 @@ public class BrowseItem extends DSpaceObject { return withdrawn; } + + public boolean isDiscoverable() { + return discoverable; + } } diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseItemDAOOracle.java b/dspace-api/src/main/java/org/dspace/browse/BrowseItemDAOOracle.java index fe19b00e9a28ed14f0fc3e941e21268c12c1d832..bd2e84038c03fa42cc1c430cd997d4f2ea8c3d30 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseItemDAOOracle.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseItemDAOOracle.java @@ -21,7 +21,7 @@ import java.util.List; public class BrowseItemDAOOracle implements BrowseItemDAO { /** query to obtain all the items from the database */ - 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, discoverable FROM item WHERE in_archive = 1 OR withdrawn = 1"; /** query to get the text value of a metadata element only (qualifier is NULL) */ private String getByMetadataElement = "SELECT authority, confidence, text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " + @@ -75,7 +75,8 @@ public class BrowseItemDAOOracle implements BrowseItemDAO TableRow row = tri.next(); items.add(new BrowseItem(context, row.getIntColumn("item_id"), row.getBooleanColumn("in_archive"), - row.getBooleanColumn("withdrawn"))); + row.getBooleanColumn("withdrawn"), + row.getBooleanColumn("discoverable"))); } } finally diff --git a/dspace-api/src/main/java/org/dspace/browse/BrowseItemDAOPostgres.java b/dspace-api/src/main/java/org/dspace/browse/BrowseItemDAOPostgres.java index 1d68438e15b1e920af62034bf3fbabdc56188784..851cd47cfb9dfd11db04d839d935b71cf793dd33 100644 --- a/dspace-api/src/main/java/org/dspace/browse/BrowseItemDAOPostgres.java +++ b/dspace-api/src/main/java/org/dspace/browse/BrowseItemDAOPostgres.java @@ -21,7 +21,7 @@ import java.util.List; public class BrowseItemDAOPostgres implements BrowseItemDAO { /** query to obtain all the items from the database */ - 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, discoverable FROM item WHERE in_archive = true OR withdrawn = true"; /** query to get the text value of a metadata element only (qualifier is NULL) */ private String getByMetadataElement = "SELECT authority, confidence, text_value,text_lang,element,qualifier FROM metadatavalue, metadatafieldregistry, metadataschemaregistry " + @@ -74,7 +74,8 @@ public class BrowseItemDAOPostgres implements BrowseItemDAO TableRow row = tri.next(); items.add(new BrowseItem(context, row.getIntColumn("item_id"), row.getBooleanColumn("in_archive"), - row.getBooleanColumn("withdrawn"))); + row.getBooleanColumn("withdrawn"), + row.getBooleanColumn("discoverable"))); } } finally diff --git a/dspace-api/src/main/java/org/dspace/browse/IndexBrowse.java b/dspace-api/src/main/java/org/dspace/browse/IndexBrowse.java index d14df1eca42fb3e6e25002e40fc26e6b83317b96..dcf1fae6ba5725c6cf7f16ffb746c564f6c4e609 100644 --- a/dspace-api/src/main/java/org/dspace/browse/IndexBrowse.java +++ b/dspace-api/src/main/java/org/dspace/browse/IndexBrowse.java @@ -344,7 +344,7 @@ public class IndexBrowse { boolean reqCommunityMappings = false; Map<Integer, String> sortMap = getSortValues(item, itemMDMap); - if (item.isArchived() && !item.isWithdrawn()) + if (item.isArchived() && item.isDiscoverable()) { // Try to update an existing record in the item index if (!dao.updateIndex(BrowseIndex.getItemBrowseIndex().getTableName(), item.getID(), sortMap)) @@ -358,30 +358,23 @@ public class IndexBrowse reqCommunityMappings = true; } - else if (item.isWithdrawn()) + else if (!item.isDiscoverable()) { - // Private items are marked as withdrawn as well. check before if they are private... - Item dsoItem = Item.find(context, item.getID()); - if (!dsoItem.isDiscoverable()){ - if (!dao.updateIndex(BrowseIndex.getPrivateBrowseIndex().getTableName(), item.getID(), sortMap)) { - dao.deleteByItemID(BrowseIndex.getItemBrowseIndex().getTableName(), item.getID()); - dao.insertIndex(BrowseIndex.getPrivateBrowseIndex().getTableName(), item.getID(), sortMap); - } + if (!dao.updateIndex(BrowseIndex.getPrivateBrowseIndex().getTableName(), item.getID(), sortMap)) { + dao.deleteByItemID(BrowseIndex.getItemBrowseIndex().getTableName(), item.getID()); + dao.insertIndex(BrowseIndex.getPrivateBrowseIndex().getTableName(), item.getID(), sortMap); } - else{ - // Try to update an existing record in the withdrawn index - if (!dao.updateIndex(BrowseIndex.getWithdrawnBrowseIndex().getTableName(), item.getID(), sortMap)) - { - // Record doesn't exist - ensure that it doesn't exist in the item index, - // and add it to the withdrawn item index - dao.deleteByItemID(BrowseIndex.getItemBrowseIndex().getTableName(), item.getID()); - dao.insertIndex(BrowseIndex.getWithdrawnBrowseIndex().getTableName(), item.getID(), sortMap); - } + } + else if (item.isWithdrawn()) + { + // Try to update an existing record in the withdrawn index + if (!dao.updateIndex(BrowseIndex.getWithdrawnBrowseIndex().getTableName(), item.getID(), sortMap)) + { + // Record doesn't exist - ensure that it doesn't exist in the item index, + // and add it to the withdrawn item index + dao.deleteByItemID(BrowseIndex.getItemBrowseIndex().getTableName(), item.getID()); + dao.insertIndex(BrowseIndex.getWithdrawnBrowseIndex().getTableName(), item.getID(), sortMap); } - - - - } else { @@ -1273,5 +1266,21 @@ public class IndexBrowse return browseItem.isWithdrawn(); } + + /** + * Is the Item discoverable? + * @return + */ + public boolean isDiscoverable() + { + if (item != null) + { + return item.isDiscoverable(); + } + + return browseItem.isDiscoverable(); + } + + } } diff --git a/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOFactory.java b/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOFactory.java index 0667c3022a4fcb169fe999b0e3a689e04d253d43..20131bbd393b4e48cb96cd71c2765245af6da4f8 100644 --- a/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOFactory.java +++ b/dspace-api/src/main/java/org/dspace/browse/ItemCountDAOFactory.java @@ -15,36 +15,46 @@ import org.dspace.core.ConfigurationManager; * item count information * * @author Richard Jones + * @author Ivan Masár * */ public class ItemCountDAOFactory { - /** - * Get an instance of ItemCountDAO which supports the correct database - * for the specific DSpace instance. - * - * @param context - * @throws ItemCountException - */ - public static ItemCountDAO getInstance(Context context) - throws ItemCountException - { - String db = ConfigurationManager.getProperty("db.name"); - ItemCountDAO dao; - if ("postgres".equals(db)) - { - dao = new ItemCountDAOPostgres(); - } - else if ("oracle".equals(db)) - { - dao = new ItemCountDAOOracle(); - } - else - { - throw new ItemCountException("Database type: " + db + " is not currently supported"); - } - - dao.setContext(context); - return dao; - } + /** + * Get an instance of ItemCountDAO which supports the correct storage backend + * for the specific DSpace instance. + * + * @param context + * @throws ItemCountException + */ + public static ItemCountDAO getInstance(Context context) + throws ItemCountException + { + + /** Log4j logger */ + ItemCountDAO dao = null; + + String className = ConfigurationManager.getProperty("ItemCountDAO.class"); + + // SOLR implementation is the default since DSpace 4.0 + if (className == null) + { + dao = new ItemCountDAOSolr(); + } + else + { + try + { + dao = (ItemCountDAO) Class + .forName(className.trim()).newInstance(); + } + catch (Exception e) + { + throw new ItemCountException("The configuration for ItemCountDAO is invalid: " + className, e); + } + } + + dao.setContext(context); + return dao; + } } diff --git a/dspace-api/src/main/java/org/dspace/browse/ItemCounter.java b/dspace-api/src/main/java/org/dspace/browse/ItemCounter.java index 48a284b27de3a5452dfce6953849c49ad0c3bf49..62410f6adb666da5af23d39bfa8f766fd2f05c0e 100644 --- a/dspace-api/src/main/java/org/dspace/browse/ItemCounter.java +++ b/dspace-api/src/main/java/org/dspace/browse/ItemCounter.java @@ -110,7 +110,8 @@ public class ItemCounter public int getCount(DSpaceObject dso) throws ItemCountException { - boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache"); + boolean useCache = ConfigurationManager.getBooleanProperty( + "webui.strengths.cache", true); if (useCache) { diff --git a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseCreateDAO.java b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseCreateDAO.java index 538d75431bd2c0ab13f6c458913eea8c7a674ba4..ff316d5f64d27a2520a2a4e6bf49f60747866aee 100644 --- a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseCreateDAO.java +++ b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseCreateDAO.java @@ -372,6 +372,9 @@ public class SolrBrowseCreateDAO implements BrowseCreateDAO, public void insertIndex(String table, int itemID, Map sortCols) throws BrowseException { + // this is required to be sure that communities2item will be cleaned + // after the switch to SOLRBrowseDAOs. See DS-1619 + dbCreateDAO.deleteCommunityMappings(itemID); } @Override diff --git a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java index 6cdf9410b74549c45a5c2bbbe14a1a6db450f051..000a1dd3e2658e8d3108c3a883f7fe7db688ba78 100644 --- a/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java +++ b/dspace-api/src/main/java/org/dspace/browse/SolrBrowseDAO.java @@ -133,7 +133,7 @@ public class SolrBrowseDAO implements BrowseDAO private DiscoverResult sResponse = null; private boolean itemsWithdrawn = false; - private boolean itemsPrivate = false; + private boolean itemsDiscoverable = true; private boolean showFrequencies; @@ -186,7 +186,8 @@ public class SolrBrowseDAO implements BrowseDAO } try { - sResponse = searcher.search(context, query, itemsWithdrawn); + sResponse = searcher.search(context, query, itemsWithdrawn + || !itemsDiscoverable); } catch (SearchServiceException e) { @@ -201,18 +202,10 @@ public class SolrBrowseDAO implements BrowseDAO if (itemsWithdrawn) { query.addFilterQueries("withdrawn:true"); - if (itemsPrivate) - { - query.addFilterQueries("discoverable:false"); - } - else - { - query.addFilterQueries("NOT(discoverable:false)"); - } } - else + else if (!itemsDiscoverable) { - query.addFilterQueries("NOT(withdrawn:true)"); + query.addFilterQueries("discoverable:false"); } } @@ -301,7 +294,7 @@ public class SolrBrowseDAO implements BrowseDAO // processing the query... Item item = (Item) solrDoc; BrowseItem bitem = new BrowseItem(context, item.getID(), - item.isArchived(), item.isWithdrawn()); + item.isArchived(), item.isWithdrawn(), item.isDiscoverable()); bitems.add(bitem); } return bitems; @@ -681,13 +674,10 @@ public class SolrBrowseDAO implements BrowseDAO if (table.equals(BrowseIndex.getWithdrawnBrowseIndex().getTableName())) { itemsWithdrawn = true; - itemsPrivate = false; } else if (table.equals(BrowseIndex.getPrivateBrowseIndex().getTableName())) { - itemsPrivate = true; - // items private are also withdrawn - itemsWithdrawn = true; + itemsDiscoverable = false; } facetField = table; } diff --git a/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java b/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java index 6d5b7475539fc0faaa617a2756252925d0e7985a..65cea024ea58d4a2f7333abbc337cf5a2d5ff93a 100644 --- a/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java +++ b/dspace-api/src/main/java/org/dspace/checker/DailyReportEmailer.java @@ -12,21 +12,7 @@ import java.io.FileWriter; import java.io.IOException; import java.util.Date; import java.util.GregorianCalendar; -import java.util.Properties; - -import javax.activation.DataHandler; -import javax.activation.DataSource; -import javax.activation.FileDataSource; -import javax.mail.BodyPart; -import javax.mail.Message; import javax.mail.MessagingException; -import javax.mail.Multipart; -import javax.mail.Session; -import javax.mail.Transport; -import javax.mail.internet.InternetAddress; -import javax.mail.internet.MimeBodyPart; -import javax.mail.internet.MimeMessage; -import javax.mail.internet.MimeMultipart; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLineParser; @@ -79,12 +65,16 @@ public class DailyReportEmailer public void sendReport(File attachment, int numberOfBitstreams) throws IOException, javax.mail.MessagingException { - Email email = new Email(); - email.setSubject("Checksum checker Report - " + numberOfBitstreams + " Bitstreams found with POSSIBLE issues"); - email.setContent("report is attached ..."); - email.addAttachment(attachment, "checksum_checker_report.txt"); - email.addRecipient(ConfigurationManager.getProperty("mail.admin")); - email.send(); + if(numberOfBitstreams > 0) + { + String hostname = ConfigurationManager.getProperty("dspace.hostname"); + Email email = new Email(); + email.setSubject("Checksum checker Report - " + numberOfBitstreams + " Bitstreams found with POSSIBLE issues on " + hostname); + email.setContent("report is attached ..."); + email.addAttachment(attachment, "checksum_checker_report.txt"); + email.addRecipient(ConfigurationManager.getProperty("mail.admin")); + email.send(); + } } /** diff --git a/dspace-api/src/main/java/org/dspace/content/Bitstream.java b/dspace-api/src/main/java/org/dspace/content/Bitstream.java index d7465facf758aee6aef899d5a725932b10b20a71..7c8a6749b7f914c3b295e2391f89fe3bbe21d17c 100644 --- a/dspace-api/src/main/java/org/dspace/content/Bitstream.java +++ b/dspace-api/src/main/java/org/dspace/content/Bitstream.java @@ -667,7 +667,9 @@ public class Bitstream extends DSpaceObject } /** - * Determine if this bitstream is registered + * Determine if this bitstream is registered (available elsewhere on + * filesystem than in assetstore). More about registered items: + * https://wiki.duraspace.org/display/DSDOC3x/Registering+(not+Importing)+Bitstreams+via+Simple+Archive+Format * * @return true if the bitstream is registered, false otherwise */ diff --git a/dspace-api/src/main/java/org/dspace/content/Collection.java b/dspace-api/src/main/java/org/dspace/content/Collection.java index f9c350ccf4f3eb3f42d10679c356e9ed6e4134e4..06ed1386ddaff9a1e15a5036944a326d08bd857f 100644 --- a/dspace-api/src/main/java/org/dspace/content/Collection.java +++ b/dspace-api/src/main/java/org/dspace/content/Collection.java @@ -7,16 +7,6 @@ */ package org.dspace.content; -import java.io.IOException; -import java.io.InputStream; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.MissingResourceException; - import org.apache.log4j.Logger; import org.dspace.app.util.AuthorizeUtil; import org.dspace.authorize.AuthorizeConfiguration; @@ -25,13 +15,9 @@ import org.dspace.authorize.AuthorizeManager; import org.dspace.authorize.ResourcePolicy; import org.dspace.browse.BrowseException; import org.dspace.browse.IndexBrowse; -import org.dspace.browse.ItemCounter; import org.dspace.browse.ItemCountException; -import org.dspace.core.ConfigurationManager; -import org.dspace.core.Constants; -import org.dspace.core.Context; -import org.dspace.core.I18nUtil; -import org.dspace.core.LogManager; +import org.dspace.browse.ItemCounter; +import org.dspace.core.*; import org.dspace.eperson.Group; import org.dspace.event.Event; import org.dspace.handle.HandleManager; @@ -42,6 +28,16 @@ import org.dspace.workflow.WorkflowItem; import org.dspace.xmlworkflow.storedcomponents.CollectionRole; import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; +import java.io.IOException; +import java.io.InputStream; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.MissingResourceException; + /** * Class representing a collection. * <P> @@ -52,7 +48,7 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; * database after calling <code>update</code>. The default group of * submitters is slightly different - creating or removing this has instant * effect. - * + * * @author Robert Tansley * @version $Revision$ */ @@ -94,9 +90,16 @@ public class Collection extends DSpaceObject /** The default group of administrators */ private Group admins; + // Keys for accessing Collection metadata + public static final String COPYRIGHT_TEXT = "copyright_text"; + public static final String INTRODUCTORY_TEXT = "introductory_text"; + public static final String SHORT_DESCRIPTION = "short_description"; + public static final String SIDEBAR_TEXT = "side_bar_text"; + public static final String PROVENANCE_TEXT = "provenance_description"; + /** * Construct a collection with the given table row - * + * * @param context * the context this object exists in * @param row @@ -139,7 +142,7 @@ public class Collection extends DSpaceObject submitters = groupFromColumn("submitter"); admins = groupFromColumn("admin"); - + // Get our Handle if any handle = HandleManager.findHandle(context, this); @@ -153,12 +156,12 @@ public class Collection extends DSpaceObject /** * Get a collection from the database. Loads in the metadata - * + * * @param context * DSpace context object * @param id * ID of the collection - * + * * @return the collection, or null if the ID is invalid. * @throws SQLException */ @@ -199,10 +202,10 @@ public class Collection extends DSpaceObject /** * Create a new collection, with a new ID. This method is not public, and * does not check authorisation. - * + * * @param context * DSpace context object - * + * * @return the newly created collection * @throws SQLException * @throws AuthorizeException @@ -288,10 +291,10 @@ public class Collection extends DSpaceObject /** * Get all collections in the system. These are alphabetically sorted by * collection name. - * + * * @param context * DSpace context object - * + * * @return the collections in the system * @throws SQLException */ @@ -337,9 +340,59 @@ public class Collection extends DSpaceObject return collectionArray; } + /** + * Get all collections in the system. Adds support for limit and offset. + * @param context + * @param limit + * @param offset + * @return + * @throws SQLException + */ + public static Collection[] findAll(Context context, Integer limit, Integer offset) throws SQLException + { + TableRowIterator tri = DatabaseManager.queryTable(context, "collection", + "SELECT * FROM collection ORDER BY name limit ? offset ?", limit, offset); + + List<Collection> collections = new ArrayList<Collection>(); + + try + { + while (tri.hasNext()) + { + TableRow row = tri.next(); + + // First check the cache + Collection fromCache = (Collection) context.fromCache( + Collection.class, row.getIntColumn("collection_id")); + + if (fromCache != null) + { + collections.add(fromCache); + } + else + { + collections.add(new Collection(context, row)); + } + } + } + finally + { + // close the TableRowIterator to free up resources + if (tri != null) + { + tri.close(); + } + } + + Collection[] collectionArray = new Collection[collections.size()]; + collectionArray = (Collection[]) collections.toArray(collectionArray); + + return collectionArray; + } + /** * Get the in_archive items in this collection. The order is indeterminate. - * + * * @return an iterator over the items in the collection. * @throws SQLException */ @@ -356,9 +409,30 @@ public class Collection extends DSpaceObject return new ItemIterator(ourContext, rows); } + /** + * Get the in_archive items in this collection. The order is indeterminate. + * Provides the ability to use limit and offset, for efficient paging. + * @param limit Max number of results in set + * @param offset Number of results to jump ahead by. 100 = 100th result is first, not 100th page. + * @return an iterator over the items in the collection. + * @throws SQLException + */ + public ItemIterator getItems(Integer limit, Integer offset) throws SQLException + { + String myQuery = "SELECT item.* FROM item, collection2item WHERE " + + "item.item_id=collection2item.item_id AND " + + "collection2item.collection_id= ? " + + "AND item.in_archive='1' limit ? offset ?"; + + TableRowIterator rows = DatabaseManager.queryTable(ourContext, "item", + myQuery,getID(), limit, offset); + + return new ItemIterator(ourContext, rows); + } + /** * Get all the items in this collection. The order is indeterminate. - * + * * @return an iterator over the items in the collection. * @throws SQLException */ @@ -376,7 +450,7 @@ public class Collection extends DSpaceObject /** * Get the internal ID of this collection - * + * * @return the internal identifier */ public int getID() @@ -402,36 +476,36 @@ public class Collection extends DSpaceObject /** * Get the value of a metadata field - * + * * @param field * the name of the metadata field to get - * + * * @return the value of the metadata field - * + * * @exception IllegalArgumentException * if the requested metadata field doesn't exist */ public String getMetadata(String field) { String metadata = collectionRow.getStringColumn(field); - return (metadata == null) ? "" : metadata; + return (metadata == null) ? "" : metadata; } /** * Set a metadata value - * + * * @param field * the name of the metadata field to get * @param value * value to set the field to - * + * * @exception IllegalArgumentException * if the requested metadata field doesn't exist * @exception MissingResourceException */ public void setMetadata(String field, String value) throws MissingResourceException { - if ((field.trim()).equals("name") + if ((field.trim()).equals("name") && (value == null || value.trim().equals(""))) { try @@ -443,9 +517,9 @@ public class Collection extends DSpaceObject value = "Untitled"; } } - - /* - * Set metadata field to null if null + + /* + * Set metadata field to null if null * and trim strings to eliminate excess * whitespace. */ @@ -457,7 +531,7 @@ public class Collection extends DSpaceObject { collectionRow.setColumn(field, value.trim()); } - + modifiedMetadata = true; addDetails(field); } @@ -470,7 +544,7 @@ public class Collection extends DSpaceObject /** * Get the logo for the collection. <code>null</code> is returned if the * collection does not have a logo. - * + * * @return the logo of the collection, or <code>null</code> */ public Bitstream getLogo() @@ -546,10 +620,10 @@ public class Collection extends DSpaceObject * Note that while the new group is created in the database, the association * between the group and the collection is not written until * <code>update</code> is called. - * + * * @param step * the step (1-3) of the workflow to create or get the group for - * + * * @return the workflow group associated with this collection * @throws SQLException * @throws AuthorizeException @@ -581,7 +655,7 @@ public class Collection extends DSpaceObject * Set the workflow group corresponding to a particular workflow step. * <code>null</code> can be passed in if there should be no associated * group for that workflow step; any existing group is NOT deleted. - * + * * @param step * the workflow step (1-3) * @param g @@ -606,10 +680,10 @@ public class Collection extends DSpaceObject * Get the the workflow group corresponding to a particular workflow step. * This returns <code>null</code> if there is no group associated with * this collection for the given step. - * + * * @param step * the workflow step (1-3) - * + * * @return the group of reviewers or <code>null</code> */ public Group getWorkflowGroup(int step) @@ -622,7 +696,7 @@ public class Collection extends DSpaceObject * either the newly created group or the previously existing one. Note that * other groups may also be allowed to submit to this collection by the * authorization system. - * + * * @return the default group of submitters associated with this collection * @throws SQLException * @throws AuthorizeException @@ -645,7 +719,7 @@ public class Collection extends DSpaceObject // register this as the submitter group collectionRow.setColumn("submitter", submitters.getID()); - + AuthorizeManager.addPolicy(ourContext, this, Constants.ADD, submitters); modified = true; @@ -653,9 +727,9 @@ public class Collection extends DSpaceObject } /** - * Remove the submitters group, if no group has already been created - * then return without error. This will merely dereference the current - * submitters group from the collection so that it may be deleted + * Remove the submitters group, if no group has already been created + * then return without error. This will merely dereference the current + * submitters group from the collection so that it may be deleted * without violating database constraints. */ public void removeSubmitters() throws SQLException, AuthorizeException @@ -672,11 +746,11 @@ public class Collection extends DSpaceObject // Remove the link to the collection table. collectionRow.setColumnNull("submitter"); submitters = null; - + modified = true; } - + /** * Get the default group of submitters, if there is one. Note that the * authorization system may allow others to submit to the collection, so @@ -684,7 +758,7 @@ public class Collection extends DSpaceObject * <P> * The default group of submitters for collection 100 is the one called * <code>collection_100_submit</code>. - * + * * @return the default group of submitters, or <code>null</code> if there * is no default group. */ @@ -697,7 +771,7 @@ public class Collection extends DSpaceObject * Create a default administrators group if one does not already exist. * Returns either the newly created group or the previously existing one. * Note that other groups may also be administrators. - * + * * @return the default group of editors associated with this collection * @throws SQLException * @throws AuthorizeException @@ -713,7 +787,7 @@ public class Collection extends DSpaceObject ourContext.turnOffAuthorisationSystem(); admins = Group.create(ourContext); ourContext.restoreAuthSystemState(); - + admins.setName("COLLECTION_" + getID() + "_ADMIN"); admins.update(); } @@ -723,15 +797,15 @@ public class Collection extends DSpaceObject // register this as the admin group collectionRow.setColumn("admin", admins.getID()); - + modified = true; return admins; } - + /** - * Remove the administrators group, if no group has already been created - * then return without error. This will merely dereference the current - * administrators group from the collection so that it may be deleted + * Remove the administrators group, if no group has already been created + * then return without error. This will merely dereference the current + * administrators group from the collection so that it may be deleted * without violating database constraints. */ public void removeAdministrators() throws SQLException, AuthorizeException @@ -748,7 +822,7 @@ public class Collection extends DSpaceObject // Remove the link to the collection table. collectionRow.setColumnNull("admin"); admins = null; - + modified = true; } @@ -759,7 +833,7 @@ public class Collection extends DSpaceObject * <P> * The default group of administrators for collection 100 is the one called * <code>collection_100_admin</code>. - * + * * @return group of administrators, or <code>null</code> if there is no * default group. */ @@ -772,7 +846,7 @@ public class Collection extends DSpaceObject * Get the license that users must grant before submitting to this * collection. If the collection does not have a specific license, the * site-wide default is returned. - * + * * @return the license for this collection */ public String getLicense() @@ -782,7 +856,7 @@ public class Collection extends DSpaceObject if (license == null || license.trim().equals("")) { // Fallback to site-wide default - license = ConfigurationManager.getDefaultSubmissionLicense(); + license = LicenseManager.getDefaultSubmissionLicense(); } return license; @@ -790,8 +864,8 @@ public class Collection extends DSpaceObject /** * Get the license that users must grant before submitting to this - * collection. - * + * collection. + * * @return the license for this collection */ public String getLicenseCollection() @@ -801,7 +875,7 @@ public class Collection extends DSpaceObject /** * Find out if the collection has a custom license - * + * * @return <code>true</code> if the collection has a custom license */ public boolean hasCustomLicense() @@ -814,7 +888,7 @@ public class Collection extends DSpaceObject /** * Set the license for this collection. Passing in <code>null</code> means * that the site-wide default will be used. - * + * * @param license * the license, or <code>null</code> */ @@ -828,7 +902,7 @@ public class Collection extends DSpaceObject * returned if the collection does not have a template. Submission * mechanisms may copy this template to provide a convenient starting point * for a submission. - * + * * @return the item template, or <code>null</code> */ public Item getTemplateItem() throws SQLException @@ -841,7 +915,7 @@ public class Collection extends DSpaceObject * no action is taken. Caution: Make sure you call <code>update</code> on * the collection after doing this, or the item will have been created but * the collection record will not refer to it. - * + * * @throws SQLException * @throws AuthorizeException */ @@ -868,7 +942,7 @@ public class Collection extends DSpaceObject * record in the database, the collection record will be changed, including * any other changes made; in other words, this method does an * <code>update</code>. - * + * * @throws SQLException * @throws AuthorizeException * @throws IOException @@ -881,7 +955,7 @@ public class Collection extends DSpaceObject collectionRow.setColumnNull("template_item_id"); DatabaseManager.update(ourContext, collectionRow); - + if (template != null) { log.info(LogManager.getHeader(ourContext, "remove_template_item", @@ -894,7 +968,7 @@ public class Collection extends DSpaceObject ourContext.restoreAuthSystemState(); template = null; } - + ourContext.addEvent(new Event(Event.MODIFY, Constants.COLLECTION, getID(), "remove_template_item")); } @@ -903,7 +977,7 @@ public class Collection extends DSpaceObject * the item and the collection - it does nothing like set an issue date, * remove a personal workspace item etc. This has instant effect; * <code>update</code> need not be called. - * + * * @param item * item to add * @throws SQLException @@ -930,7 +1004,7 @@ public class Collection extends DSpaceObject /** * Remove an item. If the item is then orphaned, it is deleted. - * + * * @param item * item to remove * @throws SQLException @@ -956,20 +1030,20 @@ public class Collection extends DSpaceObject } log.info(LogManager.getHeader(ourContext, "remove_item", "collection_id=" + getID() + ",item_id=" + item.getID())); - + DatabaseManager.updateQuery(ourContext, "DELETE FROM collection2item WHERE collection_id= ? "+ "AND item_id= ? ", getID(), item.getID()); DatabaseManager.setConstraintImmediate(ourContext, "coll2item_item_fk"); - + ourContext.addEvent(new Event(Event.REMOVE, Constants.COLLECTION, getID(), Constants.ITEM, item.getID(), item.getHandle())); } /** * Update the collection metadata (including logo and workflow groups) to * the database. Inserts if this is a new collection. - * + * * @throws SQLException * @throws IOException * @throws AuthorizeException @@ -996,7 +1070,7 @@ public class Collection extends DSpaceObject clearDetails(); } } - + public boolean canEditBoolean() throws java.sql.SQLException { return canEditBoolean(true); @@ -1020,7 +1094,7 @@ public class Collection extends DSpaceObject { canEdit(true); } - + public void canEdit(boolean useInheritance) throws AuthorizeException, SQLException { Community[] parents = getCommunities(); @@ -1047,7 +1121,7 @@ public class Collection extends DSpaceObject * Delete the collection, including the metadata and logo. Items that are * then orphans are deleted. Groups associated with this collection * (workflow participants and submitters) are NOT deleted. - * + * * @throws SQLException * @throws AuthorizeException * @throws IOException @@ -1064,12 +1138,12 @@ public class Collection extends DSpaceObject // remove subscriptions - hmm, should this be in Subscription.java? DatabaseManager.updateQuery(ourContext, - "DELETE FROM subscription WHERE collection_id= ? ", + "DELETE FROM subscription WHERE collection_id= ? ", getID()); // Remove Template Item removeTemplateItem(); - + // Remove items ItemIterator items = getAllItems(); @@ -1079,7 +1153,7 @@ public class Collection extends DSpaceObject { Item item = items.next(); IndexBrowse ib = new IndexBrowse(ourContext); - + if (item.isOwningCollection(this)) { // the collection to be deleted is the owning collection, thus remove @@ -1092,12 +1166,12 @@ public class Collection extends DSpaceObject // Browse.itemRemoved(ourContext, itemId); collections[i].removeItem(item); } - - } + + } // the item was only mapped to this collection, so just remove it else { - //notify Browse of removing item mapping. + //notify Browse of removing item mapping. ib.indexItem(item); // Browse.itemChanged(ourContext, item); removeItem(item); @@ -1226,7 +1300,7 @@ public class Collection extends DSpaceObject /** * Get the communities this collection appears in - * + * * @return array of <code>Community</code> objects * @throws SQLException */ @@ -1282,10 +1356,10 @@ public class Collection extends DSpaceObject /** * Return <code>true</code> if <code>other</code> is the same Collection * as this object, <code>false</code> otherwise - * + * * @param other * object to compare to - * + * * @return <code>true</code> if object passed in represents the same * collection as this object */ @@ -1321,7 +1395,7 @@ public class Collection extends DSpaceObject /** * Utility method for reading in a group from a group ID in a column. If the * column is null, null is returned. - * + * * @param col * the column name to read * @return the group referred to by that column, or null @@ -1339,7 +1413,7 @@ public class Collection extends DSpaceObject /** * return type found in Constants - * + * * @return int Constants.COLLECTION */ public int getType() @@ -1351,13 +1425,13 @@ public class Collection extends DSpaceObject * return an array of collections that user has a given permission on * (useful for trimming 'select to collection' list) or figuring out which * collections a person is an editor for. - * + * * @param context * @param comm * (optional) restrict search to a community, else null * @param actionID * of the action - * + * * @return Collection [] of collections with matching permissions * @throws SQLException */ @@ -1437,7 +1511,7 @@ public class Collection extends DSpaceObject return itemcount; } - + public DSpaceObject getAdminObject(int action) throws SQLException { DSpaceObject adminObject = null; @@ -1473,7 +1547,7 @@ public class Collection extends DSpaceObject } return adminObject; } - + @Override public DSpaceObject getParentObject() throws SQLException { diff --git a/dspace-api/src/main/java/org/dspace/content/Community.java b/dspace-api/src/main/java/org/dspace/content/Community.java index 3c377f2b6ef4697fa18efea589453007bc0d3a76..ed632e7e7f3748e0272df770f0ae84a99fb739bd 100644 --- a/dspace-api/src/main/java/org/dspace/content/Community.java +++ b/dspace-api/src/main/java/org/dspace/content/Community.java @@ -7,13 +7,6 @@ */ package org.dspace.content; -import java.io.IOException; -import java.io.InputStream; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.MissingResourceException; - import org.apache.commons.lang.builder.HashCodeBuilder; import org.apache.log4j.Logger; import org.dspace.app.util.AuthorizeUtil; @@ -21,8 +14,8 @@ import org.dspace.authorize.AuthorizeConfiguration; import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeManager; import org.dspace.authorize.ResourcePolicy; -import org.dspace.browse.ItemCounter; import org.dspace.browse.ItemCountException; +import org.dspace.browse.ItemCounter; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.I18nUtil; @@ -34,6 +27,13 @@ import org.dspace.storage.rdbms.DatabaseManager; import org.dspace.storage.rdbms.TableRow; import org.dspace.storage.rdbms.TableRowIterator; +import java.io.IOException; +import java.io.InputStream; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; +import java.util.MissingResourceException; + /** * Class representing a community * <P> @@ -70,6 +70,12 @@ public class Community extends DSpaceObject /** The default group of administrators */ private Group admins; + // Keys for accessing Community metadata + public static final String COPYRIGHT_TEXT = "copyright_text"; + public static final String INTRODUCTORY_TEXT = "introductory_text"; + public static final String SHORT_DESCRIPTION = "short_description"; + public static final String SIDEBAR_TEXT = "side_bar_text"; + /** * Construct a community object from a database row. * @@ -793,6 +799,48 @@ public class Community extends DSpaceObject return communityArray; } + /** + * Return an array of collections of this community and its subcommunities + * + * @return an array of collections + */ + + public Collection[] getAllCollections() throws SQLException + { + List<Collection> collectionList = new ArrayList<Collection>(); + for (Community subcommunity : getSubcommunities()) + { + addCollectionList(subcommunity, collectionList); + } + + for (Collection collection : getCollections()) + { + collectionList.add(collection); + } + + // Put them in an array + Collection[] collectionArray = new Collection[collectionList.size()]; + collectionArray = (Collection[]) collectionList.toArray(collectionArray); + + return collectionArray; + + } + /** + * Internal method to process subcommunities recursively + */ + private void addCollectionList(Community community, List<Collection> collectionList) throws SQLException + { + for (Community subcommunity : community.getSubcommunities()) + { + addCollectionList(subcommunity, collectionList); + } + + for (Collection collection : community.getCollections()) + { + collectionList.add(collection); + } + } + /** * Create a new collection within this community. The collection is created * without any workflow groups or default submitter group. diff --git a/dspace-api/src/main/java/org/dspace/content/DCValue.java b/dspace-api/src/main/java/org/dspace/content/DCValue.java index 57c3cad49285f717804dc23197d6a7028b1f5ea4..dd529874aa04dc687e9a259be8719955c683c869 100644 --- a/dspace-api/src/main/java/org/dspace/content/DCValue.java +++ b/dspace-api/src/main/java/org/dspace/content/DCValue.java @@ -40,4 +40,12 @@ public class DCValue /** Authority control confidence */ public int confidence = Choices.CF_UNSET; + + /** + * Get the field in dot notation. i.e. schema.element.qualifier, as in dc.date.issued + * @return + */ + public String getField() { + return schema + "." + element + (qualifier==null?"":("." + qualifier)); + } } diff --git a/dspace-api/src/main/java/org/dspace/content/InstallItem.java b/dspace-api/src/main/java/org/dspace/content/InstallItem.java index 44adf66cdfeb26154f2f4d9158adcb88ded47400..12dab09d79fa6bae33139978d2760cd00b2e3a80 100644 --- a/dspace-api/src/main/java/org/dspace/content/InstallItem.java +++ b/dspace-api/src/main/java/org/dspace/content/InstallItem.java @@ -69,14 +69,12 @@ public class InstallItem identifierService.register(c, item, suppliedHandle); } } catch (IdentifierException e) { - throw new RuntimeException("Can't create an Identifier!"); + throw new RuntimeException("Can't create an Identifier!", e); } - populateMetadata(c, item); return finishItem(c, item, is); - } /** @@ -115,28 +113,38 @@ public class InstallItem } // Even though we are restoring an item it may not have the proper dates. So let's - // double check that it has a date accessioned and date issued, and if either of those dates - // are not set then set them to today. + // double check its associated date(s) DCDate now = DCDate.getCurrent(); - // If the item doesn't have a date.accessioned, create one. + // If the item doesn't have a date.accessioned, set it to today DCValue[] dateAccessioned = item.getDC("date", "accessioned", Item.ANY); if (dateAccessioned.length == 0) { item.addDC("date", "accessioned", null, now.toString()); } - // create issue date if not present + // If issue date is set as "today" (literal string), then set it to current date + // In the below loop, we temporarily clear all issued dates and re-add, one-by-one, + // replacing "today" with today's date. + // NOTE: As of DSpace 4.0, DSpace no longer sets an issue date by default DCValue[] currentDateIssued = item.getDC("date", "issued", Item.ANY); - if (currentDateIssued.length == 0) + item.clearDC("date", "issued", Item.ANY); + for (DCValue dcv : currentDateIssued) { - DCDate issued = new DCDate(now.getYear(),now.getMonth(),now.getDay(),-1,-1,-1); - item.addDC("date", "issued", null, issued.toString()); + if(dcv.value!=null && dcv.value.equalsIgnoreCase("today")) + { + DCDate issued = new DCDate(now.getYear(),now.getMonth(),now.getDay(),-1,-1,-1); + item.addDC(dcv.element, dcv.qualifier, dcv.language, issued.toString()); + } + else if(dcv.value!=null) + { + item.addDC(dcv.element, dcv.qualifier, dcv.language, dcv.value); + } } // Record that the item was restored - String provDescription = "Restored into DSpace on "+ now + " (GMT)."; - item.addDC("description", "provenance", "en", provDescription); + String provDescription = "Restored into DSpace on "+ now + " (GMT)."; + item.addDC("description", "provenance", "en", provDescription); return finishItem(c, item, is); } @@ -158,23 +166,39 @@ public class InstallItem item.addDC("date", "available", null, now.toString()); } - // create issue date if not present + // If issue date is set as "today" (literal string), then set it to current date + // In the below loop, we temporarily clear all issued dates and re-add, one-by-one, + // replacing "today" with today's date. + // NOTE: As of DSpace 4.0, DSpace no longer sets an issue date by default DCValue[] currentDateIssued = item.getDC("date", "issued", Item.ANY); - - if (currentDateIssued.length == 0) + item.clearDC("date", "issued", Item.ANY); + for (DCValue dcv : currentDateIssued) { - DCDate issued = new DCDate(now.getYear(),now.getMonth(),now.getDay(),-1,-1,-1); - item.addDC("date", "issued", null, issued.toString()); + if(dcv.value!=null && dcv.value.equalsIgnoreCase("today")) + { + DCDate issued = new DCDate(now.getYear(),now.getMonth(),now.getDay(),-1,-1,-1); + item.addDC(dcv.element, dcv.qualifier, dcv.language, issued.toString()); + } + else if(dcv.value!=null) + { + item.addDC(dcv.element, dcv.qualifier, dcv.language, dcv.value); + } } String provDescription = "Made available in DSpace on " + now + " (GMT). " + getBitstreamProvenanceMessage(item); + // If an issue date was passed in and it wasn't set to "today" (literal string) + // then note this previous issue date in provenance message if (currentDateIssued.length != 0) { - DCDate d = new DCDate(currentDateIssued[0].value); - provDescription = provDescription + " Previous issue date: " - + d.toString(); + String previousDateIssued = currentDateIssued[0].value; + if(previousDateIssued!=null && !previousDateIssued.equalsIgnoreCase("today")) + { + DCDate d = new DCDate(previousDateIssued); + provDescription = provDescription + " Previous issue date: " + + d.toString(); + } } // Add provenance description @@ -192,14 +216,9 @@ public class InstallItem // set owning collection item.setOwningCollection(is.getCollection()); - // set in_archive=true only if the user didn't specify that it is a private item - if(item.isDiscoverable()){ - item.setArchived(true); - } - else{ // private item is withdrawn as well - item.withdraw(); - } - + // set in_archive=true + item.setArchived(true); + // save changes ;-) item.update(); diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/METSDisseminationCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/METSDisseminationCrosswalk.java index 528742b4af5fb67e0255722e33fdb7359cf8dd94..74e649e2cbe802dc483083388d831e9a4c4068fc 100644 --- a/dspace-api/src/main/java/org/dspace/content/crosswalk/METSDisseminationCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/METSDisseminationCrosswalk.java @@ -114,7 +114,9 @@ public class METSDisseminationCrosswalk pparams.put("manifestOnly", "true"); // Create a temporary file to disseminate into - String tempDirectory = ConfigurationManager.getProperty("upload.temp.dir"); + String tempDirectory = (ConfigurationManager.getProperty("upload.temp.dir") != null) + ? ConfigurationManager.getProperty("upload.temp.dir") : System.getProperty("java.io.tmpdir"); + File tempFile = File.createTempFile("METSDissemination" + dso.hashCode(), null, new File(tempDirectory)); tempFile.deleteOnExit(); diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/METSRightsCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/METSRightsCrosswalk.java index 150fffc46f93e8637bb2355193b2b179affa63fb..fa1cba00b199bcabe23108ee6882849f6fe4d436 100644 --- a/dspace-api/src/main/java/org/dspace/content/crosswalk/METSRightsCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/METSRightsCrosswalk.java @@ -9,11 +9,15 @@ package org.dspace.content.crosswalk; import java.io.IOException; import java.sql.SQLException; +import java.text.ParseException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Date; +import java.text.SimpleDateFormat; +import java.util.logging.Level; import org.apache.commons.lang.ArrayUtils; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeException; @@ -165,6 +169,33 @@ public class METSRightsCrosswalk // Create our <Context> node for this policy Element rightsContext = new Element("Context", METSRights_NS); + String rpName = policy.getRpName(); + if (rpName != null) + { + rightsContext.setAttribute("rpName",rpName); + } + + // As of DSpace 3.0, policies may have an effective date range, check if a policy is effective + rightsContext.setAttribute("in-effect","true"); + Date now = new Date(); + SimpleDateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd"); + if (policy.getStartDate() != null) + { + rightsContext.setAttribute("start-date", iso8601.format(policy.getStartDate())); + if (policy.getStartDate().after(now)) + { + rightsContext.setAttribute("in-effect","false"); + } + } + + if (policy.getEndDate() != null) + { + rightsContext.setAttribute("end-date", iso8601.format(policy.getEndDate())); + if (policy.getEndDate().before(now)) + { + rightsContext.setAttribute("in-effect","false"); + } + } //First, handle Group-based policies // For Group policies we need to setup a @@ -418,6 +449,7 @@ public class METSRightsCrosswalk } // Loop through each Element in the List + List<ResourcePolicy> policies = new ArrayList<ResourcePolicy>(); for (Element element : ml) { // if we're fed a <RightsDeclarationMD> wrapper object, recurse on its guts: @@ -431,102 +463,178 @@ public class METSRightsCrosswalk //get what class of context this is String contextClass = element.getAttributeValue("CONTEXTCLASS"); - //also get reference to the <Permissions> element - Element permsElement = element.getChild("Permissions", METSRights_NS); + if ((element.getAttributeValue("start-date") != null) + || (element.getAttributeValue("end-date") != null) + || (element.getAttributeValue("rpName") != null)) + { + SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd" ); + try { + ResourcePolicy rp = ResourcePolicy.create(context); + if (element.getAttributeValue("CONTEXTCLASS").equalsIgnoreCase("GENERAL PUBLIC")) { + Group anonGroup = Group.find(context, 0); + rp.setGroup(anonGroup); + } + else + { + if (element.getAttributeValue("CONTEXTCLASS").equalsIgnoreCase("REPOSITORY MGR")) { + Group adminGroup = Group.find(context, 1); + rp.setGroup(adminGroup); + } + } + if (element.getAttributeValue("rpName") != null) + { + rp.setRpName(element.getAttributeValue("rpName")); + } + try { + if (element.getAttributeValue("start-date") != null) + { + rp.setStartDate(sdf.parse(element.getAttributeValue("start-date"))); + } + if (element.getAttributeValue("end-date") != null) + { + rp.setEndDate(sdf.parse(element.getAttributeValue("end-date"))); + } + }catch (ParseException ex) { + java.util.logging.Logger.getLogger(METSRightsCrosswalk.class.getName()).log(Level.SEVERE, null, ex); + } - //Check if this permission pertains to Anonymous users - if(ANONYMOUS_CONTEXTCLASS.equals(contextClass)) + List<Element> le = new ArrayList<Element>(element.getChildren()); + for (Element el : le) + { + if ((el.getAttributeValue("DISCOVER").equalsIgnoreCase("true")) + && (el.getAttributeValue("DISPLAY").equalsIgnoreCase("true"))) + { + if (el.getAttributeValue("DELETE").equalsIgnoreCase("false")) + { + if (el.getAttributeValue("MODIFY").equalsIgnoreCase("false")) + { + rp.setAction(Constants.READ); + } + else + { + rp.setAction(Constants.WRITE); + } + } + else + { + if (el.getAttributeValue("MODIFY").equalsIgnoreCase("true")) + { + rp.setAction(Constants.DELETE); + if ((el.getAttributeValue("COPY").equalsIgnoreCase("true")) + &&(el.getAttributeValue("DUPLICATE").equalsIgnoreCase("true")) + &&(el.getAttributeValue("PRINT").equalsIgnoreCase("true"))) + { + rp.setAction(Constants.ADMIN); + } + } + } + } + } + policies.add(rp); + } catch (NullPointerException ex) { + java.util.logging.Logger.getLogger(METSRightsCrosswalk.class.getName()).log(Level.SEVERE, null, ex); + } + assignPermissions(context, dso, policies); + } + else { - //get DSpace Anonymous group, ID=0 - Group anonGroup = Group.find(context, 0); - if(anonGroup==null) + //also get reference to the <Permissions> element + Element permsElement = element.getChild("Permissions", METSRights_NS); + + //Check if this permission pertains to Anonymous users + if(ANONYMOUS_CONTEXTCLASS.equals(contextClass)) { - throw new CrosswalkInternalException("The DSpace database has not been properly initialized. The Anonymous Group is missing from the database."); - } + //get DSpace Anonymous group, ID=0 + Group anonGroup = Group.find(context, 0); + if(anonGroup==null) + { + throw new CrosswalkInternalException("The DSpace database has not been properly initialized. The Anonymous Group is missing from the database."); + } - assignPermissions(context, dso, anonGroup, permsElement); - } // else if this permission declaration pertains to Administrators - else if(ADMIN_CONTEXTCLASS.equals(contextClass)) - { - //get DSpace Administrator group, ID=1 - Group adminGroup = Group.find(context, 1); - if(adminGroup==null) + assignPermissions(context, dso, anonGroup, permsElement); + } // else if this permission declaration pertains to Administrators + else if(ADMIN_CONTEXTCLASS.equals(contextClass)) { - throw new CrosswalkInternalException("The DSpace database has not been properly initialized. The Administrator Group is missing from the database."); - } + //get DSpace Administrator group, ID=1 + Group adminGroup = Group.find(context, 1); + if(adminGroup==null) + { + throw new CrosswalkInternalException("The DSpace database has not been properly initialized. The Administrator Group is missing from the database."); + } - assignPermissions(context, dso, adminGroup, permsElement); - } // else if this permission pertains to another DSpace group - else if(GROUP_CONTEXTCLASS.equals(contextClass)) - { - try + assignPermissions(context, dso, adminGroup, permsElement); + } // else if this permission pertains to another DSpace group + else if(GROUP_CONTEXTCLASS.equals(contextClass)) + { + try + { + //we need to find the name of DSpace group it pertains to + //Get the text within the <UserName> child element, + // this is the group's name + String groupName = element.getChildTextTrim("UserName", METSRights_NS); + + //Translate Group name back to internal ID format (e.g. COLLECTION_<ID>_ADMIN) + // from its external format (e.g. COLLECTION_<handle>_ADMIN) + groupName = PackageUtils.translateGroupNameForImport(context, groupName); + + //Check if this group exists in DSpace already + Group group = Group.findByName(context, groupName); + + //if not found, throw an error -- user should restore group from the SITE AIP + if(group==null) + { + throw new CrosswalkInternalException("Cannot restore Group permissions on object (" + + "type=" + Constants.typeText[dso.getType()] + ", " + + "handle=" + dso.getHandle() + ", " + + "ID=" + dso.getID() + + "). The Group named '" + groupName + "' is missing from DSpace. " + + "Please restore this group using the SITE AIP, or recreate it."); + } + + //assign permissions to group on this object + assignPermissions(context, dso, group, permsElement); + } + catch(PackageException pe) + { + //A PackageException will only be thrown if translateDefaultGroupName() fails + //We'll just wrap it as a CrosswalkException and throw it upwards + throw new CrosswalkException(pe); + } + }//end if Group + else if(PERSON_CONTEXTCLASS.equals(contextClass)) { - //we need to find the name of DSpace group it pertains to - //Get the text within the <UserName> child element, - // this is the group's name - String groupName = element.getChildTextTrim("UserName", METSRights_NS); + //we need to find the person it pertains to + // Get the text within the <UserName> child element, + // this is the person's email address + String personEmail = element.getChildTextTrim("UserName", METSRights_NS); - //Translate Group name back to internal ID format (e.g. COLLECTION_<ID>_ADMIN) - // from its external format (e.g. COLLECTION_<handle>_ADMIN) - groupName = PackageUtils.translateGroupNameForImport(context, groupName); + //Check if this person exists in DSpace already + EPerson person = EPerson.findByEmail(context, personEmail); - //Check if this group exists in DSpace already - Group group = Group.findByName(context, groupName); + //If cannot find by email, try by netID + //(though METSRights should contain email if it was exported by DSpace) + if(person==null) + { + person = EPerson.findByNetid(context, personEmail); + } - //if not found, throw an error -- user should restore group from the SITE AIP - if(group==null) + //if not found, throw an error -- user should restore person from the SITE AIP + if(person==null) { - throw new CrosswalkInternalException("Cannot restore Group permissions on object (" + throw new CrosswalkInternalException("Cannot restore Person permissions on object (" + "type=" + Constants.typeText[dso.getType()] + ", " + "handle=" + dso.getHandle() + ", " + "ID=" + dso.getID() - + "). The Group named '" + groupName + "' is missing from DSpace. " - + "Please restore this group using the SITE AIP, or recreate it."); + + "). The Person with email/netid '" + personEmail + "' is missing from DSpace. " + + "Please restore this Person object using the SITE AIP, or recreate it."); } - //assign permissions to group on this object - assignPermissions(context, dso, group, permsElement); - } - catch(PackageException pe) - { - //A PackageException will only be thrown if translateDefaultGroupName() fails - //We'll just wrap it as a CrosswalkException and throw it upwards - throw new CrosswalkException(pe); - } - }//end if Group - else if(PERSON_CONTEXTCLASS.equals(contextClass)) - { - //we need to find the person it pertains to - // Get the text within the <UserName> child element, - // this is the person's email address - String personEmail = element.getChildTextTrim("UserName", METSRights_NS); - - //Check if this person exists in DSpace already - EPerson person = EPerson.findByEmail(context, personEmail); - - //If cannot find by email, try by netID - //(though METSRights should contain email if it was exported by DSpace) - if(person==null) - { - person = EPerson.findByNetid(context, personEmail); - } - - //if not found, throw an error -- user should restore person from the SITE AIP - if(person==null) - { - throw new CrosswalkInternalException("Cannot restore Person permissions on object (" - + "type=" + Constants.typeText[dso.getType()] + ", " - + "handle=" + dso.getHandle() + ", " - + "ID=" + dso.getID() - + "). The Person with email/netid '" + personEmail + "' is missing from DSpace. " - + "Please restore this Person object using the SITE AIP, or recreate it."); - } - - //assign permissions to person on this object - assignPermissions(context, dso, person, permsElement); - }//end if Person - else - log.error("Unrecognized CONTEXTCLASS: " + contextClass); + //assign permissions to person on this object + assignPermissions(context, dso, person, permsElement); + }//end if Person + else + log.error("Unrecognized CONTEXTCLASS: " + contextClass); + } } //end if "Context" element }//end while loop } @@ -542,6 +650,18 @@ public class METSRightsCrosswalk * @param group The DSpace Group * @param permsElement The METSRights <code>Permissions</code> element */ +private void assignPermissions(Context context, DSpaceObject dso, List<ResourcePolicy> policies) + throws SQLException, AuthorizeException + { + AuthorizeManager.removeAllPolicies(context, dso); + if (policies == null){ + throw new AuthorizeException("Policies are null"); + } + else{ + AuthorizeManager.addPolicies(context, policies, dso); + } + } + private void assignPermissions(Context context, DSpaceObject dso, Group group, Element permsElement) throws SQLException, AuthorizeException { diff --git a/dspace-api/src/main/java/org/dspace/content/crosswalk/RoleCrosswalk.java b/dspace-api/src/main/java/org/dspace/content/crosswalk/RoleCrosswalk.java index bc5e56f516594142228ca4b01d29493eca931fa5..b9fdc53a4767d317582871aa249a754a660dda52 100644 --- a/dspace-api/src/main/java/org/dspace/content/crosswalk/RoleCrosswalk.java +++ b/dspace-api/src/main/java/org/dspace/content/crosswalk/RoleCrosswalk.java @@ -182,7 +182,8 @@ public class RoleCrosswalk } // Create a temporary file to disseminate into - String tempDirectory = ConfigurationManager.getProperty("upload.temp.dir"); + String tempDirectory = (ConfigurationManager.getProperty("upload.temp.dir") != null) + ? ConfigurationManager.getProperty("upload.temp.dir") : System.getProperty("java.io.tmpdir"); File tempFile = File.createTempFile("RoleCrosswalkDisseminate" + dso.hashCode(), null, new File(tempDirectory)); tempFile.deleteOnExit(); @@ -311,7 +312,8 @@ public class RoleCrosswalk } // Create a temporary file to ingest from - String tempDirectory = ConfigurationManager.getProperty("upload.temp.dir"); + String tempDirectory = (ConfigurationManager.getProperty("upload.temp.dir") != null) + ? ConfigurationManager.getProperty("upload.temp.dir") : System.getProperty("java.io.tmpdir"); File tempFile = File.createTempFile("RoleCrosswalkIngest" + dso.hashCode(), null, new File(tempDirectory)); tempFile.deleteOnExit(); FileOutputStream fileOutStream = null; @@ -340,4 +342,4 @@ public class RoleCrosswalk } } -} \ No newline at end of file +} diff --git a/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java b/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java index 1f6b637ea9c5c4ba12d18f1eaad1bad85c9f4b38..63eb2bc69aa071a4d429900239f3ed3cb4bd5381 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/AbstractMETSIngester.java @@ -749,6 +749,8 @@ public abstract class AbstractMETSIngester extends AbstractPackageIngester // Loop through these files, and add them one by one to Item List<Element> manifestContentFiles = manifest .getContentFiles(); + List<Element> manifestBundleFiles = manifest + .getBundleFiles(); boolean setPrimaryBitstream = false; BitstreamFormat unknownFormat = BitstreamFormat.findUnknown(context); @@ -837,6 +839,40 @@ public abstract class AbstractMETSIngester extends AbstractPackageIngester bitstream.update(); }// end for each manifest file + for (Iterator<Element> mi = manifestBundleFiles.iterator(); mi + .hasNext();) + { + Element mfile = mi.next(); + + String bundleName = METSManifest.getBundleName(mfile, false); + + Bundle bundle; + Bundle bns[] = item.getBundles(bundleName); + if (bns != null && bns.length > 0) + { + bundle = bns[0]; + } + else + { + bundle = item.createBundle(bundleName); + } + + String mfileGrp = mfile.getAttributeValue("ADMID"); + if (mfileGrp != null) + { + manifest.crosswalkBundle(context, params, bundle, mfileGrp,mdRefCallback); + } + else + { + if (log.isDebugEnabled()) + { + log.debug("Ingesting bundle with no ADMID, not crosswalking bundle metadata"); + } + } + + bundle.update(); + }// end for each manifest file + // Step 3 -- Sanity checks // sanity check for primary bitstream if (primaryID != null && !setPrimaryBitstream) diff --git a/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java b/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java index 2b5a66bcdce3157d41421122f466485c130555c0..2ec62373bd1ac5371bbfdcb159a6bf2b78eaa864 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/METSManifest.java @@ -21,6 +21,7 @@ import org.apache.commons.codec.binary.Base64; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; import org.dspace.content.DSpaceObject; import org.dspace.content.crosswalk.AbstractPackagerWrappingCrosswalk; import org.dspace.content.crosswalk.CrosswalkException; @@ -155,6 +156,7 @@ public class METSManifest /** <file> elements in "original" file group (bundle) */ private List<Element> contentFiles = null; + private List<Element> bundleFiles = null; /** builder to use for mdRef streams, inherited from create() */ private SAXBuilder parser = null; @@ -319,6 +321,29 @@ public class METSManifest * the item's content. * @return a List of <code>Element</code>s. */ + public List<Element> getBundleFiles() + throws MetadataValidationException + { + if (bundleFiles != null) + { + return bundleFiles; + } + + bundleFiles = new ArrayList<Element>(); + Element fileSec = mets.getChild("fileSec", metsNS); + + if (fileSec != null) + { + Iterator fgi = fileSec.getChildren("fileGrp", metsNS).iterator(); + while (fgi.hasNext()) + { + Element fg = (Element)fgi.next(); + bundleFiles.add(fg); + } + } + return bundleFiles; + } + public List<Element> getContentFiles() throws MetadataValidationException { @@ -446,7 +471,24 @@ public class METSManifest public static String getBundleName(Element file) throws MetadataValidationException { - Element fg = file.getParentElement(); + return getBundleName(file, true); + } + + /** + * Get the DSpace bundle name corresponding to the <code>USE</code> + * attribute of the file group enclosing this <code>file</code> element. + * + * @return DSpace bundle name + * @throws MetadataValidationException when there is no USE attribute on the enclosing fileGrp. + */ + public static String getBundleName(Element file, boolean getParent) + throws MetadataValidationException + { + Element fg = file; + if (getParent) + { + fg = file.getParentElement(); + } String fgUse = fg.getAttributeValue("USE"); if (fgUse == null) { @@ -1271,9 +1313,52 @@ public class METSManifest { crosswalkXmd(context, params, bitstream, (Element)ti.next(), callback); } + for (Iterator ti = amdSec.getChildren("rightsMD", metsNS).iterator(); ti.hasNext();) + { + crosswalkXmd(context, params, bitstream, (Element)ti.next(), callback); + } } } + + public void crosswalkBundle(Context context, PackageParameters params, + Bundle bundle, + String fileId, Mdref callback) + throws MetadataValidationException, PackageValidationException, + CrosswalkException, IOException, SQLException, AuthorizeException + { + Element file = getElementByXPath("descendant::mets:fileGrp[@ADMID=\""+fileId+"\"]", false); + if (file == null) + { + throw new MetadataValidationException("Failed in Bitstream crosswalk, Could not find file element with ID=" + fileId); + } + + // In DSpace METS SIP spec, admin metadata is only "highly + // recommended", not "required", so it is OK if there is no ADMID. + String amds = file.getAttributeValue("ADMID"); + if (amds == null) + { + log.warn("Got no bitstream ADMID, file@ID="+fileId); + return; + } + String amdID[] = amds.split("\\s+"); + for (int i = 0; i < amdID.length; ++i) + { + Element amdSec = getElementByXPath("mets:amdSec[@ID=\""+amdID[i]+"\"]", false); + for (Iterator ti = amdSec.getChildren("techMD", metsNS).iterator(); ti.hasNext();) + { + crosswalkXmd(context, params, bundle, (Element)ti.next(), callback); + } + for (Iterator ti = amdSec.getChildren("sourceMD", metsNS).iterator(); ti.hasNext();) + { + crosswalkXmd(context, params, bundle, (Element)ti.next(), callback); + } + for (Iterator ti = amdSec.getChildren("rightsMD", metsNS).iterator(); ti.hasNext();) + { + crosswalkXmd(context, params, bundle, (Element)ti.next(), callback); + } + } + } /** * @return root element of METS document. */ diff --git a/dspace-api/src/main/java/org/dspace/content/packager/RoleDisseminator.java b/dspace-api/src/main/java/org/dspace/content/packager/RoleDisseminator.java index b871d6b4aa17f27d451ad065db7e312f2eef479f..84aea2a05e10b7a8707a658b05f9ffd13b63ffdd 100644 --- a/dspace-api/src/main/java/org/dspace/content/packager/RoleDisseminator.java +++ b/dspace-api/src/main/java/org/dspace/content/packager/RoleDisseminator.java @@ -334,7 +334,8 @@ public class RoleDisseminator implements PackageDisseminator { writer.writeEmptyElement(MEMBER); writer.writeAttribute(ID, String.valueOf(member.getID())); - writer.writeAttribute(NAME, member.getName()); + if (null != member.getName()) + writer.writeAttribute(NAME, member.getName()); } writer.writeEndElement(); } @@ -444,9 +445,12 @@ public class RoleDisseminator implements PackageDisseminator writer.writeStartElement(EPERSON); writer.writeAttribute(ID, String.valueOf(eperson.getID())); - writer.writeStartElement(EMAIL); - writer.writeCharacters(eperson.getEmail()); - writer.writeEndElement(); + if (eperson.getEmail()!=null) + { + writer.writeStartElement(EMAIL); + writer.writeCharacters(eperson.getEmail()); + writer.writeEndElement(); + } if(eperson.getNetid()!=null) { @@ -479,19 +483,25 @@ public class RoleDisseminator implements PackageDisseminator if (emitPassword) { PasswordHash password = eperson.getPasswordHash(); + if (null != password) + { + writer.writeStartElement(PASSWORD_HASH); - writer.writeStartElement(PASSWORD_HASH); - - String algorithm = password.getAlgorithm(); - if (null != algorithm) - writer.writeAttribute(PASSWORD_DIGEST, algorithm); + String algorithm = password.getAlgorithm(); + if (null != algorithm) + { + writer.writeAttribute(PASSWORD_DIGEST, algorithm); + } - String salt = password.getSaltString(); - if (null != salt) - writer.writeAttribute(PASSWORD_SALT, salt); + String salt = password.getSaltString(); + if (null != salt) + { + writer.writeAttribute(PASSWORD_SALT, salt); + } - writer.writeCharacters(password.getHashString()); - writer.writeEndElement(); + writer.writeCharacters(password.getHashString()); + writer.writeEndElement(); + } } if (eperson.canLogIn()) diff --git a/dspace-api/src/main/java/org/dspace/core/ConfigurationManager.java b/dspace-api/src/main/java/org/dspace/core/ConfigurationManager.java index b250f7680c6e2bf5b13b9038877e4c6177d3406a..3020bf53c7bc67869e979f6f3c06aa0793d0afde 100644 --- a/dspace-api/src/main/java/org/dspace/core/ConfigurationManager.java +++ b/dspace-api/src/main/java/org/dspace/core/ConfigurationManager.java @@ -7,16 +7,11 @@ */ package org.dspace.core; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; import java.net.MalformedURLException; import java.net.URL; import java.util.Enumeration; @@ -30,8 +25,7 @@ import org.apache.log4j.helpers.OptionConverter; /** * Class for reading the DSpace system configuration. The main configuration is - * read in as properties from a standard properties file. Email templates and - * configuration files for other tools are also be accessed via this class. + * read in as properties from a standard properties file. * <P> * The main configuration is by default read from the <em>resource</em> * <code>/dspace.cfg</code>. @@ -43,7 +37,7 @@ import org.apache.log4j.helpers.OptionConverter; * of the DSpace installation directory (specified as the property * <code>dspace.dir</code> in the main configuration file.) * - * + * * @author Robert Tansley * @author Larry Stone - Interpolated values. * @author Mark Diggory - General Improvements to detection, logging and loading. @@ -56,20 +50,17 @@ public class ConfigurationManager /** The configuration properties */ private static Properties properties = null; - + /** module configuration properties */ private static Map<String, Properties> moduleProps = new HashMap<String, Properties>(); - /** The default license */ - private static String license; - // limit of recursive depth of property variable interpolation in // configuration; anything greater than this is very likely to be a loop. private static final int RECURSION_LIMIT = 9; protected ConfigurationManager() { - + } /** @@ -80,7 +71,7 @@ public class ConfigurationManager { return properties != null; } - + public static boolean isConfigured(String module) { return moduleProps.get(module) != null; @@ -97,24 +88,24 @@ public class ConfigurationManager // { // properties = null; // } - + /** * REMOVED - Flushing the properties could be dangerous in the current DSpace state * Need to consider how it will affect in-flight processes * * Discard properties for a module - will force a reload from disk * when any of module's properties are requested - * + * * @param module the module name */ // public static void flush(String module) // { // moduleProps.remove(module); // } - + /** * Returns all properties in main configuration - * + * * @return properties - all non-modular properties */ public static Properties getProperties() @@ -135,7 +126,7 @@ public class ConfigurationManager /** * Returns all properties for a given module - * + * * @param module * the name of the module * @return properties - all module's properties @@ -163,10 +154,10 @@ public class ConfigurationManager /** * Get a configuration property - * + * * @param property * the name of the property - * + * * @return the value of the property, or <code>null</code> if the property * does not exist. */ @@ -176,11 +167,11 @@ public class ConfigurationManager String value = props == null ? null : props.getProperty(property); return (value != null) ? value.trim() : null; } - + /** * Get a module configuration property value. - * - * @param module + * + * @param module * the name of the module, or <code>null</code> for regular configuration * property * @param property @@ -195,7 +186,7 @@ public class ConfigurationManager { return getProperty(property); } - + String value = null; Properties modProps = getMutableProperties(module); @@ -215,10 +206,10 @@ public class ConfigurationManager /** * Get a configuration property as an integer - * + * * @param property * the name of the property - * + * * @return the value of the property. <code>0</code> is returned if the * property does not exist. To differentiate between this case and * when the property actually is zero, use <code>getProperty</code>. @@ -227,16 +218,16 @@ public class ConfigurationManager { return getIntProperty(property, 0); } - + /** * Get a module configuration property as an integer * * @param module * the name of the module - * + * * @param property * the name of the property - * + * * @return the value of the property. <code>0</code> is returned if the * property does not exist. To differentiate between this case and * when the property actually is zero, use <code>getProperty</code>. @@ -248,10 +239,10 @@ public class ConfigurationManager /** * Get a configuration property as an integer, with default - * + * * @param property * the name of the property - * + * * @param defaultValue * value to return if property is not found or is not an Integer. * @@ -264,16 +255,16 @@ public class ConfigurationManager { return getIntProperty(null, property, defaultValue); } - + /** * Get a module configuration property as an integer, with default - * + * * @param module * the name of the module - * + * * @param property * the name of the property - * + * * @param defaultValue * value to return if property is not found or is not an Integer. * @@ -316,12 +307,12 @@ public class ConfigurationManager { return getLongProperty(property, 0); } - + /** * Get a module configuration property as a long * * @param module - * the name of the module + * the name of the module * @param property * the name of the property * @@ -333,10 +324,10 @@ public class ConfigurationManager { return getLongProperty(module, property, 0); } - + /** * Get a configuration property as an long, with default - * + * * * @param property * the name of the property @@ -356,7 +347,7 @@ public class ConfigurationManager /** * Get a configuration property as an long, with default - * + * * @param module the module, or <code>null</code> for regular property * * @param property @@ -390,78 +381,14 @@ public class ConfigurationManager return longValue; } - /** - * Get the License - * - * @param - * licenseFile file name - * - * @return - * license text - * - */ - public static String getLicenseText(String licenseFile) - { - // Load in default license - - FileReader fr = null; - BufferedReader br = null; - try - { - fr = new FileReader(licenseFile); - br = new BufferedReader(fr); - String lineIn; - license = ""; - while ((lineIn = br.readLine()) != null) - { - license = license + lineIn + '\n'; - } - } - catch (IOException e) - { - fatal("Can't load configuration", e); - - // FIXME: Maybe something more graceful here, but with the - // configuration we can't do anything - throw new IllegalStateException("Failed to read default license.", e); - } - finally - { - if (br != null) - { - try - { - br.close(); - } - catch (IOException ioe) - { - } - } - - if (fr != null) - { - try - { - fr.close(); - } - catch (IOException ioe) - { - - } - } - } - - return license; - } - /** * Get a configuration property as a boolean. True is indicated if the value * of the property is <code>TRUE</code> or <code>YES</code> (case * insensitive.) - * + * * @param property * the name of the property - * + * * @return the value of the property. <code>false</code> is returned if * the property does not exist. To differentiate between this case * and when the property actually is false, use @@ -471,17 +398,17 @@ public class ConfigurationManager { return getBooleanProperty(property, false); } - + /** - * Get a module configuration property as a boolean. True is indicated if + * Get a module configuration property as a boolean. True is indicated if * the value of the property is <code>TRUE</code> or <code>YES</code> (case * insensitive.) - * - * @param module the module, or <code>null</code> for regular property - * + * + * @param module the module, or <code>null</code> for regular property + * * @param property * the name of the property - * + * * @return the value of the property. <code>false</code> is returned if * the property does not exist. To differentiate between this case * and when the property actually is false, use @@ -491,7 +418,7 @@ public class ConfigurationManager { return getBooleanProperty(module, property, false); } - + /** * Get a configuration property as a boolean, with default. * True is indicated if the value @@ -519,8 +446,8 @@ public class ConfigurationManager * True is indicated if the value * of the property is <code>TRUE</code> or <code>YES</code> (case * insensitive.) - * - * @param module module, or <code>null</code> for regular property + * + * @param module module, or <code>null</code> for regular property * * @param property * the name of the property @@ -551,19 +478,19 @@ public class ConfigurationManager /** * Returns an enumeration of all the keys in the DSpace configuration - * + * * @return an enumeration of all the keys in the DSpace configuration */ public static Enumeration<?> propertyNames() { return propertyNames(null); } - + /** * Returns an enumeration of all the keys in a module configuration - * - * @param module module, or <code>null</code> for regular property - * + * + * @param module module, or <code>null</code> for regular property + * * @return an enumeration of all the keys in the module configuration, * or <code>null</code> if the module does not exist. */ @@ -573,211 +500,14 @@ public class ConfigurationManager return props == null ? null : props.propertyNames(); } - /** - * Get the template for an email message. The message is suitable for - * inserting values using <code>java.text.MessageFormat</code>. - * - * @param emailFile - * full name for the email template, for example "/dspace/config/emails/register". - * - * @return the email object, with the content and subject filled out from - * the template - * - * @throws IOException - * if the template couldn't be found, or there was some other - * error reading the template - */ - public static Email getEmail(String emailFile) throws IOException - { - String charset = null; - String subject = ""; - StringBuffer contentBuffer = new StringBuffer(); - - // Read in template - BufferedReader reader = null; - try - { - reader = new BufferedReader(new FileReader(emailFile)); - - boolean more = true; - - while (more) - { - String line = reader.readLine(); - - if (line == null) - { - more = false; - } - else if (line.toLowerCase().startsWith("subject:")) - { - // Extract the first subject line - everything to the right - // of the colon, trimmed of whitespace - subject = line.substring(8).trim(); - } - else if (line.toLowerCase().startsWith("charset:")) - { - // Extract the character set from the email - charset = line.substring(8).trim(); - } - else if (!line.startsWith("#")) - { - // Add non-comment lines to the content - contentBuffer.append(line); - contentBuffer.append("\n"); - } - } - } - finally - { - if (reader != null) - { - reader.close(); - } - } - // Create an email - Email email = new Email(); - email.setSubject(subject); - email.setContent(contentBuffer.toString()); - - if (charset != null) - { - email.setCharset(charset); - } - - return email; - } - - /** - * Get the site-wide default license that submitters need to grant - * - * @return the default license - */ - public static String getDefaultSubmissionLicense() - { - if (properties == null) - { - loadConfig(null); - } - - return license; - } - - /** - * Get the path for the news files. - * - */ - public static String getNewsFilePath() - { - String filePath = ConfigurationManager.getProperty("dspace.dir") - + File.separator + "config" + File.separator; - - return filePath; - } - - /** - * Reads news from a text file. - * - * @param newsFile - * name of the news file to read in, relative to the news file path. - */ - public static String readNewsFile(String newsFile) - { - String fileName = getNewsFilePath(); - - fileName += newsFile; - - StringBuilder text = new StringBuilder(); - - try - { - // retrieve existing news from file - FileInputStream fir = new FileInputStream(fileName); - InputStreamReader ir = new InputStreamReader(fir, "UTF-8"); - BufferedReader br = new BufferedReader(ir); - - String lineIn; - - while ((lineIn = br.readLine()) != null) - { - text.append(lineIn); - } - - br.close(); - } - catch (IOException e) - { - warn("news_read: " + e.getLocalizedMessage()); - } - - return text.toString(); - } - - /** - * Writes news to a text file. - * - * @param newsFile - * name of the news file to read in, relative to the news file path. - * @param news - * the text to be written to the file. - */ - public static String writeNewsFile(String newsFile, String news) - { - String fileName = getNewsFilePath(); - - fileName += newsFile; - - try - { - // write the news out to the appropriate file - FileOutputStream fos = new FileOutputStream(fileName); - OutputStreamWriter osr = new OutputStreamWriter(fos, "UTF-8"); - PrintWriter out = new PrintWriter(osr); - out.print(news); - out.close(); - } - catch (IOException e) - { - warn("news_write: " + e.getLocalizedMessage()); - } - - return news; - } - - /** - * Writes license to a text file. - * - * @param licenseFile - * name for the file int which license will be written, - * relative to the current directory. - */ - public static void writeLicenseFile(String licenseFile, String newLicense) - { - try - { - // write the news out to the appropriate file - FileOutputStream fos = new FileOutputStream(licenseFile); - OutputStreamWriter osr = new OutputStreamWriter(fos, "UTF-8"); - PrintWriter out = new PrintWriter(osr); - out.print(newLicense); - out.close(); - } - catch (IOException e) - { - warn("license_write: " + e.getLocalizedMessage()); - } - - license = newLicense; - } - + /** The configuration that was loaded. */ private static File loadedFile = null; /** - * Return the file that configuration was actually loaded from. Only returns - * a valid File after configuration has been loaded. - * + * Return the file that configuration was actually loaded from. + * * @deprecated Please remove all direct usage of the configuration file. - * @return File naming configuration data file, or null if not loaded yet. + * @return File naming configuration data file. */ protected static File getConfigurationFile() { @@ -805,13 +535,20 @@ public class ConfigurationManager { Properties modProps = new Properties(); InputStream modIS = null; + InputStreamReader modIR = null; try { modIS = new FileInputStream(modFile); - modProps.load(modIS); + modIR = new InputStreamReader(modIS, "UTF-8"); + modProps.load(modIR); } finally { + if (modIR != null) + { + modIR.close(); + } + if (modIS != null) { modIS.close(); @@ -837,17 +574,16 @@ public class ConfigurationManager } catch (IOException ioE) { - fatal("Can't load configuration: " + (modFile == null ? "<unknown>" : modFile.getAbsolutePath()), ioE); + fatal("Can't load configuration: " + + (modFile == null ? "<unknown>" : modFile.getAbsolutePath()), ioE); } - - return; } /** * Load the DSpace configuration properties. Only does anything if * properties are not already loaded. Properties are loaded in from the * specified file, or default locations. - * + * * @param configFile * The <code>dspace.cfg</code> configuration file to use, or * <code>null</code> to try default locations @@ -860,8 +596,9 @@ public class ConfigurationManager } URL url = null; - + InputStream is = null; + InputStreamReader reader = null; try { String configProperty = null; @@ -875,27 +612,27 @@ public class ConfigurationManager // This isn't really a fatal error though, so catch and ignore log.warn("Unable to access system properties, ignoring.", se); } - + // should only occur after a flush() if (loadedFile != null) { info("Reloading current config file: " + loadedFile.getAbsolutePath()); - + url = loadedFile.toURI().toURL(); } else if (configFile != null) { info("Loading provided config file: " + configFile); - + loadedFile = new File(configFile); url = loadedFile.toURI().toURL(); - + } // Has the default configuration location been overridden? else if (configProperty != null) { info("Loading system provided config property (-Ddspace.configuration): " + configProperty); - + // Load the overriding configuration loadedFile = new File(configProperty); url = loadedFile.toURI().toURL(); @@ -907,11 +644,11 @@ public class ConfigurationManager if (url != null) { info("Loading from classloader: " + url); - + loadedFile = new File(url.getPath()); } } - + if (url == null) { fatal("Cannot find dspace.cfg"); @@ -921,7 +658,8 @@ public class ConfigurationManager { properties = new Properties(); is = url.openStream(); - properties.load(is); + reader = new InputStreamReader(is, "UTF-8"); + properties.load(reader); // walk values, interpolating any embedded references. for (Enumeration<?> pe = properties.propertyNames(); pe.hasMoreElements(); ) @@ -940,140 +678,79 @@ public class ConfigurationManager { fatal("Can't load configuration: " + url, e); - // FIXME: Maybe something more graceful here, but with the - // configuration we can't do anything + // FIXME: Maybe something more graceful here, but without a + // configuration we can't do anything. throw new IllegalStateException("Cannot load configuration: " + url, e); } finally { - if (is != null) + if (reader != null) { - try - { - is.close(); + try { + reader.close(); } catch (IOException ioe) - { - } - } - } - - // Load in default license - File licenseFile = new File(getProperty("dspace.dir") + File.separator - + "config" + File.separator + "default.license"); - - FileInputStream fir = null; - InputStreamReader ir = null; - BufferedReader br = null; - try - { - - fir = new FileInputStream(licenseFile); - ir = new InputStreamReader(fir, "UTF-8"); - br = new BufferedReader(ir); - String lineIn; - license = ""; - - while ((lineIn = br.readLine()) != null) - { - license = license + lineIn + '\n'; - } - - br.close(); - - } - catch (IOException e) - { - fatal("Can't load license: " + licenseFile.toString() , e); - - // FIXME: Maybe something more graceful here, but with the - // configuration we can't do anything - throw new IllegalStateException("Cannot load license: " + licenseFile.toString(),e); - } - finally - { - if (br != null) - { - try { - br.close(); - } - catch (IOException ioe) - { - } - } - - if (ir != null) - { - try - { - ir.close(); - } - catch (IOException ioe) - { } } - - if (fir != null) + if (is != null) { try { - fir.close(); + is.close(); } catch (IOException ioe) - { + { } } } - - try { /* * Initialize Logging once ConfigurationManager is initialized. - * - * This is selection from a property in dspace.cfg, if the property + * + * This is controlled by a property in dspace.cfg. If the property * is absent then nothing will be configured and the application - * will use the defaults provided by log4j. - * + * will use the defaults provided by log4j. + * * Property format is: - * + * * log.init.config = ${dspace.dir}/config/log4j.properties * or * log.init.config = ${dspace.dir}/config/log4j.xml - * + * * See default log4j initialization documentation here: * http://logging.apache.org/log4j/docs/manual.html - * + * * If there is a problem with the file referred to in - * "log.configuration" it needs to be sent to System.err + * "log.configuration", it needs to be sent to System.err * so do not instantiate another Logging configuration. * */ String dsLogConfiguration = ConfigurationManager.getProperty("log.init.config"); - if (dsLogConfiguration == null || System.getProperty("dspace.log.init.disable") != null) + if (dsLogConfiguration == null || System.getProperty("dspace.log.init.disable") != null) { - /* - * Do nothing if log config not set in dspace.cfg or "dspace.log.init.disable" - * system property set. Leave it upto log4j to properly init its logging + /* + * Do nothing if log config not set in dspace.cfg or "dspace.log.init.disable" + * system property set. Leave it upto log4j to properly init its logging * via classpath or system properties. */ - info("Using default log4j provided log configuration," + - "if unintended, check your dspace.cfg for (log.init.config)"); + info("Using default log4j provided log configuration." + + " If unintended, check your dspace.cfg for (log.init.config)"); } else { info("Using dspace provided log configuration (log.init.config)"); - - + + File logConfigFile = new File(dsLogConfiguration); - + if(logConfigFile.exists()) { info("Loading: " + dsLogConfiguration); - + OptionConverter.selectAndConfigure(logConfigFile.toURI() .toURL(), null, org.apache.log4j.LogManager .getLoggerRepository()); @@ -1090,7 +767,61 @@ public class ConfigurationManager fatal("Can't load dspace provided log4j configuration", e); throw new IllegalStateException("Cannot load dspace provided log4j configuration",e); } - + + } + + /** + * Wrapper for {@link NewsManager#getNewsFilePath()}. + * @deprecated since 4.0 + */ + public static String getNewsFilePath() + { + return NewsManager.getNewsFilePath(); + } + + /** + * Wrapper for {@link NewsManager#readNewsFile(java.lang.String)}. + * @deprecated since 4.0 + */ + public static String readNewsFile(String name) + { + return NewsManager.readNewsFile(name); + } + + /** + * Wrapper for {@link NewsManager#writeNewsFile(java.lang.String, java.lang.String)}. + * @deprecated since 4.0 + */ + public static String writeNewsFile(String file, String news) + { + return NewsManager.writeNewsFile(file, news); + } + + /** + * Wrapper for {@link LicenseManager#getLicenseText(java.lang.String)}. + * @deprecated since 4.0 + */ + public static String getLicenseText(String licenseFile) + { + return LicenseManager.getLicenseText(licenseFile); + } + + /** + * Wrapper for {@link LicenseManager#getDefaultSubmissionLicense()}. + * @deprecated since 4.0 + */ + public static String getDefaultSubmissionLicense() + { + return LicenseManager.getDefaultSubmissionLicense(); + } + + /** + * Wrapper for {@link LicenseManager#writeLicenseFile(java.lang.String, java.lang.String)}. + * @deprecated since 4.0 + */ + public static void writeLicenseFile(String licenseFile, String newLicense) + { + LicenseManager.writeLicenseFile(licenseFile, newLicense); } /** @@ -1167,7 +898,7 @@ public class ConfigurationManager * <code>name</code> from <code>dspace.cfg</code> to the standard * output. If the property does not exist, nothing is written.</li> * </ul> - * + * * @param argv * command-line arguments */ @@ -1189,7 +920,7 @@ public class ConfigurationManager System.exit(0); } else if ((argv.length == 4) && argv[0].equals("-module") && - argv[2].equals("-property")) + argv[2].equals("-property")) { String val = getProperty(argv[1], argv[3]); @@ -1212,7 +943,7 @@ public class ConfigurationManager System.exit(1); } - + private static void info(String string) { if (!isLog4jConfigured()) @@ -1263,8 +994,8 @@ public class ConfigurationManager } /* - * Only current solution available to detect - * if log4j is truly configured. + * Only current solution available to detect + * if log4j is truly configured. */ private static boolean isLog4jConfigured() { diff --git a/dspace-api/src/main/java/org/dspace/core/Constants.java b/dspace-api/src/main/java/org/dspace/core/Constants.java index 0d22fc04966f863e55c79c0e6d1e487988e87e64..e70e5abe2fea6628b541fffb3388c7ba573fde77 100644 --- a/dspace-api/src/main/java/org/dspace/core/Constants.java +++ b/dspace-api/src/main/java/org/dspace/core/Constants.java @@ -142,8 +142,8 @@ public class Constants "DEFAULT_BITSTREAM_READ", "DEFAULT_ITEM_READ", "ADMIN" }; /** - * constants for the relevance array generating dynamicallis is simple: just - * 1 < < TYPE + * generating constants for the relevance array dynamically is simple: just + * 1 << TYPE */ public static final int RBITSTREAM = 1 << BITSTREAM; @@ -157,10 +157,10 @@ public class Constants /** * Array of relevances of actions to objects - used by the UI to only - * display actions that are relevant to an object type To see if an action + * display actions that are relevant to an object type; To see if an action * is relevant to an object, just OR the relevance type above with the value * in actionTypeRelevance[] (To see if READ is relevant to community, just - * test actionTypeRelevance[READ] | RCOMMUNITY, 0 = irrelevant + * test actionTypeRelevance[READ] | RCOMMUNITY, 0 = irrelevant) */ public static final int[] actionTypeRelevance = { RBITSTREAM | RBUNDLE | RITEM | RCOLLECTION | RCOMMUNITY, // 0 - READ diff --git a/dspace-api/src/main/java/org/dspace/core/Context.java b/dspace-api/src/main/java/org/dspace/core/Context.java index e0e530430fa3f2f6b87aea7877400c62fff56652..a8b3382cba433f9b3943be96afd93f5a5044d9a9 100644 --- a/dspace-api/src/main/java/org/dspace/core/Context.java +++ b/dspace-api/src/main/java/org/dspace/core/Context.java @@ -41,6 +41,9 @@ public class Context { private static final Logger log = Logger.getLogger(Context.class); + /** option flags */ + public static final short READ_ONLY = 0x01; + /** Database connection */ private Connection connection; @@ -77,14 +80,42 @@ public class Context /** Event dispatcher name */ private String dispName = null; + /** options */ + private short options = 0; + /** - * Construct a new context object. A database connection is opened. No user - * is authenticated. + * Construct a new context object with default options. A database connection is opened. + * No user is authenticated. * * @exception SQLException * if there was an error obtaining a database connection */ public Context() throws SQLException + { + init(); + } + + /** + * Construct a new context object with passed options. A database connection is opened. + * No user is authenticated. + * + * @param options context operation flags + * @exception SQLException + * if there was an error obtaining a database connection + */ + public Context(short options) throws SQLException + { + this.options = options; + init(); + } + + /** + * Initializes a new context object. + * + * @exception SQLException + * if there was an error obtaining a database connection + */ + private void init() throws SQLException { // Obtain a non-auto-committing connection connection = DatabaseManager.getConnection(); @@ -292,7 +323,10 @@ public class Context try { // Commit any changes made as part of the transaction - commit(); + if (! isReadOnly()) + { + commit(); + } } finally { @@ -313,6 +347,14 @@ public class Context */ public void commit() throws SQLException { + /* + * invalid condition if in read-only mode: no valid + * transactions can be committed: no recourse but to bail + */ + if (isReadOnly()) + { + throw new IllegalStateException("Attempt to commit transaction in read-only context"); + } // Commit any changes made as part of the transaction Dispatcher dispatcher = null; @@ -368,6 +410,14 @@ public class Context */ public void addEvent(Event event) { + /* + * invalid condition if in read-only mode: events - which + * indicate mutation - are firing: no recourse but to bail + */ + if (isReadOnly()) + { + throw new IllegalStateException("Attempt to mutate object in read-only context"); + } if (events == null) { events = new LinkedList<Event>(); @@ -419,7 +469,10 @@ public class Context { if (!connection.isClosed()) { - connection.rollback(); + if (! isReadOnly()) + { + connection.rollback(); + } } } catch (SQLException se) @@ -459,6 +512,17 @@ public class Context return (connection != null); } + /** + * Reports whether context supports updating DSpaceObjects, or only reading. + * + * @return <code>true</code> if the context is read-only, otherwise + * <code>false</code> + */ + public boolean isReadOnly() + { + return (options & READ_ONLY) > 0; + } + /** * Store an object in the object cache. * @@ -487,8 +551,12 @@ public class Context */ public void cache(Object o, int id) { - String key = o.getClass().getName() + id; - objectCache.put(key, o); + // bypass cache if in read-only mode + if (! isReadOnly()) + { + String key = o.getClass().getName() + id; + objectCache.put(key, o); + } } /** diff --git a/dspace-api/src/main/java/org/dspace/core/Email.java b/dspace-api/src/main/java/org/dspace/core/Email.java index 540b978912bbf96c5289198cb5bb9468bbd7bd73..97e076a42d58a8fd0966ff26609d2c9557bbc84f 100644 --- a/dspace-api/src/main/java/org/dspace/core/Email.java +++ b/dspace-api/src/main/java/org/dspace/core/Email.java @@ -7,31 +7,38 @@ */ package org.dspace.core; -import org.apache.log4j.Logger; - +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Date; +import java.util.Enumeration; import java.util.Iterator; import java.util.List; -import java.util.Properties; - import javax.activation.DataHandler; +import javax.activation.DataSource; import javax.activation.FileDataSource; import javax.mail.Address; -import javax.mail.Authenticator; import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; -import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; +import org.apache.log4j.Logger; +import org.dspace.services.EmailService; +import org.dspace.utils.DSpace; /** * Class representing an e-mail message, also used to send e-mails. @@ -54,57 +61,48 @@ import javax.mail.internet.MimeMultipart; * starts with "Subject:" the text on the right of the colon is used for the * subject line. For example: * <P> - * + * * <pre> - * + * * # This is a comment line which is stripped * # * # Parameters: {0} is a person's name * # {1} is the name of a submission * # * Subject: Example e-mail - * + * * Dear {0}, - * + * * Thank you for sending us your submission "{1}". - * + * * </pre> - * + * * <P> * If the example code above was used to send this mail, the resulting mail * would have the subject <code>Example e-mail</code> and the body would be: * <P> - * + * * <pre> - * - * + * + * * Dear John, - * + * * Thank you for sending us your submission "On the Testing of DSpace". - * + * * </pre> - * + * * <P> * Note that parameters like <code>{0}</code> cannot be placed in the subject * of the e-mail; they won't get filled out. - * - * + * + * * @author Robert Tansley * @author Jim Downing - added attachment handling code - * @version $Revision$ + * @author Adan Roman Ruiz at arvo.es - added inputstream attachment handling code + * @version $Revision: 5844 $ */ public class Email { - /* - * Implementation note: It might be necessary to add a quick utility method - * like "send(to, subject, message)". We'll see how far we get without it - - * having all emails as templates in the config allows customisation and - * internationalisation. - * - * Note that everything is stored and the run in send() so that only send() - * throws a MessagingException. - */ - /** The content of the message */ private String content; @@ -121,6 +119,7 @@ public class Email private String replyTo; private List<FileAttachment> attachments; + private List<InputStreamAttachment> moreAttachments; /** The character set this message will be sent in */ private String charset; @@ -135,6 +134,7 @@ public class Email arguments = new ArrayList<Object>(50); recipients = new ArrayList<String>(50); attachments = new ArrayList<FileAttachment>(10); + moreAttachments = new ArrayList<InputStreamAttachment>(10); subject = ""; content = ""; replyTo = null; @@ -143,7 +143,7 @@ public class Email /** * Add a recipient - * + * * @param email * the recipient's email address */ @@ -156,7 +156,7 @@ public class Email * Set the content of the message. Setting this "resets" the message * formatting -<code>addArgument</code> will start. Comments and any * "Subject:" line must be stripped. - * + * * @param cnt * the content of the message */ @@ -168,7 +168,7 @@ public class Email /** * Set the subject of the message - * + * * @param s * the subject of the message */ @@ -179,7 +179,7 @@ public class Email /** * Set the reply-to email address - * + * * @param email * the reply-to email address */ @@ -190,7 +190,7 @@ public class Email /** * Fill out the next argument in the template - * + * * @param arg * the value for the next argument */ @@ -203,6 +203,10 @@ public class Email { attachments.add(new FileAttachment(f, name)); } + public void addAttachment(InputStream is, String name,String mimetype) + { + moreAttachments.add(new InputStreamAttachment(is, name,mimetype)); + } public void setCharset(String cs) { @@ -218,78 +222,33 @@ public class Email arguments = new ArrayList<Object>(50); recipients = new ArrayList<String>(50); attachments = new ArrayList<FileAttachment>(10); + moreAttachments = new ArrayList<InputStreamAttachment>(10); replyTo = null; charset = null; } /** * Sends the email. - * + * * @throws MessagingException * if there was a problem sending the mail. + * @throws IOException */ - public void send() throws MessagingException + public void send() throws MessagingException, IOException { // Get the mail configuration properties - String server = ConfigurationManager.getProperty("mail.server"); String from = ConfigurationManager.getProperty("mail.from.address"); boolean disabled = ConfigurationManager.getBooleanProperty("mail.server.disabled", false); - if (disabled) { - log.info("message not sent due to mail.server.disabled: " + subject); - return; - } - - // Set up properties for mail session - Properties props = System.getProperties(); - props.put("mail.smtp.host", server); - - // Set the port number for the mail server - String portNo = ConfigurationManager.getProperty("mail.server.port"); - if (portNo == null) - { - portNo = "25"; - } - props.put("mail.smtp.port", portNo.trim()); - // If no character set specified, attempt to retrieve a default if (charset == null) { - charset = ConfigurationManager.getProperty("mail.charset"); + charset = ConfigurationManager.getProperty("mail.charset"); } // Get session - Session session; - - // Get the SMTP server authentication information - String username = ConfigurationManager.getProperty("mail.server.username"); - String password = ConfigurationManager.getProperty("mail.server.password"); - - if (username != null) - { - props.put("mail.smtp.auth", "true"); - SMTPAuthenticator smtpAuthenticator = new SMTPAuthenticator( - username, password); - session = Session.getInstance(props, smtpAuthenticator); - } - else - { - session = Session.getDefaultInstance(props); - } - - // Set extra configuration properties - String extras = ConfigurationManager.getProperty("mail.extraproperties"); - if ((extras != null) && (!"".equals(extras.trim()))) - { - String arguments[] = extras.split(","); - String key, value; - for (String argument : arguments) - { - key = argument.substring(0, argument.indexOf('=')).trim(); - value = argument.substring(argument.indexOf('=') + 1).trim(); - props.put(key, value); - } - } + Session session = new DSpace().getServiceManager(). + getServicesByType(EmailService.class).get(0).getSession(); // Create message MimeMessage message = new MimeMessage(session); @@ -321,9 +280,9 @@ public class Email { message.setSubject(fullSubject); } - + // Add attachments - if (attachments.isEmpty()) + if (attachments.isEmpty() && moreAttachments.isEmpty()) { // If a character set has been specified, or a default exists if (charset != null) @@ -335,25 +294,37 @@ public class Email message.setText(fullMessage); } } - else - { - Multipart multipart = new MimeMultipart(); - // create the first part of the email - BodyPart messageBodyPart = new MimeBodyPart(); - messageBodyPart.setText(fullMessage); - multipart.addBodyPart(messageBodyPart); - - for (Iterator<FileAttachment> iter = attachments.iterator(); iter.hasNext();) - { - FileAttachment f = iter.next(); - // add the file - messageBodyPart = new MimeBodyPart(); - messageBodyPart.setDataHandler(new DataHandler( - new FileDataSource(f.file))); - messageBodyPart.setFileName(f.name); - multipart.addBodyPart(messageBodyPart); - } - message.setContent(multipart); + else{ + Multipart multipart = new MimeMultipart(); + // create the first part of the email + BodyPart messageBodyPart = new MimeBodyPart(); + messageBodyPart.setText(fullMessage); + multipart.addBodyPart(messageBodyPart); + if(!attachments.isEmpty()){ + for (Iterator<FileAttachment> iter = attachments.iterator(); iter.hasNext();) + { + FileAttachment f = iter.next(); + // add the file + messageBodyPart = new MimeBodyPart(); + messageBodyPart.setDataHandler(new DataHandler( + new FileDataSource(f.file))); + messageBodyPart.setFileName(f.name); + multipart.addBodyPart(messageBodyPart); + } + message.setContent(multipart); + } + if(!moreAttachments.isEmpty()){ + for (Iterator<InputStreamAttachment> iter = moreAttachments.iterator(); iter.hasNext();) + { + InputStreamAttachment isa = iter.next(); + // add the stream + messageBodyPart = new MimeBodyPart(); + messageBodyPart.setDataHandler(new DataHandler(new InputStreamDataSource(isa.name,isa.mimetype,isa.is))); + messageBodyPart.setFileName(isa.name); + multipart.addBodyPart(messageBodyPart); + } + message.setContent(multipart); + } } if (replyTo != null) @@ -363,9 +334,127 @@ public class Email message.setReplyTo(replyToAddr); } - Transport.send(message); + if (disabled) + { + StringBuffer text = new StringBuffer( + "Message not sent due to mail.server.disabled:\n"); + + Enumeration<String> headers = message.getAllHeaderLines(); + while (headers.hasMoreElements()) + text.append(headers.nextElement()).append('\n'); + + if (!attachments.isEmpty()) + { + text.append("\nAttachments:\n"); + for (FileAttachment f : attachments) + text.append(f.name).append('\n'); + text.append('\n'); + } + + text.append('\n').append(fullMessage); + + log.info(text); + } + else + Transport.send(message); } + /** + * Get the template for an email message. The message is suitable for + * inserting values using <code>java.text.MessageFormat</code>. + * + * @param emailFile + * full name for the email template, for example "/dspace/config/emails/register". + * + * @return the email object, with the content and subject filled out from + * the template + * + * @throws IOException + * if the template couldn't be found, or there was some other + * error reading the template + */ + public static Email getEmail(String emailFile) + throws IOException + { + String charset = null; + String subject = ""; + StringBuilder contentBuffer = new StringBuilder(); + InputStream is = null; + InputStreamReader ir = null; + BufferedReader reader = null; + try + { + is = new FileInputStream(emailFile); + ir = new InputStreamReader(is, "UTF-8"); + reader = new BufferedReader(ir); + boolean more = true; + while (more) + { + String line = reader.readLine(); + if (line == null) + { + more = false; + } + else if (line.toLowerCase().startsWith("subject:")) + { + subject = line.substring(8).trim(); + } + else if (line.toLowerCase().startsWith("charset:")) + { + charset = line.substring(8).trim(); + } + else if (!line.startsWith("#")) + { + contentBuffer.append(line); + contentBuffer.append("\n"); + } + } + } finally + { + if (reader != null) + { + try { + reader.close(); + } catch (IOException ioe) + { + } + } + if (ir != null) + { + try { + ir.close(); + } catch (IOException ioe) + { + } + } + if (is != null) + { + try { + is.close(); + } catch (IOException ioe) + { + } + } + } + Email email = new Email(); + email.setSubject(subject); + email.setContent(contentBuffer.toString()); + if (charset != null) + { + email.setCharset(charset); + } + return email; + } + /* + * Implementation note: It might be necessary to add a quick utility method + * like "send(to, subject, message)". We'll see how far we get without it - + * having all emails as templates in the config allows customisation and + * internationalisation. + * + * Note that everything is stored and the run in send() so that only send() + * throws a MessagingException. + */ + /** * Test method to send an email to check email server settings * @@ -396,15 +485,21 @@ public class Email System.err.println("\nPlease see the DSpace documentation for assistance.\n"); System.err.println("\n"); System.exit(1); + }catch (IOException e1) { + System.err.println("\nError sending email:"); + System.err.println(" - Error: " + e1); + System.err.println("\nPlease see the DSpace documentation for assistance.\n"); + System.err.println("\n"); + System.exit(1); } System.out.println("\nEmail sent successfully!\n"); } /** * Utility struct class for handling file attachments. - * + * * @author ojd20 - * + * */ private static class FileAttachment { @@ -418,27 +513,62 @@ public class Email String name; } - + /** - * Inner Class for SMTP authentication information + * Utility struct class for handling file attachments. + * + * @author Adán Román Ruiz at arvo.es + * */ - private static class SMTPAuthenticator extends Authenticator + private static class InputStreamAttachment { - // User name - private String name; - - // Password - private String password; - - public SMTPAuthenticator(String n, String p) + public InputStreamAttachment(InputStream is, String name, String mimetype) { - name = n; - password = p; - } - - protected PasswordAuthentication getPasswordAuthentication() - { - return new PasswordAuthentication(name, password); + this.is = is; + this.name = name; + this.mimetype = mimetype; } + + InputStream is; + String mimetype; + String name; } + + /** + * + * @author arnaldo + */ + public class InputStreamDataSource implements DataSource { + private String name; + private String contentType; + private ByteArrayOutputStream baos; + + InputStreamDataSource(String name, String contentType, InputStream inputStream) throws IOException { + this.name = name; + this.contentType = contentType; + baos = new ByteArrayOutputStream(); + int read; + byte[] buff = new byte[256]; + while((read = inputStream.read(buff)) != -1) { + baos.write(buff, 0, read); + } + } + + public String getContentType() { + return contentType; + } + + public InputStream getInputStream() throws IOException { + return new ByteArrayInputStream(baos.toByteArray()); + } + + public String getName() { + return name; + } + + public OutputStream getOutputStream() throws IOException { + throw new IOException("Cannot write to this read-only resource"); + } + } + } diff --git a/dspace-api/src/main/java/org/dspace/ctask/general/MetadataValueLinkChecker.java b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataValueLinkChecker.java index 5c3cf49e65fac3ec3f9420c9c5ac5b1111b672fb..61d244832d3b9a0e5bffc9cf039341e2f7970134 100644 --- a/dspace-api/src/main/java/org/dspace/ctask/general/MetadataValueLinkChecker.java +++ b/dspace-api/src/main/java/org/dspace/ctask/general/MetadataValueLinkChecker.java @@ -17,7 +17,7 @@ import java.util.List; * A link checker that builds upon the BasicLinkChecker to check URLs that * appear in all metadata fields where the field starts with http:// or https:// * - * Of course thi assumes that there is no extra metadata following the URL. + * Of course this assumes that there is no extra metadata following the URL. * * @author Stuart Lewis */ diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java index 5f574c757db89d9609e9462fa9fe4ab6254a9439..dcfff697d1a7ad655d81efe48251d7c147fc54ee 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java +++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverQuery.java @@ -22,6 +22,7 @@ public class DiscoverQuery { private List<String> filterQueries; private int DSpaceObjectFilter = -1; private List<String> fieldPresentQueries; + private boolean spellCheck; private int start = 0; private int maxResults = -1; @@ -264,4 +265,12 @@ public class DiscoverQuery { { this.hitHighlighting.put(hitHighlighting.getField(), hitHighlighting); } + + public boolean isSpellCheck() { + return spellCheck; + } + + public void setSpellCheck(boolean spellCheck) { + this.spellCheck = spellCheck; + } } diff --git a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java index 98a0bfc5542ab64254c71a6d3b202e832742bea0..62389a17c87d5014c36b0b254a56bb509aead78f 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java +++ b/dspace-api/src/main/java/org/dspace/discovery/DiscoverResult.java @@ -27,6 +27,7 @@ public class DiscoverResult { private int maxResults = -1; private int searchTime; private Map<String, DSpaceObjectHighlightResult> highlightedResults; + private String spellCheckQuery; public DiscoverResult() { @@ -150,6 +151,14 @@ public class DiscoverResult { } } + public String getSpellCheckQuery() { + return spellCheckQuery; + } + + public void setSpellCheckQuery(String spellCheckQuery) { + this.spellCheckQuery = spellCheckQuery; + } + public static final class DSpaceObjectHighlightResult { private DSpaceObject dso; diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java index 43819abbc6ede7bedcf154f95caeb1138293c9e7..7e8e7bc614f047423b0ba08cf62816874a49be74 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceImpl.java @@ -7,6 +7,33 @@ */ package org.dspace.discovery; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.sql.SQLException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.TimeZone; +import java.util.TreeMap; +import java.util.Vector; + import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.Transformer; @@ -16,38 +43,56 @@ import org.apache.commons.io.IOUtils; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.time.DateFormatUtils; +import org.apache.commons.validator.routines.UrlValidator; +import org.apache.http.HttpHost; +import org.apache.http.HttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.params.ClientPNames; +import org.apache.http.client.utils.URIBuilder; import org.apache.log4j.Logger; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; +import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.apache.solr.client.solrj.response.FacetField; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.util.ClientUtils; import org.apache.solr.common.SolrDocument; import org.apache.solr.common.SolrDocumentList; import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.common.params.CommonParams; -import org.apache.solr.common.params.FacetParams; -import org.apache.solr.common.params.HighlightParams; -import org.apache.solr.common.params.MoreLikeThisParams; +import org.apache.solr.common.params.*; import org.apache.solr.common.util.NamedList; -import org.dspace.content.*; +import org.dspace.content.Bitstream; +import org.dspace.content.Bundle; import org.dspace.content.Collection; +import org.dspace.content.Community; +import org.dspace.content.DCValue; +import org.dspace.content.DSpaceObject; +import org.dspace.content.Item; +import org.dspace.content.ItemIterator; import org.dspace.content.authority.ChoiceAuthorityManager; import org.dspace.content.authority.Choices; import org.dspace.content.authority.MetadataAuthorityManager; -import org.dspace.core.*; -import org.dspace.discovery.configuration.*; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; +import org.dspace.core.Context; +import org.dspace.core.Email; +import org.dspace.core.I18nUtil; +import org.dspace.core.LogManager; +import org.dspace.discovery.configuration.DiscoveryConfiguration; +import org.dspace.discovery.configuration.DiscoveryConfigurationParameters; +import org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration; +import org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration; +import org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration; +import org.dspace.discovery.configuration.DiscoveryRecentSubmissionsConfiguration; +import org.dspace.discovery.configuration.DiscoverySearchFilter; +import org.dspace.discovery.configuration.DiscoverySearchFilterFacet; +import org.dspace.discovery.configuration.DiscoverySortConfiguration; +import org.dspace.discovery.configuration.DiscoverySortFieldConfiguration; +import org.dspace.discovery.configuration.HierarchicalSidebarFacetConfiguration; import org.dspace.handle.HandleManager; import org.dspace.utils.DSpace; import org.springframework.stereotype.Service; -import java.io.*; -import java.sql.SQLException; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - /** * SolrIndexer contains the methods that index Items and their metadata, * collections, communities, etc. It is meant to either be invoked from the @@ -78,32 +123,44 @@ public class SolrServiceImpl implements SearchService, IndexingService { public static final String FILTER_SEPARATOR = "\n|||\n"; public static final String AUTHORITY_SEPARATOR = "###"; - + public static final String STORE_SEPARATOR = "\n|||\n"; - + public static final String VARIANTS_STORE_SEPARATOR = "###"; /** * Non-Static CommonsHttpSolrServer for processing indexing events. */ - private CommonsHttpSolrServer solr = null; + private HttpSolrServer solr = null; - protected CommonsHttpSolrServer getSolr() throws java.net.MalformedURLException, org.apache.solr.client.solrj.SolrServerException + protected HttpSolrServer getSolr() { if ( solr == null) { - String solrService = new DSpace().getConfigurationService().getProperty("discovery.search.server") ; + String solrService = new DSpace().getConfigurationService().getProperty("discovery.search.server"); - log.debug("Solr URL: " + solrService); - solr = new CommonsHttpSolrServer(solrService); + UrlValidator urlValidator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS); + if (urlValidator.isValid(solrService)) + { + try { + log.debug("Solr URL: " + solrService); + solr = new HttpSolrServer(solrService); - solr.setBaseURL(solrService); + solr.setBaseURL(solrService); - SolrQuery solrQuery = new SolrQuery() - .setQuery("search.resourcetype:2 AND search.resourceid:1"); + SolrQuery solrQuery = new SolrQuery() + .setQuery("search.resourcetype:2 AND search.resourceid:1"); - solr.query(solrQuery); + solr.query(solrQuery); + } catch (SolrServerException e) { + log.error("Error while initialinging solr server", e); + } + } + else + { + log.error("Error while initializing solr, invalid url: " + solrService); + } } return solr; @@ -255,10 +312,12 @@ public class SolrServiceImpl implements SearchService, IndexingService { throws SQLException, IOException { try { - getSolr().deleteByQuery("handle:\""+handle+"\""); - if(commit) - { - getSolr().commit(); + if(getSolr() != null){ + getSolr().deleteByQuery("handle:\"" + handle + "\""); + if(commit) + { + getSolr().commit(); + } } } catch (SolrServerException e) { @@ -326,7 +385,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { try { ItemIterator items = null; try { - for (items = Item.findAllUnfiltered(context); items.hasNext();) + for (items = Item.findAllUnfiltered(context); items.hasNext();) { Item item = items.next(); indexContent(context, item, force); @@ -354,7 +413,10 @@ public class SolrServiceImpl implements SearchService, IndexingService { context.removeCached(community, community.getID()); } - getSolr().commit(); + if(getSolr() != null) + { + getSolr().commit(); + } } catch (Exception e) { @@ -379,6 +441,10 @@ public class SolrServiceImpl implements SearchService, IndexingService { try { + if(getSolr() == null) + { + return; + } if (force) { getSolr().deleteByQuery("search.resourcetype:[2 TO 4]"); @@ -433,6 +499,10 @@ public class SolrServiceImpl implements SearchService, IndexingService { public void optimize() { try { + if(getSolr() == null) + { + return; + } long start = System.currentTimeMillis(); System.out.println("SOLR Search Optimize -- Process Started:"+start); getSolr().optimize(); @@ -459,9 +529,9 @@ public class SolrServiceImpl implements SearchService, IndexingService { String recipient = ConfigurationManager .getProperty("alert.recipient"); - if (recipient != null) + if (StringUtils.isNotBlank(recipient)) { - Email email = ConfigurationManager + Email email = Email .getEmail(I18nUtil.getEmailFilename( Locale.getDefault(), "internal_error")); email.addRecipient(recipient); @@ -516,6 +586,10 @@ public class SolrServiceImpl implements SearchService, IndexingService { QueryResponse rsp; try { + if(getSolr() == null) + { + return false; + } rsp = getSolr().query(query); } catch (SolrServerException e) { @@ -598,7 +672,10 @@ public class SolrServiceImpl implements SearchService, IndexingService { protected void writeDocument(SolrInputDocument doc) throws IOException { try { - getSolr().add(doc); + if(getSolr() != null) + { + getSolr().add(doc); + } } catch (SolrServerException e) { log.error(e.getMessage(), e); @@ -754,7 +831,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { SolrInputDocument doc = buildDocument(Constants.ITEM, item.getID(), handle, locations); - + log.debug("Building Item: " + handle); doc.addField("withdrawn", item.isWithdrawn()); @@ -839,7 +916,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { toProjectionFields.add(projectionFieldsString); } } - + DCValue[] mydc = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); for (DCValue meta : mydc) { @@ -848,7 +925,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { String value = meta.value; - if (value == null) + if (value == null) { continue; } @@ -864,7 +941,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { { continue; } - + String authority = null; String preferedLabel = null; List<String> variants = null; @@ -878,7 +955,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { meta.schema, meta.element, meta.qualifier):Choices.CF_ACCEPTED; - + if (isAuthorityControlled && meta.authority != null && meta.confidence >= minConfidence) { @@ -965,7 +1042,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { } doc.addField(searchFilter.getIndexFieldName(), value); doc.addField(searchFilter.getIndexFieldName() + "_keyword", value); - + if (authority != null && preferedLabel == null) { doc.addField(searchFilter.getIndexFieldName() @@ -1006,7 +1083,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { + AUTHORITY_SEPARATOR + authority); } } - + //Add a dynamic fields for auto complete in search doc.addField(searchFilter.getIndexFieldName() + "_ac", value.toLowerCase() + separator + value); @@ -1024,7 +1101,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { + "_ac", var.toLowerCase() + separator + var); } - } + } if(searchFilter.getFilterType().equals(DiscoverySearchFilterFacet.FILTER_TYPE_FACET)) { @@ -1048,13 +1125,38 @@ public class SolrServiceImpl implements SearchService, IndexingService { if(date != null) { String indexField = searchFilter.getIndexFieldName() + ".year"; - doc.addField(searchFilter.getIndexFieldName() + "_keyword", DateFormatUtils.formatUTC(date, "yyyy")); - doc.addField(indexField, DateFormatUtils.formatUTC(date, "yyyy")); + String yearUTC = DateFormatUtils.formatUTC(date, "yyyy"); + doc.addField(searchFilter.getIndexFieldName() + "_keyword", yearUTC); + // add the year to the autocomplete index + doc.addField(searchFilter.getIndexFieldName() + "_ac", yearUTC); + doc.addField(indexField, yearUTC); + + if (yearUTC.startsWith("0")) + { + doc.addField( + searchFilter.getIndexFieldName() + + "_keyword", + yearUTC.replaceFirst("0*", "")); + // add date without starting zeros for autocomplete e filtering + doc.addField( + searchFilter.getIndexFieldName() + + "_ac", + yearUTC.replaceFirst("0*", "")); + doc.addField( + searchFilter.getIndexFieldName() + + "_ac", + value.replaceFirst("0*", "")); + doc.addField( + searchFilter.getIndexFieldName() + + "_keyword", + value.replaceFirst("0*", "")); + } + //Also save a sort value of this year, this is required for determining the upper & lower bound year of our facet if(doc.getField(indexField + "_sort") == null) { //We can only add one year so take the first one - doc.addField(indexField + "_sort", DateFormatUtils.formatUTC(date, "yyyy")); + doc.addField(indexField + "_sort", yearUTC); } } }else @@ -1140,7 +1242,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { variantsToStore.append(VARIANTS_STORE_SEPARATOR); variantsToStore.append(var); } - } + } doc.addField( field + "_stored", value + STORE_SEPARATOR + preferedLabel @@ -1152,7 +1254,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { + STORE_SEPARATOR + authority + STORE_SEPARATOR + meta.language); } - + if (meta.language != null && !meta.language.trim().equals("")) { String langField = field + "." + meta.language; @@ -1179,9 +1281,9 @@ public class SolrServiceImpl implements SearchService, IndexingService { { handlePrefix = "http://hdl.handle.net/"; } - + doc.addField("publication_grp",values[0].value.replaceFirst(handlePrefix,"") ); - + } else { @@ -1272,7 +1374,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { } catch (RuntimeException e) { log.error("Error while writing item to discovery index: " + handle + " message:"+ e.getMessage(), e); - } + } } /** @@ -1341,6 +1443,14 @@ public class SolrServiceImpl implements SearchService, IndexingService { // Choose the likely date formats based on string length switch (t.length()) { + // case from 1 to 3 go through adding anyone a single 0. Case 4 define + // for all the SimpleDateFormat + case 1: + t = "0" + t; + case 2: + t = "0" + t; + case 3: + t = "0" + t; case 4: dfArr = new SimpleDateFormat[]{new SimpleDateFormat("yyyy")}; break; @@ -1415,8 +1525,8 @@ public class SolrServiceImpl implements SearchService, IndexingService { { return search(context, dso, query, false); } - - public DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery discoveryQuery, boolean includeWithdrawn) throws SearchServiceException { + + public DiscoverResult search(Context context, DSpaceObject dso, DiscoverQuery discoveryQuery, boolean includeUnDiscoverable) throws SearchServiceException { if(dso != null) { if (dso instanceof Community) @@ -1430,14 +1540,17 @@ public class SolrServiceImpl implements SearchService, IndexingService { discoveryQuery.addFilterQueries("handle:" + dso.getHandle()); } } - return search(context, discoveryQuery, includeWithdrawn); + return search(context, discoveryQuery, includeUnDiscoverable); } - public DiscoverResult search(Context context, DiscoverQuery discoveryQuery, boolean includeWithdrawn) throws SearchServiceException { + public DiscoverResult search(Context context, DiscoverQuery discoveryQuery, boolean includeUnDiscoverable) throws SearchServiceException { try { - SolrQuery solrQuery = resolveToSolrQuery(context, discoveryQuery, includeWithdrawn); + if(getSolr() == null){ + return new DiscoverResult(); + } + SolrQuery solrQuery = resolveToSolrQuery(context, discoveryQuery, includeUnDiscoverable); QueryResponse queryResponse = getSolr().query(solrQuery); @@ -1449,7 +1562,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { } } - protected SolrQuery resolveToSolrQuery(Context context, DiscoverQuery discoveryQuery, boolean includeWithdrawn) + protected SolrQuery resolveToSolrQuery(Context context, DiscoverQuery discoveryQuery, boolean includeUnDiscoverable) { SolrQuery solrQuery = new SolrQuery(); @@ -1460,10 +1573,17 @@ public class SolrServiceImpl implements SearchService, IndexingService { } solrQuery.setQuery(query); - - if (!includeWithdrawn) + if(discoveryQuery.isSpellCheck()) + { + solrQuery.setParam(SpellingParams.SPELLCHECK_Q, query); + solrQuery.setParam(SpellingParams.SPELLCHECK_COLLATE, Boolean.TRUE); + solrQuery.setParam("spellcheck", Boolean.TRUE); + } + + if (!includeUnDiscoverable) { solrQuery.addFilterQuery("NOT(withdrawn:true)"); + solrQuery.addFilterQuery("NOT(discoverable:false)"); } for (int i = 0; i < discoveryQuery.getFilterQueries().size(); i++) @@ -1594,6 +1714,11 @@ public class SolrServiceImpl implements SearchService, IndexingService { public InputStream searchJSON(Context context, DiscoverQuery discoveryQuery, String jsonIdentifier) throws SearchServiceException { + if(getSolr() == null) + { + return null; + } + SolrQuery solrQuery = resolveToSolrQuery(context, discoveryQuery, false); //We use json as out output type solrQuery.setParam("json.nl", "map"); @@ -1601,7 +1726,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { solrQuery.setParam(CommonParams.WT, "json"); StringBuilder urlBuilder = new StringBuilder(); - urlBuilder.append(solr.getBaseURL()).append("/select?"); + urlBuilder.append(getSolr().getBaseURL()).append("/select?"); urlBuilder.append(solrQuery.toString()); try { @@ -1615,7 +1740,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { } return null; } - + protected DiscoverResult retrieveResult(Context context, DiscoverQuery query, QueryResponse solrQueryResponse) throws SQLException { DiscoverResult result = new DiscoverResult(); @@ -1709,10 +1834,11 @@ public class SolrServiceImpl implements SearchService, IndexingService { if(solrQueryResponse.getFacetQuery() != null) { - //TODO: do not sort when not a date, just retrieve the facets in the order they where requested ! - //At the moment facet queries are only used for dates so we need to sort our results - TreeMap<String, Integer> sortedFacetQueries = new TreeMap<String, Integer>(solrQueryResponse.getFacetQuery()); - for(String facetQuery : sortedFacetQueries.descendingKeySet()) + // just retrieve the facets in the order they where requested! + // also for the date we ask it in proper (reverse) order + // At the moment facet queries are only used for dates + LinkedHashMap<String, Integer> sortedFacetQueries = new LinkedHashMap<String, Integer>(solrQueryResponse.getFacetQuery()); + for(String facetQuery : sortedFacetQueries.keySet()) { //TODO: do not assume this, people may want to use it for other ends, use a regex to make sure //We have a facet query, the values looks something like: dateissued.year:[1990 TO 2000] AND -2000 @@ -1722,7 +1848,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { name = name.substring(0, name.lastIndexOf(']')).replaceAll("TO", "-"); String filter = facetQuery.substring(facetQuery.indexOf('[')); filter = filter.substring(0, filter.lastIndexOf(']') + 1); - + Integer count = sortedFacetQueries.get(facetQuery); //No need to show empty years @@ -1732,6 +1858,15 @@ public class SolrServiceImpl implements SearchService, IndexingService { } } } + + if(solrQueryResponse.getSpellCheckResponse() != null) + { + String recommendedQuery = solrQueryResponse.getSpellCheckResponse().getCollatedResult(); + if(StringUtils.isNotBlank(recommendedQuery)) + { + result.setSpellCheckQuery(recommendedQuery); + } + } } return result; @@ -1757,21 +1892,25 @@ public class SolrServiceImpl implements SearchService, IndexingService { /** Simple means to return the search result as an InputStream */ public java.io.InputStream searchAsInputStream(DiscoverQuery query) throws SearchServiceException, java.io.IOException { - try { - org.apache.commons.httpclient.methods.GetMethod method = - new org.apache.commons.httpclient.methods.GetMethod(getSolr().getHttpClient().getHostConfiguration().getHostURL() + ""); - - method.setQueryString(query.toString()); - - getSolr().getHttpClient().executeMethod(method); - - return method.getResponseBodyAsStream(); - - } catch (org.apache.solr.client.solrj.SolrServerException e) + if(getSolr() == null) { - throw new SearchServiceException(e.getMessage(), e); + return null; + } + HttpHost hostURL = (HttpHost)(getSolr().getHttpClient().getParams().getParameter(ClientPNames.DEFAULT_HOST)); + + HttpGet method = new HttpGet(hostURL.toHostString() + ""); + try + { + URI uri = new URIBuilder(method.getURI()).addParameter("q",query.toString()).build(); } + catch (URISyntaxException e) + { + throw new SearchServiceException(e); + } + + HttpResponse response = getSolr().getHttpClient().execute(method); + return response.getEntity().getContent(); } public List<DSpaceObject> search(Context context, String query, int offset, int max, String... filterquery) @@ -1783,6 +1922,11 @@ public class SolrServiceImpl implements SearchService, IndexingService { { try { + if(getSolr() == null) + { + return Collections.emptyList(); + } + SolrQuery solrQuery = new SolrQuery(); solrQuery.setQuery(query); solrQuery.setFields("search.resourceid", "search.resourcetype"); @@ -1821,7 +1965,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { return new ArrayList<DSpaceObject>(0); } } - + public DiscoverFilterQuery toFilterQuery(Context context, String field, String operator, String value) throws SQLException{ DiscoverFilterQuery result = new DiscoverFilterQuery(); @@ -1846,15 +1990,24 @@ public class SolrServiceImpl implements SearchService, IndexingService { filterQuery.insert(0, "-"); } filterQuery.append(":"); - if("equals".equals(operator)) + if("equals".equals(operator) || "notequals".equals(operator)) { //DO NOT ESCAPE RANGE QUERIES ! if(!value.matches("\\[.*TO.*\\]")) { value = ClientUtils.escapeQueryChars(value); - + filterQuery.append(value); + } + else + { + if (value.matches("\\[\\d{1,4} TO \\d{1,4}\\]")) + { + int minRange = Integer.parseInt(value.substring(1, value.length()-1).split(" TO ")[0]); + int maxRange = Integer.parseInt(value.substring(1, value.length()-1).split(" TO ")[1]); + value = "["+String.format("%04d", minRange) + " TO "+ String.format("%04d", maxRange) + "]"; + } + filterQuery.append(value); } - filterQuery.append(value); } else{ //DO NOT ESCAPE RANGE QUERIES ! @@ -1862,7 +2015,9 @@ public class SolrServiceImpl implements SearchService, IndexingService { { value = ClientUtils.escapeQueryChars(value); filterQuery.append("(").append(value).append(")"); - }else{ + } + else + { filterQuery.append(value); } } @@ -1902,6 +2057,10 @@ public class SolrServiceImpl implements SearchService, IndexingService { solrQuery.setParam(MoreLikeThisParams.DOC_COUNT, String.valueOf(mltConfig.getMax())); solrQuery.setParam(MoreLikeThisParams.MIN_WORD_LEN, String.valueOf(mltConfig.getMinWordLength())); + if(getSolr() == null) + { + return Collections.emptyList(); + } QueryResponse rsp = getSolr().query(solrQuery); NamedList mltResults = (NamedList) rsp.getResponse().get("moreLikeThis"); if(mltResults != null && mltResults.get(item.getType() + "-" + item.getID()) != null) @@ -1925,7 +2084,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { } return results; } - + @Override public String toSortFieldIndex(String metadataField, String type) { @@ -2020,9 +2179,13 @@ public class SolrServiceImpl implements SearchService, IndexingService { } return value; } - + protected String transformAuthorityValue(Context context, String field, String value) throws SQLException { - if (field.endsWith("_filter") || field.endsWith("_ac") + if(field.equals("location.comm") || field.equals("location.coll")) + { + return value; + } + if (field.endsWith("_filter") || field.endsWith("_ac") || field.endsWith("_acid")) { //We have a filter make sure we split ! @@ -2051,7 +2214,7 @@ public class SolrServiceImpl implements SearchService, IndexingService { } return null; } - + protected String transformSortValue(Context context, String field, String value) throws SQLException { if(field.equals("location.comm") || field.equals("location.coll")) { @@ -2097,7 +2260,10 @@ public class SolrServiceImpl implements SearchService, IndexingService { @Override public void commit() throws SearchServiceException { try { - getSolr().commit(); + if(getSolr() != null) + { + getSolr().commit(); + } } catch (Exception e) { throw new SearchServiceException(e.getMessage(), e); } diff --git a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java index 8dd034d3e796d675079036c3fa15d649b9e34998..9d1e41b4d68ed7e68106dbf0ab4609fb4b1a315a 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java +++ b/dspace-api/src/main/java/org/dspace/discovery/SolrServiceResourceRestrictionPlugin.java @@ -59,32 +59,26 @@ public class SolrServiceResourceRestrictionPlugin implements SolrServiceIndexPlu @Override public void additionalSearchParameters(Context context, DiscoverQuery discoveryQuery, SolrQuery solrQuery) { - StringBuilder resourceQuery = new StringBuilder(); - //Always add the anonymous group id to the query - resourceQuery.append("read:(g0"); - EPerson currentUser = context.getCurrentUser(); - if(currentUser != null){ - try { - resourceQuery.append(" OR e").append(currentUser.getID()); - //Retrieve all the groups the current user is a member of ! - Set<Integer> groupIds = Group.allMemberGroupIDs(context, currentUser); - for (Integer groupId : groupIds) { - resourceQuery.append(" OR g").append(groupId); + try { + if(!AuthorizeManager.isAdmin(context)){ + StringBuilder resourceQuery = new StringBuilder(); + //Always add the anonymous group id to the query + resourceQuery.append("read:(g0"); + EPerson currentUser = context.getCurrentUser(); + if(currentUser != null){ + resourceQuery.append(" OR e").append(currentUser.getID()); + //Retrieve all the groups the current user is a member of ! + Set<Integer> groupIds = Group.allMemberGroupIDs(context, currentUser); + for (Integer groupId : groupIds) { + resourceQuery.append(" OR g").append(groupId); + } } - } catch (SQLException e) { - log.error(LogManager.getHeader(context, "Error while adding resource policy information to query", "") ,e); - } - } - resourceQuery.append(")"); - try { - if(AuthorizeManager.isAdmin(context)){ - //Admins always have read access even if no policies are present ! - resourceQuery.append(" OR (!read[* TO *])"); - + resourceQuery.append(")"); + + solrQuery.addFilterQuery(resourceQuery.toString()); } } catch (SQLException e) { - log.error(LogManager.getHeader(context, "Error while verifying if current user is admin !", ""), e); + log.error(LogManager.getHeader(context, "Error while adding resource policy information to query", ""), e); } - solrQuery.addFilterQuery(resourceQuery.toString()); } } diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfiguration.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfiguration.java index 2b04d055a63a9fc51f7bad9acc01b180e35a6120..aa58addd3ed572c0c4274bb3819eb47130e574e0 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryConfiguration.java @@ -39,6 +39,7 @@ public class DiscoveryConfiguration implements InitializingBean{ private String id; private DiscoveryHitHighlightingConfiguration hitHighlightingConfiguration; private DiscoveryMoreLikeThisConfiguration moreLikeThisConfiguration; + private boolean spellCheckEnabled; public String getId() { return id; @@ -122,6 +123,14 @@ public class DiscoveryConfiguration implements InitializingBean{ return moreLikeThisConfiguration; } + public boolean isSpellCheckEnabled() { + return spellCheckEnabled; + } + + public void setSpellCheckEnabled(boolean spellCheckEnabled) { + this.spellCheckEnabled = spellCheckEnabled; + } + /** * After all the properties are set check that the sidebar facets are a subset of our search filters * diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryRecentSubmissionsConfiguration.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryRecentSubmissionsConfiguration.java index e3bdef5fbddbbdff3be9951db1dd1e7a272d7c76..33b8d9098963926a2b41d4f8211c7837f5ead4e3 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryRecentSubmissionsConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoveryRecentSubmissionsConfiguration.java @@ -18,6 +18,7 @@ public class DiscoveryRecentSubmissionsConfiguration { private String type; private int max = 5; + private boolean useAsHomePage; public String getMetadataSortField() { return metadataSortField; @@ -44,4 +45,12 @@ public class DiscoveryRecentSubmissionsConfiguration { public void setType(String type) { this.type = type; } + + public void setUseAsHomePage(boolean useAsHomePage) { + this.useAsHomePage = useAsHomePage; + } + + public boolean getUseAsHomePage() { + return useAsHomePage; + } } diff --git a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortFieldConfiguration.java b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortFieldConfiguration.java index f312ee9d498b9147b944a23eb40ec66e2690653b..fd55a5258211b692c3522d6d6234732375bb716e 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortFieldConfiguration.java +++ b/dspace-api/src/main/java/org/dspace/discovery/configuration/DiscoverySortFieldConfiguration.java @@ -10,11 +10,7 @@ package org.dspace.discovery.configuration; import org.springframework.beans.factory.annotation.Required; /** - * Created by IntelliJ IDEA. - * User: Kevin - * Date: 28/08/11 - * Time: 14:11 - * To change this template use File | Settings | File Templates. + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class DiscoverySortFieldConfiguration { diff --git a/dspace-api/src/main/java/org/dspace/eperson/AccountManager.java b/dspace-api/src/main/java/org/dspace/eperson/AccountManager.java index 64f54d7c135042fcf51cab5fc954e9a02805205e..95bbd958deea2a822fe824ab3348a911331f20de 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/AccountManager.java +++ b/dspace-api/src/main/java/org/dspace/eperson/AccountManager.java @@ -31,9 +31,9 @@ import org.dspace.storage.rdbms.TableRow; * randomly generated and thus hard to guess. When the user presents the token * back to the system, the AccountManager can use the token to determine the * identity of the eperson. - * + * * *NEW* now ignores expiration dates so that tokens never expire - * + * * @author Peter Breton * @version $Revision$ */ @@ -49,12 +49,12 @@ public class AccountManager /** * Email registration info to the given email address. - * + * * Potential error conditions: Cannot create registration data in database * (throws SQLException) Error sending email (throws MessagingException) * Error reading email template (throws IOException) Authorization error * (throws AuthorizeException) - * + * * @param context * DSpace context * @param email @@ -69,12 +69,12 @@ public class AccountManager /** * Email forgot password info to the given email address. - * + * * Potential error conditions: No EPerson with that email (returns null) * Cannot create registration data in database (throws SQLException) Error * sending email (throws MessagingException) Error reading email template * (throws IOException) Authorization error (throws AuthorizeException) - * + * * @param context * DSpace context * @param email @@ -93,11 +93,11 @@ public class AccountManager * person by either the sendRegistrationInfo or sendForgotPasswordInfo * methods. * </p> - * + * * <p> * If the token is not found return null. * </p> - * + * * @param context * DSpace context * @param token @@ -125,7 +125,7 @@ public class AccountManager /** * Return the e-mail address referred to by a token, or null if email * address can't be found ignores expiration of token - * + * * @param context * DSpace context * @param token @@ -153,7 +153,7 @@ public class AccountManager /** * Delete token. - * + * * @param context * DSpace context * @param token @@ -171,16 +171,16 @@ public class AccountManager /* * THIS IS AN INTERNAL METHOD. THE SEND PARAMETER ALLOWS IT TO BE USED FOR * TESTING PURPOSES. - * + * * Send an info to the EPerson with the given email address. If isRegister * is TRUE, this is registration email; otherwise, it is forgot-password * email. If send is TRUE, the email is sent; otherwise it is skipped. - * + * * Potential error conditions: No EPerson with that email (returns null) * Cannot create registration data in database (throws SQLException) Error * sending email (throws MessagingException) Error reading email template * (throws IOException) Authorization error (throws AuthorizeException) - * + * * @param context DSpace context @param email Email address to send the * forgot-password email to @param isRegister If true, this is for * registration; otherwise, it is for forgot-password @param send If true, @@ -227,10 +227,10 @@ public class AccountManager /** * Send a DSpace message to the given email address. - * + * * If isRegister is <code>true</code>, this is registration email; * otherwise, it is a forgot-password email. - * + * * @param email * The email address to mail to * @param isRegister @@ -255,7 +255,7 @@ public class AccountManager .append("token=").append(rd.getStringColumn("token")) .toString(); Locale locale = context.getCurrentLocale(); - Email bean = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(locale, isRegister ? "register" + Email bean = Email.getEmail(I18nUtil.getEmailFilename(locale, isRegister ? "register" : "change_password")); bean.addRecipient(email); bean.addArgument(specialLink); diff --git a/dspace-api/src/main/java/org/dspace/eperson/EPerson.java b/dspace-api/src/main/java/org/dspace/eperson/EPerson.java index 6800f065ef699cd308e87a49fd2b382f04e9adfa..b2233751fe10ce7dc340f68256f9fc7451987363 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/EPerson.java +++ b/dspace-api/src/main/java/org/dspace/eperson/EPerson.java @@ -9,7 +9,17 @@ package org.dspace.eperson; import java.sql.SQLException; import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.Locale; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.CommandLineParser; +import org.apache.commons.cli.GnuParser; +import org.apache.commons.cli.Option; +import org.apache.commons.cli.OptionGroup; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.apache.commons.cli.HelpFormatter; import org.apache.commons.codec.DecoderException; import org.apache.log4j.Logger; @@ -811,7 +821,7 @@ public class EPerson extends DSpaceObject } /** - * Can the user log in? + * Is the user self-registered? * * @return boolean, yes/no (or false if the column is an SQL NULL) */ @@ -895,7 +905,7 @@ public class EPerson extends DSpaceObject /** * Return the EPerson's password hash. * - * @return hash of the password + * @return hash of the password, or null on failure (such as no password). */ public PasswordHash getPasswordHash() { @@ -954,6 +964,26 @@ public class EPerson extends DSpaceObject return answer; } + /** + * Stamp the EPerson's last-active date. + * + * @param when latest activity timestamp, or null to clear. + */ + public void setLastActive(Date when) + { + myRow.setColumn("last_active", when); + } + + /** + * Get the EPerson's last-active stamp. + * + * @return date when last logged on, or null. + */ + public Date getLastActive() + { + return myRow.getDateColumn("last_active"); + } + /** * Update the EPerson */ @@ -1152,6 +1182,7 @@ public class EPerson extends DSpaceObject } } + @Override public String getName() { return getEmail(); @@ -1163,4 +1194,415 @@ public class EPerson extends DSpaceObject } + /* + * Commandline tool for manipulating EPersons. + */ + + private static final Option VERB_ADD = new Option("a", "add", false, "create a new EPerson"); + private static final Option VERB_DELETE = new Option("d", "delete", false, "delete an existing EPerson"); + private static final Option VERB_LIST = new Option("L", "list", false, "list EPersons"); + private static final Option VERB_MODIFY = new Option("M", "modify", false, "modify an EPerson"); + + private static final Option OPT_GIVENNAME = new Option("g", "givenname", true, "the person's actual first or personal name"); + private static final Option OPT_SURNAME = new Option("s", "surname", true, "the person's actual last or family name"); + private static final Option OPT_PHONE = new Option("t", "telephone", true, "telephone number, empty for none"); + private static final Option OPT_LANGUAGE = new Option("l", "language", true, "the person's preferred language"); + private static final Option OPT_REQUIRE_CERTIFICATE = new Option("c", "requireCertificate", true, "if 'true', an X.509 certificate will be required for login"); + private static final Option OPT_CAN_LOGIN = new Option("C", "canLogIn", true, "'true' if the user can log in"); + + private static final Option OPT_EMAIL = new Option("m", "email", true, "the user's email address, empty for none"); + private static final Option OPT_NETID = new Option("n", "netid", true, "network ID associated with the person, empty for none"); + + private static final Option OPT_NEW_EMAIL = new Option("i", "newEmail", true, "new email address"); + private static final Option OPT_NEW_NETID = new Option("I", "newNetid", true, "new network ID"); + + /** + * Tool for manipulating user accounts. + */ + public static void main(String argv[]) + throws ParseException, SQLException + { + final OptionGroup VERBS = new OptionGroup(); + VERBS.addOption(VERB_ADD); + VERBS.addOption(VERB_DELETE); + VERBS.addOption(VERB_LIST); + VERBS.addOption(VERB_MODIFY); + + final Options globalOptions = new Options(); + globalOptions.addOptionGroup(VERBS); + globalOptions.addOption("h", "help", false, "explain options"); + + GnuParser parser = new GnuParser(); + CommandLine command = parser.parse(globalOptions, argv, true); + + Context context = new Context(); + + // Disable authorization since this only runs from the local commandline. + context.turnOffAuthorisationSystem(); + + int status = 0; + if (command.hasOption(VERB_ADD.getOpt())) + { + status = cmdAdd(context, argv); + } + else if (command.hasOption(VERB_DELETE.getOpt())) + { + status = cmdDelete(context, argv); + } + else if (command.hasOption(VERB_MODIFY.getOpt())) + { + status = cmdModify(context, argv); + } + else if (command.hasOption(VERB_LIST.getOpt())) + { + status = cmdList(context, argv); + } + else if (command.hasOption('h')) + { + new HelpFormatter().printHelp("user [options]", globalOptions); + } + else + { + System.err.println("Unknown operation."); + new HelpFormatter().printHelp("user [options]", globalOptions); + context.abort(); + status = 1; + throw new IllegalArgumentException(); + } + + if (context.isValid()) + { + try { + context.complete(); + } catch (SQLException ex) { + System.err.println(ex.getMessage()); + } + } + } + + /** Command to create an EPerson. */ + private static int cmdAdd(Context context, String[] argv) + { + Options options = new Options(); + + options.addOption(VERB_ADD); + + final OptionGroup identityOptions = new OptionGroup(); + identityOptions.addOption(OPT_EMAIL); + identityOptions.addOption(OPT_NETID); + + options.addOptionGroup(identityOptions); + + options.addOption(OPT_GIVENNAME); + options.addOption(OPT_SURNAME); + options.addOption(OPT_PHONE); + options.addOption(OPT_LANGUAGE); + options.addOption(OPT_REQUIRE_CERTIFICATE); + + Option option = new Option("p", "password", true, "password to match the EPerson name"); + options.addOption(option); + + options.addOption("h", "help", false, "explain --add options"); + + // Rescan the command for more details. + GnuParser parser = new GnuParser(); + CommandLine command; + try { + command = parser.parse(options, argv); + } catch (ParseException e) { + System.err.println(e.getMessage()); + return 1; + } + + if (command.hasOption('h')) + { + new HelpFormatter().printHelp("user --add [options]", options); + return 0; + } + + // Check that we got sufficient credentials to define a user. + if ((!command.hasOption(OPT_EMAIL.getOpt())) && (!command.hasOption(OPT_NETID.getOpt()))) + { + System.err.println("You must provide an email address or a netid to identify the new user."); + return 1; + } + + if (!command.hasOption('p')) + { + System.err.println("You must provide a password for the new user."); + return 1; + } + + // Create! + EPerson eperson = null; + try { + eperson = create(context); + } catch (SQLException ex) { + context.abort(); + System.err.println(ex.getMessage()); + return 1; + } catch (AuthorizeException ex) { /* XXX SNH */ } + eperson.setCanLogIn(true); + eperson.setSelfRegistered(false); + + eperson.setEmail(command.getOptionValue(OPT_EMAIL.getOpt())); + eperson.setFirstName(command.getOptionValue(OPT_GIVENNAME.getOpt())); + eperson.setLastName(command.getOptionValue(OPT_SURNAME.getOpt())); + eperson.setLanguage(command.getOptionValue(OPT_LANGUAGE.getOpt(), + Locale.getDefault().getLanguage())); + eperson.setMetadata("phone", command.getOptionValue(OPT_PHONE.getOpt())); + eperson.setNetid(command.getOptionValue(OPT_NETID.getOpt())); + eperson.setPassword(command.getOptionValue('p')); + if (command.hasOption(OPT_REQUIRE_CERTIFICATE.getOpt())) + { + eperson.setRequireCertificate(Boolean.valueOf(command.getOptionValue( + OPT_REQUIRE_CERTIFICATE.getOpt()))); + } + else + { + eperson.setRequireCertificate(false); + } + + try { + eperson.update(); + context.commit(); + System.out.printf("Created EPerson %d\n", eperson.getID()); + } catch (SQLException ex) { + context.abort(); + System.err.println(ex.getMessage()); + return 1; + } catch (AuthorizeException ex) { /* XXX SNH */ } + + return 0; + } + + /** Command to delete an EPerson. */ + private static int cmdDelete(Context context, String[] argv) + { + Options options = new Options(); + + options.addOption(VERB_DELETE); + + final OptionGroup identityOptions = new OptionGroup(); + identityOptions.addOption(OPT_EMAIL); + identityOptions.addOption(OPT_NETID); + + options.addOptionGroup(identityOptions); + + options.addOption("h", "help", false, "explain --delete options"); + + GnuParser parser = new GnuParser(); + CommandLine command; + try { + command = parser.parse(options, argv); + } catch (ParseException e) { + System.err.println(e.getMessage()); + return 1; + } + + if (command.hasOption('h')) + { + new HelpFormatter().printHelp("user --delete [options]", options); + return 0; + } + + // Delete! + EPerson eperson = null; + try { + if (command.hasOption(OPT_NETID.getOpt())) + { + eperson = findByNetid(context, command.getOptionValue(OPT_NETID.getOpt())); + } + else if (command.hasOption(OPT_EMAIL.getOpt())) + { + eperson = findByEmail(context, command.getOptionValue(OPT_EMAIL.getOpt())); + } + else + { + System.err.println("You must specify the user's email address or netid."); + return 1; + } + } catch (SQLException e) { + System.err.append(e.getMessage()); + return 1; + } catch (AuthorizeException e) { /* XXX SNH */ } + + if (null == eperson) + { + System.err.println("No such EPerson"); + return 1; + } + + try { + eperson.delete(); + context.commit(); + System.out.printf("Deleted EPerson %d\n", eperson.getID()); + } catch (SQLException ex) { + System.err.println(ex.getMessage()); + return 1; + } catch (AuthorizeException ex) { + System.err.println(ex.getMessage()); + return 1; + } catch (EPersonDeletionException ex) { + System.err.println(ex.getMessage()); + return 1; + } + + return 0; + } + + /** Command to modify an EPerson. */ + private static int cmdModify(Context context, String[] argv) + { + Options options = new Options(); + + options.addOption(VERB_MODIFY); + + final OptionGroup identityOptions = new OptionGroup(); + identityOptions.addOption(OPT_EMAIL); + identityOptions.addOption(OPT_NETID); + + options.addOptionGroup(identityOptions); + + options.addOption(OPT_GIVENNAME); + options.addOption(OPT_SURNAME); + options.addOption(OPT_PHONE); + options.addOption(OPT_LANGUAGE); + options.addOption(OPT_REQUIRE_CERTIFICATE); + + options.addOption(OPT_CAN_LOGIN); + options.addOption(OPT_NEW_EMAIL); + options.addOption(OPT_NEW_NETID); + + options.addOption("h", "help", false, "explain --modify options"); + + GnuParser parser = new GnuParser(); + CommandLine command; + try { + command = parser.parse(options, argv); + } catch (ParseException e) { + System.err.println(e.getMessage()); + return 1; + } + + if (command.hasOption('h')) + { + new HelpFormatter().printHelp("user --modify [options]", options); + return 0; + } + + // Modify! + EPerson eperson = null; + try { + if (command.hasOption(OPT_NETID.getOpt())) + { + eperson = findByNetid(context, command.getOptionValue(OPT_NETID.getOpt())); + } + else if (command.hasOption(OPT_EMAIL.getOpt())) + { + eperson = findByEmail(context, command.getOptionValue(OPT_EMAIL.getOpt())); + } + else + { + System.err.println("No EPerson selected"); + return 1; + } + } catch (SQLException e) { + System.err.append(e.getMessage()); + return 1; + } catch (AuthorizeException e) { /* XXX SNH */ } + + boolean modified = false; + if (null == eperson) + { + System.err.println("No such EPerson"); + return 1; + } + else + { + if (command.hasOption(OPT_NEW_EMAIL.getOpt())) + { + eperson.setEmail(command.getOptionValue(OPT_NEW_EMAIL.getOpt())); + modified = true; + } + if (command.hasOption(OPT_NEW_NETID.getOpt())) + { + eperson.setNetid(command.getOptionValue(OPT_NEW_NETID.getOpt())); + modified = true; + } + if (command.hasOption(OPT_GIVENNAME.getOpt())) + { + eperson.setFirstName(command.getOptionValue(OPT_GIVENNAME.getOpt())); + modified = true; + } + if (command.hasOption(OPT_SURNAME.getOpt())) + { + eperson.setLastName(command.getOptionValue(OPT_SURNAME.getOpt())); + modified = true; + } + if (command.hasOption(OPT_PHONE.getOpt())) + { + eperson.setMetadata("phone", command.getOptionValue(OPT_PHONE.getOpt())); + modified = true; + } + if (command.hasOption(OPT_LANGUAGE.getOpt())) + { + eperson.setLanguage(command.getOptionValue(OPT_LANGUAGE.getOpt())); + modified = true; + } + if (command.hasOption(OPT_REQUIRE_CERTIFICATE.getOpt())) + { + eperson.setRequireCertificate(Boolean.valueOf(command.getOptionValue( + OPT_REQUIRE_CERTIFICATE.getOpt()))); + modified = true; + } + if (command.hasOption(OPT_CAN_LOGIN.getOpt())) + { + eperson.setCanLogIn(Boolean.valueOf(command.getOptionValue(OPT_CAN_LOGIN.getOpt()))); + modified = true; + } + if (modified) + { + try { + eperson.update(); + context.commit(); + System.out.printf("Modified EPerson %d\n", eperson.getID()); + } catch (SQLException ex) { + context.abort(); + System.err.println(ex.getMessage()); + return 1; + } catch (AuthorizeException ex) { /* XXX SNH */ } + } + else + { + System.out.println("No changes."); + } + } + + return 0; + } + + /** Command to list known EPersons. */ + private static int cmdList(Context context, String[] argv) + { + // XXX ideas: + // specific user/netid + // wild or regex match user/netid + // select details (pseudo-format string) + try { + for (EPerson person : findAll(context, EMAIL)) + { + System.out.printf("%d\t%s/%s\t%s, %s\n", + person.getID(), + person.getEmail(), + person.getNetid(), + person.getLastName(), person.getFirstName()); // TODO more user details + } + } catch (SQLException ex) { + System.err.println(ex.getMessage()); + return 1; + } + + return 0; + } } diff --git a/dspace-api/src/main/java/org/dspace/eperson/EPersonConsumer.java b/dspace-api/src/main/java/org/dspace/eperson/EPersonConsumer.java index 44ec870f074da65c2457fbc762e98c34b217ba49..fd6738f8e2fa12b63b81f5bc66e8bcca54032c19 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/EPersonConsumer.java +++ b/dspace-api/src/main/java/org/dspace/eperson/EPersonConsumer.java @@ -72,7 +72,7 @@ public class EPersonConsumer implements Consumer try { EPerson eperson = EPerson.find(context, id); - Email adminEmail = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "registration_notify")); + Email adminEmail = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "registration_notify")); adminEmail.addRecipient(notifyRecipient); adminEmail.addArgument(ConfigurationManager.getProperty("dspace.name")); @@ -80,7 +80,7 @@ public class EPersonConsumer implements Consumer adminEmail.addArgument(eperson.getFirstName() + " " + eperson.getLastName()); // Name adminEmail.addArgument(eperson.getEmail()); adminEmail.addArgument(new Date()); - + adminEmail.setReplyTo(eperson.getEmail()); adminEmail.send(); diff --git a/dspace-api/src/main/java/org/dspace/eperson/Subscribe.java b/dspace-api/src/main/java/org/dspace/eperson/Subscribe.java index 3e01a44a64993e3b9188cf34529d19c2cc7e6c0f..ea1b61a4301712d6f0a1ec00e1473b34d68c9f95 100644 --- a/dspace-api/src/main/java/org/dspace/eperson/Subscribe.java +++ b/dspace-api/src/main/java/org/dspace/eperson/Subscribe.java @@ -34,7 +34,9 @@ import org.dspace.content.Collection; import org.dspace.content.DCDate; import org.dspace.content.DCValue; import org.dspace.content.Item; +import org.dspace.content.Site; import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.Email; import org.dspace.core.I18nUtil; @@ -48,7 +50,7 @@ import org.dspace.storage.rdbms.TableRowIterator; /** * Class defining methods for sending new item e-mail alerts to users - * + * * @author Robert Tansley * @version $Revision$ */ @@ -60,7 +62,7 @@ public class Subscribe /** * Subscribe an e-person to a collection. An e-mail will be sent every day a * new item appears in the collection. - * + * * @param context * DSpace context * @param eperson @@ -76,10 +78,10 @@ public class Subscribe || ((context.getCurrentUser() != null) && (context .getCurrentUser().getID() == eperson.getID()))) { - // already subscribed? + // already subscribed? TableRowIterator r = DatabaseManager.query(context, "SELECT * FROM subscription WHERE eperson_id= ? " + - " AND collection_id= ? ", + " AND collection_id= ? ", eperson.getID(),collection.getID()); try @@ -117,7 +119,7 @@ public class Subscribe * Unsubscribe an e-person to a collection. Passing in <code>null</code> * for the collection unsubscribes the e-person from all collections they * are subscribed to. - * + * * @param context * DSpace context * @param eperson @@ -141,10 +143,10 @@ public class Subscribe eperson.getID()); } else - { + { DatabaseManager.updateQuery(context, "DELETE FROM subscription WHERE eperson_id= ? " + - "AND collection_id= ? ", + "AND collection_id= ? ", eperson.getID(),collection.getID()); log.info(LogManager.getHeader(context, "unsubscribe", @@ -161,7 +163,7 @@ public class Subscribe /** * Find out which collections an e-person is subscribed to - * + * * @param context * DSpace context * @param eperson @@ -195,15 +197,56 @@ public class Subscribe tri.close(); } } - + Collection[] collArray = new Collection[collections.size()]; return (Collection[]) collections.toArray(collArray); } + /** + * Find out which collections the currently logged in e-person can subscribe to + * + * @param context + * DSpace context + * @param eperson + * EPerson + * @return array of collections the currently logged in e-person can subscribe to + */ + public static Collection[] getAvailableSubscriptions(Context context) + throws SQLException + { + return getAvailableSubscriptions(context, null); + } + + /** + * Find out which collections an e-person can subscribe to + * + * @param context + * DSpace context + * @param eperson + * EPerson + * @return array of collections e-person can subscribe to + */ + public static Collection[] getAvailableSubscriptions(Context context, EPerson eperson) + throws SQLException + { + Collection[] collections; + + if (eperson != null) + { + context.setCurrentUser(eperson); + } + + Site site = (Site) Site.find(context, 0); + + collections = Collection.findAuthorized(context, null, Constants.ADD); + + return collections; + } + /** * Is that e-person subscribed to that collection? - * + * * @param context * DSpace context * @param eperson @@ -217,7 +260,7 @@ public class Subscribe { TableRowIterator tri = DatabaseManager.query(context, "SELECT * FROM subscription WHERE eperson_id= ? " + - "AND collection_id= ? ", + "AND collection_id= ? ", eperson.getID(),collection.getID()); try @@ -246,10 +289,10 @@ public class Subscribe * <P> * For example, if today's date is 2002-10-10 (in UTC) items made available * during 2002-10-09 (UTC) will be included. - * + * * @param context * DSpace context object - * @param test + * @param test */ public static void processDaily(Context context, boolean test) throws SQLException, IOException @@ -306,7 +349,7 @@ public class Subscribe tri.close(); } } - + // Process the last person if (currentEPerson != null) { @@ -327,36 +370,36 @@ public class Subscribe * Sends an email to the given e-person with details of new items in the * given collections, items that appeared yesterday. No e-mail is sent if * there aren't any new items in any of the collections. - * + * * @param context * DSpace context object * @param eperson * eperson to send to * @param collections * List of collection IDs (Integers) - * @param test + * @param test */ public static void sendEmail(Context context, EPerson eperson, List<Collection> collections, boolean test) throws IOException, MessagingException, SQLException { // Get a resource bundle according to the eperson language preferences - Locale supportedLocale = I18nUtil.getEPersonLocale(eperson); + Locale supportedLocale = I18nUtil.getEPersonLocale(eperson); ResourceBundle labels = ResourceBundle.getBundle("Messages", supportedLocale); - + // Get the start and end dates for yesterday - // The date should reflect the timezone as well. Otherwise we stand to lose that information + // The date should reflect the timezone as well. Otherwise we stand to lose that information // in truncation and roll to an earlier date than intended. Calendar cal = Calendar.getInstance(TimeZone.getDefault()); cal.setTime(new Date()); - + // What we actually want to pass to Harvest is "Midnight of yesterday in my current timezone" // Truncation will actually pass in "Midnight of yesterday in UTC", which will be, // at least in CDT, "7pm, the day before yesterday, in my current timezone". cal.add(Calendar.HOUR, -24); Date thisTimeYesterday = cal.getTime(); - + cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); @@ -374,7 +417,7 @@ public class Subscribe try { boolean includeAll = ConfigurationManager.getBooleanProperty("harvest.includerestricted.subscription", true); - + // we harvest all the changed item from yesterday until now List<HarvestedItemInfo> itemInfos = Harvest.harvest(context, c, new DCDate(midnightYesterday).toString(), null, 0, // Limit // and @@ -386,7 +429,7 @@ public class Subscribe false, // But not containers false, // Or withdrawals includeAll); - + if (ConfigurationManager.getBooleanProperty("eperson.subscription.onlynew", false)) { // get only the items archived yesterday @@ -394,7 +437,7 @@ public class Subscribe } else { - // strip out the item archived today or + // strip out the item archived today or // not archived yesterday and modified today itemInfos = filterOutToday(itemInfos); } @@ -411,19 +454,19 @@ public class Subscribe { isFirst = false; } - + emailText.append(labels.getString("org.dspace.eperson.Subscribe.new-items")).append(" ").append( c.getMetadata("name")).append(": ").append( itemInfos.size()).append("\n\n"); - + for (int j = 0; j < itemInfos.size(); j++) { HarvestedItemInfo hii = (HarvestedItemInfo) itemInfos .get(j); - + DCValue[] titles = hii.item.getDC("title", null, Item.ANY); emailText.append(" ").append(labels.getString("org.dspace.eperson.Subscribe.title")).append(" "); - + if (titles.length > 0) { emailText.append(titles[0].value); @@ -432,22 +475,22 @@ public class Subscribe { emailText.append(labels.getString("org.dspace.eperson.Subscribe.untitled")); } - + DCValue[] authors = hii.item.getDC("contributor", Item.ANY, Item.ANY); - + if (authors.length > 0) { emailText.append("\n ").append(labels.getString("org.dspace.eperson.Subscribe.authors")).append(" ").append( authors[0].value); - + for (int k = 1; k < authors.length; k++) { emailText.append("\n ").append( authors[k].value); } } - + emailText.append("\n ").append(labels.getString("org.dspace.eperson.Subscribe.id")).append(" ").append( HandleManager.getCanonicalForm(hii.handle)).append( "\n\n"); @@ -463,47 +506,47 @@ public class Subscribe // Send an e-mail if there were any new items if (emailText.length() > 0) { - + if(test) { log.info(LogManager.getHeader(context, "subscription:", "eperson=" + eperson.getEmail() )); log.info(LogManager.getHeader(context, "subscription:", "text=" + emailText.toString() )); } else { - - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(supportedLocale, "subscription")); + + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "subscription")); email.addRecipient(eperson.getEmail()); email.addArgument(emailText.toString()); email.send(); - + log.info(LogManager.getHeader(context, "sent_subscription", "eperson_id=" + eperson.getID() )); - + } - + } } /** * Method for invoking subscriptions via the command line - * + * * @param argv * command-line arguments, none used yet */ - public static void main(String[] argv) + public static void main(String[] argv) { String usage = "org.dspace.eperson.Subscribe [-t] or nothing to send out subscriptions."; - + Options options = new Options(); HelpFormatter formatter = new HelpFormatter(); CommandLine line = null; - + { Option opt = new Option("t", "test", false, "Run test session"); opt.setRequired(false); options.addOption(opt); } - + { Option opt = new Option("h", "help", false, "Print this help message"); opt.setRequired(false); @@ -527,14 +570,14 @@ public class Subscribe formatter.printHelp(usage, options); System.exit(1); } - + boolean test = line.hasOption("t"); if(test) { log.setLevel(Level.DEBUG); } - + Context context = null; try @@ -556,7 +599,7 @@ public class Subscribe } } } - + private static List<HarvestedItemInfo> filterOutToday(List<HarvestedItemInfo> completeList) { log.debug("Filtering out all today item to leave new items list size=" @@ -614,7 +657,7 @@ public class Subscribe } else { - // the item has been modified yesterday... + // the item has been modified yesterday... filteredList.add(infoObject); } } @@ -632,11 +675,11 @@ public class Subscribe Date thisTimeYesterday = new Date(System.currentTimeMillis() - (24 * 60 * 60 * 1000)); String yesterday = sdf.format(thisTimeYesterday); - + for (HarvestedItemInfo infoObject : completeList) { DCValue[] dateAccArr = infoObject.item.getMetadata("dc", "date", "accessioned", Item.ANY); - + if (dateAccArr != null && dateAccArr.length > 0) { for(DCValue date : dateAccArr) @@ -656,9 +699,9 @@ public class Subscribe } } } - - + + } else { diff --git a/dspace-api/src/main/java/org/dspace/handle/HandleManager.java b/dspace-api/src/main/java/org/dspace/handle/HandleManager.java index 60c4dfe32a2149d2db5776395310ba1bfa22a27f..dc09a83f50dc76078d213651b341ecfa979139e7 100644 --- a/dspace-api/src/main/java/org/dspace/handle/HandleManager.java +++ b/dspace-api/src/main/java/org/dspace/handle/HandleManager.java @@ -84,6 +84,48 @@ public class HandleManager return url; } + + /** + * Try to detect a handle in a URL. + * @param context DSpace context + * @param url The URL + * @return The handle or null if the handle couldn't be extracted of a URL + * or if the extracted handle couldn't be found. + * @throws SQLException If a database error occurs + */ + public static String resolveUrlToHandle(Context context, String url) + throws SQLException + { + String dspaceUrl = ConfigurationManager.getProperty("dspace.url") + + "/handle/"; + String handleResolver = ConfigurationManager.getProperty("handle.canonical.prefix"); + + String handle = null; + + if (url.startsWith(dspaceUrl)) + { + handle = url.substring(dspaceUrl.length()); + } + + if (url.startsWith(handleResolver)) + { + handle = url.substring(handleResolver.length()); + } + + if (null == handle) + { + return null; + } + + // remove trailing slashes + while (handle.startsWith("/")) + { + handle = handle.substring(1); + } + TableRow dbhandle = findHandleInternal(context, handle); + + return (null == dbhandle) ? null : handle; + } /** * Transforms handle into the canonical form <em>hdl:handle</em>. @@ -403,7 +445,7 @@ public class HandleManager * @exception SQLException * If a database error occurs */ - static List<String> getHandlesForPrefix(Context context, String prefix) + public static List<String> getHandlesForPrefix(Context context, String prefix) throws SQLException { String sql = "SELECT handle FROM handle WHERE handle LIKE ? "; diff --git a/dspace-api/src/main/java/org/dspace/harvest/OAIHarvester.java b/dspace-api/src/main/java/org/dspace/harvest/OAIHarvester.java index a7b325677b18f1f01c9c80fb12736c26067d9994..a2d1ea72de502587f0416b72002e67f64f08fd3b 100644 --- a/dspace-api/src/main/java/org/dspace/harvest/OAIHarvester.java +++ b/dspace-api/src/main/java/org/dspace/harvest/OAIHarvester.java @@ -29,6 +29,8 @@ import java.util.TimeZone; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; +import ORG.oclc.oai.harvester2.verb.*; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; @@ -63,111 +65,101 @@ import org.jdom.input.DOMBuilder; import org.jdom.output.XMLOutputter; import org.xml.sax.SAXException; -import ORG.oclc.oai.harvester2.verb.GetRecord; -import ORG.oclc.oai.harvester2.verb.Identify; -import ORG.oclc.oai.harvester2.verb.ListMetadataFormats; -import ORG.oclc.oai.harvester2.verb.ListRecords; -import ORG.oclc.oai.harvester2.verb.ListSets; - /** - * This class handles OAI harvesting of externally located records into this repository. - * + * This class handles OAI harvesting of externally located records into this repository. + * * @author Alexey Maslov */ public class OAIHarvester { - + /* The main harvesting thread */ private static HarvestScheduler harvester; private static Thread mainHarvestThread; - + /** log4j category */ private static Logger log = Logger.getLogger(OAIHarvester.class); - + private static final Namespace ATOM_NS = Namespace.getNamespace("http://www.w3.org/2005/Atom"); private static final Namespace ORE_NS = Namespace.getNamespace("http://www.openarchives.org/ore/terms/"); private static final Namespace OAI_NS = Namespace.getNamespace("http://www.openarchives.org/OAI/2.0/"); - + public static final String OAI_ADDRESS_ERROR = "invalidAddress"; public static final String OAI_SET_ERROR = "noSuchSet"; public static final String OAI_DMD_ERROR = "metadataNotSupported"; public static final String OAI_ORE_ERROR = "oreNotSupported"; - - + + // The collection this harvester instance is dealing with Collection targetCollection; HarvestedCollection harvestRow; - + // our context Context ourContext; - + // Namespace used by the ORE serialization format // Set in dspace.cfg as harvester.oai.oreSerializationFormat.{ORESerialKey} = {ORESerialNS} private Namespace ORESerialNS; private String ORESerialKey; - + // Namespace of the descriptive metadata that should be harvested in addition to the ORE // Set in dspace.cfg as harvester.oai.metadataformats.{MetadataKey} = {MetadataNS},{Display Name} private Namespace metadataNS; - private String metadataKey; - + private String metadataKey; + // DOMbuilder class for the DOM -> JDOM conversions private static DOMBuilder db = new DOMBuilder(); - + // The point at which this thread should terminate itself /* Initialize the harvester with a collection object */ - public OAIHarvester(Context c, DSpaceObject dso, HarvestedCollection hc) throws HarvestingException, SQLException + public OAIHarvester(Context c, DSpaceObject dso, HarvestedCollection hc) throws HarvestingException, SQLException { if (dso.getType() != Constants.COLLECTION) { throw new HarvestingException("OAIHarvester can only harvest collections"); } - + ourContext = c; targetCollection = (Collection)dso; - + harvestRow = hc; if (harvestRow == null || !harvestRow.isHarvestable()) { throw new HarvestingException("Provided collection is not set up for harvesting"); } - + // Set the ORE options Namespace ORESerializationNamespace = OAIHarvester.getORENamespace(); - - if (ORESerializationNamespace == null) { - log.error("No ORE serialization namespace declared; see dspace.cfg option \"harvester.oai.oreSerializationFormat.{ORESerialKey} = {ORESerialNS}\""); - throw new HarvestingException("No ORE serialization namespace specified"); - } else { - ORESerialNS = Namespace.getNamespace(ORESerializationNamespace.getURI()); - ORESerialKey = ORESerializationNamespace.getPrefix(); - } - + + //No need to worry about ORESerializationNamespace, this can never be null + ORESerialNS = Namespace.getNamespace(ORESerializationNamespace.getURI()); + ORESerialKey = ORESerializationNamespace.getPrefix(); + // Set the metadata options metadataKey = harvestRow.getHarvestMetadataConfig(); metadataNS = OAIHarvester.getDMDNamespace(metadataKey); - + if (metadataNS == null) { log.error("No matching metadata namespace found for \"" + metadataKey + "\", see oai.cfg option \"harvester.oai.metadataformats.{MetadataKey} = {MetadataNS},{Display Name}\""); throw new HarvestingException("Metadata declaration not found"); - } + } } - - + + /** - * Search the configuration options and find the ORE serializaition string - * @return Namespace of the supported ORE format. Returns null if not found. + * Search the configuration options and find the ORE serialization string + * @return Namespace of the supported ORE format. Returns null if not found. */ private static Namespace getORENamespace() { String ORESerializationString = null; String ORESeialKey = null; String oreString = "harvester.oai.oreSerializationFormat."; - + Enumeration pe = ConfigurationManager.propertyNames("oai"); - + while (pe.hasMoreElements()) { String key = (String)pe.nextElement(); @@ -178,27 +170,27 @@ public class OAIHarvester { return Namespace.getNamespace(ORESeialKey, ORESerializationString); } } - + // Fallback if the configuration option is not present return Namespace.getNamespace("ore", ATOM_NS.getURI()); } - + /** * Cycle through the options and find the metadata namespace matching the provided key. - * @param metadataKey + * @param metadataKey * @return Namespace of the designated metadata format. Returns null of not found. */ private static Namespace getDMDNamespace(String metadataKey) { String metadataString = null; String metaString = "harvester.oai.metadataformats."; - + Enumeration pe = ConfigurationManager.propertyNames("oai"); - + while (pe.hasMoreElements()) { String key = (String)pe.nextElement(); - + if (key.startsWith(metaString) && key.substring(metaString.length()).equals((metadataKey))) { metadataString = ConfigurationManager.getProperty("oai", key); String namespacePiece; @@ -216,17 +208,17 @@ public class OAIHarvester { } return null; } - - - - - - /** - * Performs a harvest cycle on this collection. This will query the remote OAI-PMH provider, check for updates since last - * harvest, and ingest the returned items. + + + + + + /** + * Performs a harvest cycle on this collection. This will query the remote OAI-PMH provider, check for updates since last + * harvest, and ingest the returned items. */ - public void runHarvest() throws SQLException, IOException, AuthorizeException - { + public void runHarvest() throws SQLException, IOException, AuthorizeException + { // figure out the relevant parameters String oaiSource = harvestRow.getOaiSource(); String oaiSetId = harvestRow.getOaiSetId(); @@ -242,13 +234,13 @@ public class OAIHarvester { { fromDate = processDate(harvestRow.getHarvestDate()); } - + Date startTime = new Date(); - String toDate = processDate(startTime,0); - + String toDate = processDate(startTime,0); + String dateGranularity; - - try + + try { // obtain the desired descriptive metadata format and verify that the OAI server actually provides it // do the same thing for ORE, which should be encoded in Atom and carry its namespace @@ -261,7 +253,7 @@ public class OAIHarvester { fromDate = fromDate.substring(0, dateGranularity.length()); } toDate = toDate.substring(0, dateGranularity.length()); - + descMDPrefix = oaiResolveNamespaceToPrefix(oaiSource, metadataNS.getURI()); OREPrefix = oaiResolveNamespaceToPrefix(oaiSource, ORESerialNS.getURI()); } @@ -272,7 +264,7 @@ public class OAIHarvester { catch (ConnectException fe) { log.error("The OAI server did not respond."); throw new HarvestingException("The OAI server did not respond.", fe); - } + } if (descMDPrefix == null) { log.error("The OAI server does not support this metadata format"); throw new HarvestingException("The OAI server does not support this metadata format: " + metadataNS.getURI()); @@ -280,53 +272,53 @@ public class OAIHarvester { if (OREPrefix == null && harvestRow.getHarvestType() != HarvestedCollection.TYPE_DMD) { throw new HarvestingException("The OAI server does not support ORE dissemination in the configured serialization format: " + ORESerialNS.getURI()); } - + Document oaiResponse = null; - Element root = null; + Element root = null; String resumptionToken; - + // set the status indicating the collection is currently being processed harvestRow.setHarvestStatus(HarvestedCollection.STATUS_BUSY); harvestRow.setHarvestMessage("Collection is currently being harvested"); harvestRow.setHarvestStartTime(startTime); harvestRow.update(); ourContext.commit(); - + // expiration timer starts int expirationInterval = ConfigurationManager.getIntProperty("oai", "harvester.threadTimeout"); if (expirationInterval == 0) { expirationInterval = 24; } - + Calendar calendar = Calendar.getInstance(); calendar.setTime(startTime); calendar.add(Calendar.HOUR, expirationInterval); Date expirationTime = calendar.getTime(); - + // main loop to keep requesting more objects until we're done List<Element> records; Set<String> errorSet = new HashSet<String>(); - + ListRecords listRecords = new ListRecords(oaiSource, fromDate, toDate, oaiSetId, descMDPrefix); log.debug("Harvesting request parameters: listRecords " + oaiSource + " " + fromDate + " " + toDate + " " + oaiSetId + " " + descMDPrefix); if (listRecords != null) { log.info("HTTP Request: " + listRecords.getRequestURL()); } - while (listRecords != null) + while (listRecords != null) { records = new ArrayList<Element>(); oaiResponse = db.build(listRecords.getDocument()); - if (listRecords.getErrors() != null && listRecords.getErrors().getLength() > 0) + if (listRecords.getErrors() != null && listRecords.getErrors().getLength() > 0) { - for (int i=0; i<listRecords.getErrors().getLength(); i++) + for (int i=0; i<listRecords.getErrors().getLength(); i++) { String errorCode = listRecords.getErrors().item(i).getAttributes().getNamedItem("code").getTextContent(); errorSet.add(errorCode); } - if (errorSet.contains("noRecordsMatch")) + if (errorSet.contains("noRecordsMatch")) { log.info("noRecordsMatch: OAI server did not contain any updates"); harvestRow.setHarvestResult(new Date(), "OAI server did not contain any updates"); @@ -337,14 +329,14 @@ public class OAIHarvester { throw new HarvestingException(errorSet.toString()); } } - else + else { root = oaiResponse.getRootElement(); records.addAll(root.getChild("ListRecords", OAI_NS).getChildren("record", OAI_NS)); } // Process the obtained records - if (records != null && records.size()>0) + if (records != null && records.size()>0) { log.info("Found " + records.size() + " records to process"); for (Element record : records) { @@ -358,7 +350,7 @@ public class OAIHarvester { { throw new HarvestingException("runHarvest method timed out for collection " + targetCollection.getID()); } - + processRecord(record,OREPrefix); ourContext.commit(); } @@ -372,20 +364,26 @@ public class OAIHarvester { else { listRecords = new ListRecords(oaiSource, resumptionToken); } - targetCollection.update(); + ourContext.turnOffAuthorisationSystem(); + try { + targetCollection.update(); + } finally { + //In case of an exception, make sure to restore our authentication state to the previous state + ourContext.restoreAuthSystemState(); + } ourContext.commit(); } } catch (HarvestingException hex) { log.error("Harvesting error occured while processing an OAI record: " + hex.getMessage()); harvestRow.setHarvestMessage("Error occured while processing an OAI record"); - + // if the last status is also an error, alert the admin if (harvestRow.getHarvestMessage().contains("Error")) { alertAdmin(HarvestedCollection.STATUS_OAI_ERROR, hex); } harvestRow.setHarvestStatus(HarvestedCollection.STATUS_OAI_ERROR); - return; + return; } catch (Exception ex) { harvestRow.setHarvestMessage("Unknown error occured while generating an OAI response"); @@ -394,14 +392,15 @@ public class OAIHarvester { log.error("Error occured while generating an OAI response: " + ex.getMessage() + " " + ex.getCause()); ex.printStackTrace(); return; - } + } finally { harvestRow.update(); + ourContext.turnOffAuthorisationSystem(); targetCollection.update(); ourContext.commit(); ourContext.restoreAuthSystemState(); } - + // If we got to this point, it means the harvest was completely successful Date finishTime = new Date(); long timeTaken = finishTime.getTime() - startTime.getTime(); @@ -411,24 +410,24 @@ public class OAIHarvester { harvestRow.update(); ourContext.commit(); } - + /** - * Process an individual PMH record, making (or updating) a corresponding DSpace Item. + * Process an individual PMH record, making (or updating) a corresponding DSpace Item. * @param record a JDOM Element containing the actual PMH record with descriptive metadata. * @param OREPrefix the metadataprefix value used by the remote PMH server to disseminate ORE. Only used for collections set up to harvest content. */ - private void processRecord(Element record, String OREPrefix) throws SQLException, AuthorizeException, IOException, CrosswalkException, HarvestingException, ParserConfigurationException, SAXException, TransformerException + private void processRecord(Element record, String OREPrefix) throws SQLException, AuthorizeException, IOException, CrosswalkException, HarvestingException, ParserConfigurationException, SAXException, TransformerException { WorkspaceItem wi = null; Date timeStart = new Date(); - + // grab the oai identifier String itemOaiID = record.getChild("header", OAI_NS).getChild("identifier", OAI_NS).getText(); Element header = record.getChild("header",OAI_NS); - + // look up the item corresponding to the OAI identifier Item item = HarvestedItem.getItemByOAIId(ourContext, itemOaiID, targetCollection.getID()); - + // Make sure the item hasn't been deleted in the mean time if (header.getAttribute("status") != null && header.getAttribute("status").getValue().equals("deleted")) { log.info("Item " + itemOaiID + " has been marked as deleted on the OAI server."); @@ -436,44 +435,44 @@ public class OAIHarvester { { targetCollection.removeItem(item); } - - ourContext.restoreAuthSystemState(); + + ourContext.restoreAuthSystemState(); return; } - + // If we are only harvesting descriptive metadata, the record should already contain all we need List<Element> descMD = record.getChild("metadata", OAI_NS).getChildren(); IngestionCrosswalk MDxwalk = (IngestionCrosswalk)PluginManager.getNamedPlugin(IngestionCrosswalk.class, this.metadataKey); - - // Otherwise, obtain the ORE ReM and initiate the ORE crosswalk + + // Otherwise, obtain the ORE ReM and initiate the ORE crosswalk IngestionCrosswalk ORExwalk = null; Element oreREM = null; if (harvestRow.getHarvestType() > 1) { oreREM = getMDrecord(harvestRow.getOaiSource(), itemOaiID, OREPrefix).get(0); ORExwalk = (IngestionCrosswalk)PluginManager.getNamedPlugin(IngestionCrosswalk.class, this.ORESerialKey); } - + // Ignore authorization ourContext.turnOffAuthorisationSystem(); - + HarvestedItem hi; - - if (item != null) // found an item so we modify - { + + if (item != null) // found an item so we modify + { log.debug("Item " + item.getHandle() + " was found locally. Using it to harvest " + itemOaiID + "."); - - // FIXME: check for null pointer if for some odd reason we don't have a matching hi + + // FIXME: check for null pointer if for some odd reason we don't have a matching hi hi = HarvestedItem.find(ourContext, item.getID()); - + // Compare last-harvest on the item versus the last time the item was updated on the OAI provider side - // If ours is more recent, forgo this item, since it's probably a left-over from a previous harvesting attempt + // If ours is more recent, forgo this item, since it's probably a left-over from a previous harvesting attempt Date OAIDatestamp = Utils.parseISO8601Date(header.getChildText("datestamp", OAI_NS)); Date itemLastHarvest = hi.getHarvestDate(); if (itemLastHarvest != null && OAIDatestamp.before(itemLastHarvest)) { log.info("Item " + item.getHandle() + " was harvested more recently than the last update time reporetd by the OAI server; skipping."); return; } - + // Otherwise, clear and re-import the metadata and bitstreams item.clearMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); if (descMD.size() == 1) @@ -488,26 +487,26 @@ public class OAIHarvester { // Import the actual bitstreams if (harvestRow.getHarvestType() == 3) { log.info("Running ORE ingest on: " + item.getHandle()); - + Bundle[] allBundles = item.getBundles(); for (Bundle bundle : allBundles) { item.removeBundle(bundle); } ORExwalk.ingest(ourContext, item, oreREM); } - + scrubMetadata(item); - } - else - // NOTE: did not find, so we create (presumably, there will never be a case where an item already + } + else + // NOTE: did not find, so we create (presumably, there will never be a case where an item already // exists in a harvest collection but does not have an OAI_id) { wi = WorkspaceItem.create(ourContext, targetCollection, false); item = wi.getItem(); - + hi = HarvestedItem.create(ourContext, item.getID(), itemOaiID); //item.setOaiID(itemOaiID); - + if (descMD.size() == 1) { MDxwalk.ingest(ourContext, item, descMD.get(0)); @@ -516,18 +515,18 @@ public class OAIHarvester { { MDxwalk.ingest(ourContext, item, descMD); } - + if (harvestRow.getHarvestType() == 3) { ORExwalk.ingest(ourContext, item, oreREM); } - + // see if we can do something about the wonky metadata scrubMetadata(item); - + // see if a handle can be extracted for the item String handle = extractHandle(item); - - if (handle != null) + + if (handle != null) { DSpaceObject dso = HandleManager.resolveToObject(ourContext, handle); if (dso != null) @@ -535,12 +534,12 @@ public class OAIHarvester { throw new HarvestingException("Handle collision: attempted to re-assign handle '" + handle + "' to an incoming harvested item '" + hi.getOaiID() + "'."); } } - + try { item = InstallItem.installItem(ourContext, wi, handle); //item = InstallItem.installItem(ourContext, wi); } - // clean up the workspace item if something goes wrong before + // clean up the workspace item if something goes wrong before catch(SQLException se) { wi.deleteWrapper(); throw se; @@ -554,27 +553,27 @@ public class OAIHarvester { throw ae; } } - + // Now create the special ORE bundle and drop the ORE document in it - if (harvestRow.getHarvestType() == 2 || harvestRow.getHarvestType() == 3) + if (harvestRow.getHarvestType() == 2 || harvestRow.getHarvestType() == 3) { Bundle OREBundle = item.createBundle("ORE"); - + XMLOutputter outputter = new XMLOutputter(); String OREString = outputter.outputString(oreREM); ByteArrayInputStream OREStream = new ByteArrayInputStream(OREString.getBytes()); - + Bitstream OREBitstream = OREBundle.createBitstream(OREStream); OREBitstream.setName("ORE.xml"); BitstreamFormat bf = FormatIdentifier.guessFormat(ourContext, OREBitstream); OREBitstream.setFormat(bf); OREBitstream.update(); - + OREBundle.addBitstream(OREBitstream); OREBundle.update(); } - + //item.setHarvestDate(new Date()); hi.setHarvestDate(new Date()); @@ -583,7 +582,7 @@ public class OAIHarvester { + this.harvestRow.getOaiSource() + " on " + new DCDate(hi.getHarvestDate()) + " (GMT). Item's OAI Record identifier: " + hi.getOaiID(); item.addMetadata("dc", "description", "provenance", "en", provenanceMsg); - + item.update(); hi.update(); long timeTaken = new Date().getTime() - timeStart.getTime(); @@ -592,47 +591,47 @@ public class OAIHarvester { // Stop ignoring authorization ourContext.restoreAuthSystemState(); } - - - + + + /** * Scan an item's metadata, looking for the value "identifier.*". If it meets the parameters that identify it as valid handle - * as set in dspace.cfg (harvester.acceptedHandleServer and harvester.rejectedHandlePrefix), use that handle instead of - * minting a new one. + * as set in dspace.cfg (harvester.acceptedHandleServer and harvester.rejectedHandlePrefix), use that handle instead of + * minting a new one. * @param item a newly created, but not yet installed, DSpace Item * @return null or the handle to be used. */ - private String extractHandle(Item item) + private String extractHandle(Item item) { String acceptedHandleServersString = ConfigurationManager.getProperty("oai", "harvester.acceptedHandleServer"); if (acceptedHandleServersString == null) { acceptedHandleServersString = "hdl.handle.net"; } - + String rejectedHandlePrefixString = ConfigurationManager.getProperty("oai", "harvester.rejectedHandlePrefix"); if (rejectedHandlePrefixString == null) { rejectedHandlePrefixString = "123456789"; } - + DCValue[] values = item.getMetadata("dc", "identifier", Item.ANY, Item.ANY); - - if (values.length > 0 && !acceptedHandleServersString.equals("")) + + if (values.length > 0 && !acceptedHandleServersString.equals("")) { String[] acceptedHandleServers = acceptedHandleServersString.split(","); String[] rejectedHandlePrefixes = rejectedHandlePrefixString.split(","); - - for (DCValue value : values) + + for (DCValue value : values) { // 0 1 2 3 4 - // http://hdl.handle.net/1234/12 + // http://hdl.handle.net/1234/12 String[] urlPieces = value.value.split("/"); if (urlPieces.length != 5) { continue; } - + for (String server : acceptedHandleServers) { if (urlPieces[2].equals(server)) { for (String prefix : rejectedHandlePrefixes) { @@ -641,22 +640,22 @@ public class OAIHarvester { return urlPieces[3] + "/" + urlPieces[4]; } } - + } } } } - + return null; } - - + + /** * Scans an item's newly ingested metadata for elements not defined in this DSpace instance. It then takes action based - * on a configurable parameter (fail, ignore, add). + * on a configurable parameter (fail, ignore, add). * @param item a DSpace item recently pushed through an ingestion crosswalk but prior to update/installation */ - private void scrubMetadata(Item item) throws SQLException, HarvestingException, AuthorizeException, IOException + private void scrubMetadata(Item item) throws SQLException, HarvestingException, AuthorizeException, IOException { // The two options, with three possibilities each: add, ignore, fail String schemaChoice = ConfigurationManager.getProperty("oai", "harvester.unknownSchema"); @@ -664,17 +663,17 @@ public class OAIHarvester { { schemaChoice = "fail"; } - + String fieldChoice = ConfigurationManager.getProperty("oai", "harvester.unknownField"); if (fieldChoice == null) { fieldChoice = "fail"; } - + List<String> clearList = new ArrayList<String>(); - + DCValue[] values = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); - for (DCValue value : values) + for (DCValue value : values) { // Verify that the schema exists MetadataSchema mdSchema = MetadataSchema.find(ourContext, value.schema); @@ -693,12 +692,12 @@ public class OAIHarvester { } clearList.add(value.schema); } - // ignore the offending schema, quietly dropping all of its metadata elements before they clog our gears + // ignore the offending schema, quietly dropping all of its metadata elements before they clog our gears else if (schemaChoice.equals("ignore")) { item.clearMetadata(value.schema, Item.ANY, Item.ANY, Item.ANY); continue; } - // otherwise, go ahead and generate the error + // otherwise, go ahead and generate the error else { throw new HarvestingException("The '" + value.schema + "' schema has not been defined in this DSpace instance. "); } @@ -727,105 +726,105 @@ public class OAIHarvester { } } } - - return; + + return; } - - - - + + + + /** * Process a date, converting it to RFC3339 format, setting the timezone to UTC and subtracting time padding * from the config file. - * @param date source Date + * @param date source Date * @return a string in the format 'yyyy-mm-ddThh:mm:ssZ' and converted to UTC timezone */ private String processDate(Date date) { Integer timePad = ConfigurationManager.getIntProperty("oai", "harvester.timePadding"); - + if (timePad == 0) { timePad = 120; } - + return processDate(date, timePad); } - + /** * Process a date, converting it to RFC3339 format, setting the timezone to UTC and subtracting time padding * from the config file. * @param date source Date - * @param secondsPad number of seconds to subtract from the date + * @param secondsPad number of seconds to subtract from the date * @return a string in the format 'yyyy-mm-ddThh:mm:ssZ' and converted to UTC timezone */ private String processDate(Date date, int secondsPad) { - + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); formatter.setTimeZone(TimeZone.getTimeZone("UTC")); - + Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.SECOND, -1*secondsPad); date = calendar.getTime(); - - return formatter.format(date); + + return formatter.format(date); } - - + + /** - * Query OAI-PMH server for the granularity of its datestamps. - * @throws TransformerException - * @throws SAXException - * @throws ParserConfigurationException - * @throws IOException + * Query OAI-PMH server for the granularity of its datestamps. + * @throws TransformerException + * @throws SAXException + * @throws ParserConfigurationException + * @throws IOException */ - private String oaiGetDateGranularity(String oaiSource) throws IOException, ParserConfigurationException, SAXException, TransformerException + private String oaiGetDateGranularity(String oaiSource) throws IOException, ParserConfigurationException, SAXException, TransformerException { Identify iden = new Identify(oaiSource); return iden.getDocument().getElementsByTagNameNS(OAI_NS.getURI(), "granularity").item(0).getTextContent(); } - + /** - * Query the OAI-PMH server for its mapping of the supplied namespace and metadata prefix. - * For example for a typical OAI-PMH server a query "http://www.openarchives.org/OAI/2.0/oai_dc/" would return "oai_dc". + * Query the OAI-PMH server for its mapping of the supplied namespace and metadata prefix. + * For example for a typical OAI-PMH server a query "http://www.openarchives.org/OAI/2.0/oai_dc/" would return "oai_dc". * @param oaiSource the address of the OAI-PMH provider * @param MDNamespace the namespace that we are trying to resolve to the metadataPrefix * @return metadataPrefix the OAI-PMH provider has assigned to the supplied namespace */ - public static String oaiResolveNamespaceToPrefix(String oaiSource, String MDNamespace) throws IOException, ParserConfigurationException, SAXException, TransformerException, ConnectException + public static String oaiResolveNamespaceToPrefix(String oaiSource, String MDNamespace) throws IOException, ParserConfigurationException, SAXException, TransformerException, ConnectException { String metaPrefix = null; // Query the OAI server for the metadata ListMetadataFormats lmf = new ListMetadataFormats(oaiSource); - + if (lmf != null) { Document lmfResponse = db.build(lmf.getDocument()); List<Element> mdFormats = lmfResponse.getRootElement().getChild("ListMetadataFormats", OAI_NS).getChildren("metadataFormat", OAI_NS); - + for (Element mdFormat : mdFormats) { - if (MDNamespace.equals(mdFormat.getChildText("metadataNamespace", OAI_NS))) + if (MDNamespace.equals(mdFormat.getChildText("metadataNamespace", OAI_NS))) { metaPrefix = mdFormat.getChildText("metadataPrefix", OAI_NS); break; } } } - - return metaPrefix; + + return metaPrefix; } - + /** - * Generate and send an email to the administrator. Prompted by errors encountered during harvesting. + * Generate and send an email to the administrator. Prompted by errors encountered during harvesting. * @param status the current status of the collection, usually HarvestedCollection.STATUS_OAI_ERROR or HarvestedCollection.STATUS_UNKNOWN_ERROR * @param ex the Exception that prompted this action */ - private void alertAdmin(int status, Exception ex) + private void alertAdmin(int status, Exception ex) { try { String recipient = ConfigurationManager.getProperty("alert.recipient"); - - if (recipient != null) { - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(Locale.getDefault(), "harvesting_error")); + + if (StringUtils.isNotBlank(recipient)) { + Email email = Email.getEmail(I18nUtil.getEmailFilename(Locale.getDefault(), "harvesting_error")); email.addRecipient(recipient); email.addArgument(targetCollection.getID()); email.addArgument(new Date()); @@ -851,22 +850,22 @@ public class OAIHarvester { } catch (Exception e) { log.warn("Unable to send email alert", e); } - + } - - - + + + /** - * Query the OAI-PMH provider for a specific metadata record. + * Query the OAI-PMH provider for a specific metadata record. * @param oaiSource the address of the OAI-PMH provider - * @param itemOaiId the OAI identifier of the target item + * @param itemOaiId the OAI identifier of the target item * @param metadataPrefix the OAI metadataPrefix of the desired metadata - * @return list of JDOM elements corresponding to the metadata entries in the located record. + * @return list of JDOM elements corresponding to the metadata entries in the located record. */ - private List<Element> getMDrecord(String oaiSource, String itemOaiId, String metadataPrefix) throws IOException, ParserConfigurationException, SAXException, TransformerException, HarvestingException + private List<Element> getMDrecord(String oaiSource, String itemOaiId, String metadataPrefix) throws IOException, ParserConfigurationException, SAXException, TransformerException, HarvestingException { GetRecord getRecord = new GetRecord(oaiSource,itemOaiId,metadataPrefix); - Set<String> errorSet = new HashSet<String>(); + Set<String> errorSet = new HashSet<String>(); // If the metadata is not available for this item, can the whole thing if (getRecord != null && getRecord.getErrors() != null && getRecord.getErrors().getLength() > 0) { for (int i=0; i<getRecord.getErrors().getLength(); i++) { @@ -881,38 +880,36 @@ public class OAIHarvester { return root.getChild("GetRecord",OAI_NS).getChild("record", OAI_NS).getChild("metadata",OAI_NS).getChildren(); } - - + + /** * Verify OAI settings for the current collection - * @return list of errors encountered during verification. Empty list indicates a "success" condition. + * @return list of errors encountered during verification. Empty list indicates a "success" condition. */ public List<String> verifyOAIharvester() { String oaiSource = harvestRow.getOaiSource(); String oaiSetId = harvestRow.getOaiSetId(); String metaPrefix = harvestRow.getHarvestMetadataConfig(); - + return verifyOAIharvester(oaiSource, oaiSetId, metaPrefix, true); } - + /** - * Verify the existance of an OAI server with the specified set and supporting the provided metadata formats. + * Verify the existence of an OAI server with the specified set and + * supporting the provided metadata formats. + * * @param oaiSource the address of the OAI-PMH provider - * @param oaiSetId + * @param oaiSetId * @param metaPrefix * @param testORE whether the method should also check the PMH provider for ORE support * @return list of errors encountered during verification. Empty list indicates a "success" condition. */ - public static List<String> verifyOAIharvester(String oaiSource, String oaiSetId, String metaPrefix, boolean testORE) + public static List<String> verifyOAIharvester(String oaiSource, + String oaiSetId, String metaPrefix, boolean testORE) { List<String> errorSet = new ArrayList<String>(); - - // First, make sure the metadata we need is supported by the target server - Namespace ORE_NS = OAIHarvester.getORENamespace(); - String OREOAIPrefix = null; - Namespace DMD_NS = OAIHarvester.getDMDNamespace(metaPrefix); - String DMDOAIPrefix = null; - + + // First, see if we can contact the target server at all. try { Identify idenTest = new Identify(oaiSource); } @@ -920,17 +917,31 @@ public class OAIHarvester { errorSet.add(OAI_ADDRESS_ERROR + ": OAI server could not be reached."); return errorSet; } - - try { - OREOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, ORE_NS.getURI()); - DMDOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, DMD_NS.getURI()); + + // Next, make sure the metadata we need is supported by the target server + Namespace DMD_NS = OAIHarvester.getDMDNamespace(metaPrefix); + if (null == DMD_NS) + { + errorSet.add(OAI_DMD_ERROR + ": " + metaPrefix); + return errorSet; + } + + String OREOAIPrefix = null; + String DMDOAIPrefix = null; + + try { + OREOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, getORENamespace().getURI()); + DMDOAIPrefix = OAIHarvester.oaiResolveNamespaceToPrefix(oaiSource, DMD_NS.getURI()); } catch (Exception ex) { - errorSet.add(OAI_ADDRESS_ERROR + ": OAI did not respond to ListMetadataFormats query (" + ORE_NS.getPrefix() + ":" + OREOAIPrefix + " ; " + - DMD_NS.getPrefix() + ":" + DMDOAIPrefix + ")"); - return errorSet; + errorSet.add(OAI_ADDRESS_ERROR + + ": OAI did not respond to ListMetadataFormats query (" + + ORE_NS.getPrefix() + ":" + OREOAIPrefix + " ; " + + DMD_NS.getPrefix() + ":" + DMDOAIPrefix + "): " + + ex.getMessage()); + return errorSet; } - + if (testORE && OREOAIPrefix == null) { errorSet.add(OAI_ORE_ERROR + ": The OAI server does not support ORE dissemination"); @@ -939,35 +950,27 @@ public class OAIHarvester { { errorSet.add(OAI_DMD_ERROR + ": The OAI server does not support dissemination in this format"); } - - // Now scan the sets and make sure the one supplied is in the list + + // Now scan the sets and make sure the one supplied is in the list boolean foundSet = false; try { //If we do not want to harvest from one set, then skip this. if(!"all".equals(oaiSetId)){ - ListSets ls = new ListSets(oaiSource); + ListIdentifiers ls = new ListIdentifiers(oaiSource, null, null, oaiSetId, DMDOAIPrefix); // The only error we can really get here is "noSetHierarchy" if (ls.getErrors() != null && ls.getErrors().getLength() > 0) { for (int i=0; i<ls.getErrors().getLength(); i++) { String errorCode = ls.getErrors().item(i).getAttributes().getNamedItem("code").getTextContent(); - errorSet.add(errorCode); + errorSet.add(OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec (" + errorCode + ")"); } } else { // Drilling down to /OAI-PMH/ListSets/set Document reply = db.build(ls.getDocument()); Element root = reply.getRootElement(); - List<Element> sets= root.getChild("ListSets",OAI_NS).getChildren("set",OAI_NS); - - for (Element set : sets) - { - String setSpec = set.getChildText("setSpec", OAI_NS); - if (setSpec.equals(oaiSetId)) { - foundSet = true; - break; - } - } + //Check if we can find items, if so this indicates that we have children and our sets exist + foundSet = 0 < root.getChild("ListIdentifiers",OAI_NS).getChildren().size(); if (!foundSet) { errorSet.add(OAI_SET_ERROR + ": The OAI server does not have a set with the specified setSpec"); @@ -986,58 +989,57 @@ public class OAIHarvester { return errorSet; } - - - /** - * Start harvest scheduler. - */ - public static synchronized void startNewScheduler() throws SQLException, AuthorizeException { - Context c = new Context(); - HarvestedCollection.exists(c); - c.complete(); - - if (mainHarvestThread != null && harvester != null) { - stopScheduler(); - } + + /** + * Start harvest scheduler. + */ + public static synchronized void startNewScheduler() throws SQLException, AuthorizeException { + Context c = new Context(); + HarvestedCollection.exists(c); + c.complete(); + + if (mainHarvestThread != null && harvester != null) { + stopScheduler(); + } harvester = new HarvestScheduler(); HarvestScheduler.interrupt = HarvestScheduler.HARVESTER_INTERRUPT_NONE; mainHarvestThread = new Thread(harvester); mainHarvestThread.start(); } - - /** - * Stop an active harvest scheduler. - */ - public static synchronized void stopScheduler() throws SQLException, AuthorizeException { - synchronized(HarvestScheduler.lock) { - HarvestScheduler.interrupt = HarvestScheduler.HARVESTER_INTERRUPT_STOP; - HarvestScheduler.lock.notify(); - } - mainHarvestThread = null; - harvester = null; + + /** + * Stop an active harvest scheduler. + */ + public static synchronized void stopScheduler() throws SQLException, AuthorizeException { + synchronized(HarvestScheduler.lock) { + HarvestScheduler.interrupt = HarvestScheduler.HARVESTER_INTERRUPT_STOP; + HarvestScheduler.lock.notify(); + } + mainHarvestThread = null; + harvester = null; } - + /** - * Pause an active harvest scheduler. + * Pause an active harvest scheduler. */ public static void pauseScheduler() throws SQLException, AuthorizeException { synchronized(HarvestScheduler.lock) { HarvestScheduler.interrupt = HarvestScheduler.HARVESTER_INTERRUPT_PAUSE; HarvestScheduler.lock.notify(); - } + } } - + /** - * Resume a paused harvest scheduler. + * Resume a paused harvest scheduler. */ public static void resumeScheduler() throws SQLException, AuthorizeException { HarvestScheduler.interrupt = HarvestScheduler.HARVESTER_INTERRUPT_RESUME; } - + public static void resetScheduler() throws SQLException, AuthorizeException, IOException { Context context = new Context(); List<Integer> cids = HarvestedCollection.findAll(context); - for (Integer cid : cids) + for (Integer cid : cids) { HarvestedCollection hc = HarvestedCollection.find(context, cid); hc.setHarvestStartTime(null); @@ -1046,14 +1048,14 @@ public class OAIHarvester { } context.commit(); } - - + + /** - * Exception class specifically assigned to recoverable errors that occur during harvesting. Throughout the harvest process, various exceptions - * are caught and turned into a HarvestingException. Uncaught exceptions are irrecoverable errors. + * Exception class specifically assigned to recoverable errors that occur during harvesting. Throughout the harvest process, various exceptions + * are caught and turned into a HarvestingException. Uncaught exceptions are irrecoverable errors. * @author alexey */ - public static class HarvestingException extends Exception + public static class HarvestingException extends Exception { public HarvestingException() { super(); @@ -1062,7 +1064,7 @@ public class OAIHarvester { public HarvestingException(String message, Throwable t) { super(message, t); } - + public HarvestingException(String message) { super(message); } @@ -1071,40 +1073,54 @@ public class OAIHarvester { super(t); } } - - /** - * The class responsible for scheduling harvesting cycles are regular intervals. - * @author alexey - */ - public static class HarvestScheduler implements Runnable - { - private EPerson harvestAdmin; - private Context mainContext; - - public static final Object lock = new Object(); - - private static Stack<HarvestThread> harvestThreads; - private static Integer maxActiveThreads; - protected static volatile Integer activeThreads = 0; - - public static final int HARVESTER_STATUS_RUNNING = 1; - public static final int HARVESTER_STATUS_SLEEPING = 2; - public static final int HARVESTER_STATUS_PAUSED = 3; - public static final int HARVESTER_STATUS_STOPPED = 4; - - public static final int HARVESTER_INTERRUPT_NONE = 0; - public static final int HARVESTER_INTERRUPT_PAUSE = 1; - public static final int HARVESTER_INTERRUPT_STOP = 2; - public static final int HARVESTER_INTERRUPT_RESUME = 3; - public static final int HARVESTER_INTERRUPT_INSERT_THREAD = 4; - public static final int HARVESTER_INTERRUPT_KILL_THREAD = 5; - - private static int status = HARVESTER_STATUS_STOPPED; - private static int interrupt = HARVESTER_INTERRUPT_NONE; - private static Integer interruptValue = 0; - - private static long minHeartbeat; - private static long maxHeartbeat; + + /** + * The class responsible for scheduling harvesting cycles are regular intervals. + * @author alexey + */ + public static class HarvestScheduler implements Runnable + { + private static EPerson harvestAdmin; + + private Context mainContext; + + public static final Object lock = new Object(); + + private static Stack<HarvestThread> harvestThreads; + + private static Integer maxActiveThreads; + + protected static volatile Integer activeThreads = 0; + + public static final int HARVESTER_STATUS_RUNNING = 1; + + public static final int HARVESTER_STATUS_SLEEPING = 2; + + public static final int HARVESTER_STATUS_PAUSED = 3; + + public static final int HARVESTER_STATUS_STOPPED = 4; + + public static final int HARVESTER_INTERRUPT_NONE = 0; + + public static final int HARVESTER_INTERRUPT_PAUSE = 1; + + public static final int HARVESTER_INTERRUPT_STOP = 2; + + public static final int HARVESTER_INTERRUPT_RESUME = 3; + + public static final int HARVESTER_INTERRUPT_INSERT_THREAD = 4; + + public static final int HARVESTER_INTERRUPT_KILL_THREAD = 5; + + private static int status = HARVESTER_STATUS_STOPPED; + + private static int interrupt = HARVESTER_INTERRUPT_NONE; + + private static Integer interruptValue = 0; + + private static long minHeartbeat; + + private static long maxHeartbeat; public static boolean hasStatus(int statusToCheck) { return status == statusToCheck; @@ -1119,58 +1135,58 @@ public class OAIHarvester { interruptValue = newInterruptValue; } - public static String getStatus() { - switch(status) { - case HARVESTER_STATUS_RUNNING: - switch(interrupt) { - case HARVESTER_INTERRUPT_PAUSE: return("The scheduler is finishing active harvests before pausing. "); - case HARVESTER_INTERRUPT_STOP: return("The scheduler is shutting down. "); - } - return("The scheduler is actively harvesting collections. "); - case HARVESTER_STATUS_SLEEPING: return("The scheduler is waiting for collections to harvest. "); - case HARVESTER_STATUS_PAUSED: return("The scheduler is paused. "); - default: return("Automatic harvesting is not active. "); - } - } - - public HarvestScheduler() throws SQLException, AuthorizeException { - mainContext = new Context(); - String harvestAdminParam = ConfigurationManager.getProperty("harvester.eperson"); - harvestAdmin = null; - if (harvestAdminParam != null && harvestAdminParam.length() > 0) + public static String getStatus() { + switch(status) { + case HARVESTER_STATUS_RUNNING: + switch(interrupt) { + case HARVESTER_INTERRUPT_PAUSE: return("The scheduler is finishing active harvests before pausing. "); + case HARVESTER_INTERRUPT_STOP: return("The scheduler is shutting down. "); + } + return("The scheduler is actively harvesting collections. "); + case HARVESTER_STATUS_SLEEPING: return("The scheduler is waiting for collections to harvest. "); + case HARVESTER_STATUS_PAUSED: return("The scheduler is paused. "); + default: return("Automatic harvesting is not active. "); + } + } + + public HarvestScheduler() throws SQLException, AuthorizeException { + mainContext = new Context(); + String harvestAdminParam = ConfigurationManager.getProperty("oai", "harvester.eperson"); + harvestAdmin = null; + if (harvestAdminParam != null && harvestAdminParam.length() > 0) { harvestAdmin = EPerson.findByEmail(mainContext, harvestAdminParam); } - - harvestThreads = new Stack<HarvestThread>(); - - maxActiveThreads = ConfigurationManager.getIntProperty("oai", "harvester.maxThreads"); - if (maxActiveThreads == 0) + + harvestThreads = new Stack<HarvestThread>(); + + maxActiveThreads = ConfigurationManager.getIntProperty("oai", "harvester.maxThreads"); + if (maxActiveThreads == 0) { maxActiveThreads = 3; } - minHeartbeat = ConfigurationManager.getIntProperty("oai", "harvester.minHeartbeat") * 1000; - if (minHeartbeat == 0) + minHeartbeat = ConfigurationManager.getIntProperty("oai", "harvester.minHeartbeat") * 1000; + if (minHeartbeat == 0) { minHeartbeat = 30000; } - maxHeartbeat = ConfigurationManager.getIntProperty("oai", "harvester.maxHeartbeat") * 1000; - if (maxHeartbeat == 0) + maxHeartbeat = ConfigurationManager.getIntProperty("oai", "harvester.maxHeartbeat") * 1000; + if (maxHeartbeat == 0) { maxHeartbeat = 3600000; } - } + } - public void run() { - scheduleLoop(); - } - - private void scheduleLoop() { - long i=0; - while(true) - { - try - { + public void run() { + scheduleLoop(); + } + + private void scheduleLoop() { + long i=0; + while(true) + { + try + { synchronized (HarvestScheduler.class) { switch (interrupt) { @@ -1201,156 +1217,156 @@ public class OAIHarvester { } } - status = HARVESTER_STATUS_RUNNING; - - // Stage #1: if something is ready for harvest, push it onto the ready stack, mark it as "queued" - mainContext = new Context(); - List<Integer> cids = HarvestedCollection.findReady(mainContext); - log.info("Collections ready for immediate harvest: " + cids.toString()); - - for (Integer cid : cids) { - addThread(cid); - } - - // Stage #2: start up all the threads currently in the queue up to the maximum number - while (!harvestThreads.isEmpty()) { - synchronized(HarvestScheduler.class) { - activeThreads++; - } - Thread activeThread = new Thread(harvestThreads.pop()); - activeThread.start(); - log.info("Thread started: " + activeThread.toString()); - - /* Wait while the number of threads running is greater than or equal to max */ - while (activeThreads >= maxActiveThreads) { - /* Wait a second */ - Thread.sleep(1000); - } - } - - // Finally, wait for the last few remaining threads to finish - // TODO: this step might be unnecessary. Theoretically a single very long harvest process - // could then lock out all the other ones from starting on their next iteration. - // FIXME: also, this might lead to a situation when a single thread getting stuck without - // throwing an exception would shut down the whole scheduler - while (activeThreads != 0) { - /* Wait a second */ - Thread.sleep(1000); - } - - // Commit everything - try { - mainContext.commit(); - mainContext.complete(); - log.info("Done with iteration " + i); - } catch (SQLException e) { - e.printStackTrace(); - mainContext.abort(); - } - - } - catch (Exception e) { - log.error("Exception on iteration: " + i); - e.printStackTrace(); - } - - // Stage #3: figure out how long until the next iteration and wait - try { - Context tempContext = new Context(); - int nextCollectionId = HarvestedCollection.findOldestHarvest(tempContext); - HarvestedCollection hc = HarvestedCollection.find(tempContext, nextCollectionId); - - int harvestInterval = ConfigurationManager.getIntProperty("oai", "harvester.harvestFrequency"); - if (harvestInterval == 0) + status = HARVESTER_STATUS_RUNNING; + + // Stage #1: if something is ready for harvest, push it onto the ready stack, mark it as "queued" + mainContext = new Context(); + List<Integer> cids = HarvestedCollection.findReady(mainContext); + log.info("Collections ready for immediate harvest: " + cids.toString()); + + for (Integer cid : cids) { + addThread(cid); + } + + // Stage #2: start up all the threads currently in the queue up to the maximum number + while (!harvestThreads.isEmpty()) { + synchronized(HarvestScheduler.class) { + activeThreads++; + } + Thread activeThread = new Thread(harvestThreads.pop()); + activeThread.start(); + log.info("Thread started: " + activeThread.toString()); + + /* Wait while the number of threads running is greater than or equal to max */ + while (activeThreads >= maxActiveThreads) { + /* Wait a second */ + Thread.sleep(1000); + } + } + + // Finally, wait for the last few remaining threads to finish + // TODO: this step might be unnecessary. Theoretically a single very long harvest process + // could then lock out all the other ones from starting on their next iteration. + // FIXME: also, this might lead to a situation when a single thread getting stuck without + // throwing an exception would shut down the whole scheduler + while (activeThreads != 0) { + /* Wait a second */ + Thread.sleep(1000); + } + + // Commit everything + try { + mainContext.commit(); + mainContext.complete(); + log.info("Done with iteration " + i); + } catch (SQLException e) { + e.printStackTrace(); + mainContext.abort(); + } + + } + catch (Exception e) { + log.error("Exception on iteration: " + i); + e.printStackTrace(); + } + + // Stage #3: figure out how long until the next iteration and wait + try { + Context tempContext = new Context(); + int nextCollectionId = HarvestedCollection.findOldestHarvest(tempContext); + HarvestedCollection hc = HarvestedCollection.find(tempContext, nextCollectionId); + + int harvestInterval = ConfigurationManager.getIntProperty("oai", "harvester.harvestFrequency"); + if (harvestInterval == 0) { harvestInterval = 720; } - Date nextTime; - long nextHarvest = 0; - if (hc != null) { - Calendar calendar = Calendar.getInstance(); - calendar.setTime(hc.getHarvestDate()); - calendar.add(Calendar.MINUTE, harvestInterval); - nextTime = calendar.getTime(); - nextHarvest = nextTime.getTime() + - new Date().getTime(); - } - - long upperBound = Math.min(nextHarvest,maxHeartbeat); - long delay = Math.max(upperBound, minHeartbeat) + 1000; - - - tempContext.complete(); - - status = HARVESTER_STATUS_SLEEPING; - synchronized(lock) { - lock.wait(delay); - } - } - catch (InterruptedException ie) { - log.warn("Interrupt: " + ie.getMessage()); - } - catch (SQLException e) { - e.printStackTrace(); - } - - i++; - } - } - - - /** - * Adds a thread to the ready stack. Can also be called externally to queue up a collection - * for harvesting before it is "due" for another cycle. This allows starting a harvest process - * from the UI that still "plays nice" with these thread mechanics instead of making an - * asynchronous call to runHarvest(). - */ - public static void addThread(int collecionID) throws SQLException, IOException, AuthorizeException { - log.debug("****** Entered the addThread method. Active threads: " + harvestThreads.toString()); - Context subContext = new Context(); - //subContext.setCurrentUser(harvestAdmin); - - HarvestedCollection hc = HarvestedCollection.find(subContext, collecionID); - hc.setHarvestStatus(HarvestedCollection.STATUS_QUEUED); - hc.update(); - subContext.commit(); - - HarvestThread ht = new HarvestThread(subContext, hc); - harvestThreads.push(ht); - - log.debug("****** Queued up a thread. Active threads: " + harvestThreads.toString()); - log.info("Thread queued up: " + ht.toString()); - } - - } - - /** - * A harvester thread used to execute a single harvest cycle on a collection - * @author alexey - */ - private static class HarvestThread extends Thread { - Context context; - HarvestedCollection hc; - - - HarvestThread(Context context, HarvestedCollection hc) throws SQLException { - this.context = context; - this.hc = hc; - } - - public void run() { - log.info("Thread for collection " + hc.getCollectionId() + " starts."); - runHarvest(); - } - - private void runHarvest() - { - Collection dso = null; - try { - dso = Collection.find(context, hc.getCollectionId()); - OAIHarvester harvester = new OAIHarvester(context, dso, hc); - harvester.runHarvest(); - } + Date nextTime; + long nextHarvest = 0; + if (hc != null) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(hc.getHarvestDate()); + calendar.add(Calendar.MINUTE, harvestInterval); + nextTime = calendar.getTime(); + nextHarvest = nextTime.getTime() + - new Date().getTime(); + } + + long upperBound = Math.min(nextHarvest,maxHeartbeat); + long delay = Math.max(upperBound, minHeartbeat) + 1000; + + + tempContext.complete(); + + status = HARVESTER_STATUS_SLEEPING; + synchronized(lock) { + lock.wait(delay); + } + } + catch (InterruptedException ie) { + log.warn("Interrupt: " + ie.getMessage()); + } + catch (SQLException e) { + e.printStackTrace(); + } + + i++; + } + } + + + /** + * Adds a thread to the ready stack. Can also be called externally to queue up a collection + * for harvesting before it is "due" for another cycle. This allows starting a harvest process + * from the UI that still "plays nice" with these thread mechanics instead of making an + * asynchronous call to runHarvest(). + */ + public static void addThread(int collecionID) throws SQLException, IOException, AuthorizeException { + log.debug("****** Entered the addThread method. Active threads: " + harvestThreads.toString()); + Context subContext = new Context(); + subContext.setCurrentUser(harvestAdmin); + + HarvestedCollection hc = HarvestedCollection.find(subContext, collecionID); + hc.setHarvestStatus(HarvestedCollection.STATUS_QUEUED); + hc.update(); + subContext.commit(); + + HarvestThread ht = new HarvestThread(subContext, hc); + harvestThreads.push(ht); + + log.debug("****** Queued up a thread. Active threads: " + harvestThreads.toString()); + log.info("Thread queued up: " + ht.toString()); + } + + } + + /** + * A harvester thread used to execute a single harvest cycle on a collection + * @author alexey + */ + private static class HarvestThread extends Thread { + Context context; + HarvestedCollection hc; + + + HarvestThread(Context context, HarvestedCollection hc) throws SQLException { + this.context = context; + this.hc = hc; + } + + public void run() { + log.info("Thread for collection " + hc.getCollectionId() + " starts."); + runHarvest(); + } + + private void runHarvest() + { + Collection dso = null; + try { + dso = Collection.find(context, hc.getCollectionId()); + OAIHarvester harvester = new OAIHarvester(context, dso, hc); + harvester.runHarvest(); + } catch (RuntimeException e) { log.error("Runtime exception in thread: " + this.toString()); log.error(e.getMessage() + " " + e.getCause()); @@ -1358,35 +1374,34 @@ public class OAIHarvester { hc.setHarvestStatus(HarvestedCollection.STATUS_UNKNOWN_ERROR); } catch (Exception ex) { - log.error("General exception in thread: " + this.toString()); - log.error(ex.getMessage() + " " + ex.getCause()); - hc.setHarvestMessage("Error occured while generating an OAI response"); - hc.setHarvestStatus(HarvestedCollection.STATUS_UNKNOWN_ERROR); - } - finally - { - try { - hc.update(); - context.restoreAuthSystemState(); - context.complete(); - } + log.error("General exception in thread: " + this.toString()); + log.error(ex.getMessage() + " " + ex.getCause()); + hc.setHarvestMessage("Error occured while generating an OAI response"); + hc.setHarvestStatus(HarvestedCollection.STATUS_UNKNOWN_ERROR); + } + finally + { + try { + hc.update(); + context.restoreAuthSystemState(); + context.complete(); + } catch (RuntimeException e) { log.error("Unexpected exception while recovering from a harvesting error: " + e.getMessage(), e); context.abort(); } - catch (Exception e) { - log.error("Unexpected exception while recovering from a harvesting error: " + e.getMessage(), e); - context.abort(); - } - - synchronized (HarvestScheduler.class) { - HarvestScheduler.activeThreads--; - } - } - - log.info("Thread for collection " + hc.getCollectionId() + " completes."); - } - } + catch (Exception e) { + log.error("Unexpected exception while recovering from a harvesting error: " + e.getMessage(), e); + context.abort(); + } -} + synchronized (HarvestScheduler.class) { + HarvestScheduler.activeThreads--; + } + } + log.info("Thread for collection " + hc.getCollectionId() + " completes."); + } + } + +} diff --git a/dspace-api/src/main/java/org/dspace/identifier/IdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/IdentifierProvider.java index 86369d73418472e81ac8f5a261448e4a38882265..3f147c3288db3c8d0314792174911981ee6986fb 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/IdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/IdentifierProvider.java @@ -36,23 +36,101 @@ public abstract class IdentifierProvider { this.parentService = parentService; } + /** + * Can this provider provide identifiers of a given type? + * + * @param identifier requested type. + * @return true if the given type is assignable from this provider's type. + */ public abstract boolean supports(Class<? extends Identifier> identifier); + /** + * Can this provider provide identifiers of a given type? + * + * @param identifier requested type. + * @return true if this provider can provide the named type of identifier. + */ public abstract boolean supports(String identifier); + /** + * Create and apply an identifier to a DSpaceObject. + * + * @param context + * @param item object to be named. + * @return existing identifier of {@code item} if it has one, else a new identifier. + * @throws IdentifierException + */ public abstract String register(Context context, DSpaceObject item) throws IdentifierException; + /** + * Create an identifier for a DSpaceObject. + * + * @param context + * @param dso object to be named. + * @return existing identifier of {@code dso} if it has one, else a new identifier. + * @throws IdentifierException + */ public abstract String mint(Context context, DSpaceObject dso) throws IdentifierException; + /** + * Find the object named by a given identifier. + * + * @param context + * @param identifier to be resolved. + * @param attributes additional information for resolving {@code identifier}. + * @return the named object. + * @throws IdentifierNotFoundException + * @throws IdentifierNotResolvableException + */ public abstract DSpaceObject resolve(Context context, String identifier, String... attributes) throws IdentifierNotFoundException, IdentifierNotResolvableException;; + /** + * Return the identifier for a DSpaceObject. + * + * @param context + * @param object The object to be looked up. + * @return identifier for {@code object}. + * @throws IdentifierNotFoundException + * @throws IdentifierNotResolvableException + */ public abstract String lookup(Context context, DSpaceObject object) throws IdentifierNotFoundException, IdentifierNotResolvableException;; + /** + * Unbind this type of identifier(s) from an object. + * + * @param context + * @param dso object to lose its identity. + * @throws IdentifierException + */ public abstract void delete(Context context, DSpaceObject dso) throws IdentifierException; + /** + * Unbind the given identifier from an object. + * + * @param context + * @param dso object to be de-identified. + * @param identifier to be removed. + * @throws IdentifierException + */ public abstract void delete(Context context, DSpaceObject dso, String identifier) throws IdentifierException; + /** + * Set an object's identifier. + * + * @param context + * @param dso object to be identified. + * @param identifier to be set on the object. + * @throws IdentifierException + */ public abstract void reserve(Context context, DSpaceObject dso, String identifier) throws IdentifierException; - public abstract void register(Context context, DSpaceObject object, String identifier) throws IdentifierException; + /** + * Create a specific identifier and apply it to an object. + * + * @param context + * @param object to be identified. + * @param identifier to be created. + */ + public abstract void register(Context context, DSpaceObject object, String identifier) + throws IdentifierException; } diff --git a/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java b/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java index d15414204ca71350b4dcfc59f9dfc6138fee50a1..122a9ba3c616ad4792979263e103565c78f701e0 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java +++ b/dspace-api/src/main/java/org/dspace/identifier/IdentifierServiceImpl.java @@ -88,9 +88,19 @@ public class IdentifierServiceImpl implements IdentifierService { //We need to commit our context because one of the providers might require the handle created above // Next resolve all other services + boolean registered = false; for (IdentifierProvider service : providers) { - service.register(context, object, identifier); + if (service.supports(identifier)) + { + service.register(context, object, identifier); + registered = true; + } + } + if (!registered) + { + throw new IdentifierException("Cannot register identifier: Didn't " + + "find a provider that supports this identifier."); } //Update our item object.update(); diff --git a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java index fc0cbd1fbe33da7802ff035892ce1be84726b42e..f4bb4c09229e08e4d7ce98efe82ceb7bd9cf7b8f 100644 --- a/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java +++ b/dspace-api/src/main/java/org/dspace/identifier/VersionedHandleIdentifierProvider.java @@ -545,7 +545,7 @@ public class VersionedHandleIdentifierProvider extends IdentifierProvider { protected String getCanonical(Item item) { String canonical = item.getHandle(); - if( canonical.lastIndexOf(DOT)!=-1) + if( canonical.matches(".*/.*\\.\\d+") && canonical.lastIndexOf(DOT)!=-1) { canonical = canonical.substring(0, canonical.lastIndexOf(DOT)); } @@ -556,7 +556,7 @@ public class VersionedHandleIdentifierProvider extends IdentifierProvider { protected String getCanonical(String identifier) { String canonical = identifier; - if( canonical.lastIndexOf(DOT)!=-1) + if( canonical.matches(".*/.*\\.\\d+") && canonical.lastIndexOf(DOT)!=-1) { canonical = canonical.substring(0, canonical.lastIndexOf(DOT)); } diff --git a/dspace-api/src/main/java/org/dspace/license/CCLookup.java b/dspace-api/src/main/java/org/dspace/license/CCLookup.java index d0fe7f1453ca0915641c31c6a7eeebd82323876d..8b40952854aacce6983515c2e6772cdc159f79b0 100644 --- a/dspace-api/src/main/java/org/dspace/license/CCLookup.java +++ b/dspace-api/src/main/java/org/dspace/license/CCLookup.java @@ -116,7 +116,7 @@ public class CCLookup { try { JDOMXPath xp_Licenses = new JDOMXPath("//licenses/license"); JDOMXPath xp_LicenseID = new JDOMXPath("@id"); - URL classUrl = new URL(this.cc_root + "/classes"); + URL classUrl = new URL(this.cc_root + "/?locale=" + language); Document classDoc = this.parser.build(classUrl); // extract the identifiers and labels using XPath List<Element> results = xp_Licenses.selectNodes(classDoc); @@ -155,7 +155,7 @@ public class CCLookup { * @see CCLicense * */ - public Collection<CCLicenseField> getLicenseFields(String license) { + public Collection<CCLicenseField> getLicenseFields(String license, String language) { JDOMXPath xp_LicenseField; JDOMXPath xp_LicenseID; @@ -185,7 +185,7 @@ public class CCLookup { // retrieve and parse the license class document try { - classUrl = new URL(this.cc_root + "/license/" + license); + classUrl = new URL(this.cc_root + "/license/" + license + "?locale=" + language); } catch (Exception err) { // do nothing... but we should return null; diff --git a/dspace-api/src/main/java/org/dspace/license/CreativeCommons.java b/dspace-api/src/main/java/org/dspace/license/CreativeCommons.java index 476483aba14b7baab597576e69cf43a15002e1ac..fb7f34f708f8bb3293bcc2da80215f085cb83d41 100644 --- a/dspace-api/src/main/java/org/dspace/license/CreativeCommons.java +++ b/dspace-api/src/main/java/org/dspace/license/CreativeCommons.java @@ -20,6 +20,7 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; @@ -61,7 +62,7 @@ public class CreativeCommons String proxyHost = ConfigurationManager.getProperty("http.proxy.host"); String proxyPort = ConfigurationManager.getProperty("http.proxy.port"); - if ((proxyHost != null) && (proxyPort != null)) + if (StringUtils.isNotBlank(proxyHost) && StringUtils.isNotBlank(proxyPort)) { System.setProperty("http.proxyHost", proxyHost); System.setProperty("http.proxyPort", proxyPort); diff --git a/dspace-api/src/main/java/org/dspace/search/DSAnalyzer.java b/dspace-api/src/main/java/org/dspace/search/DSAnalyzer.java index 182a604676f2a719183b350c4d212e800bd17809..62ca7928e02f2cfa6d3b6095c8ce3903a9117eb6 100644 --- a/dspace-api/src/main/java/org/dspace/search/DSAnalyzer.java +++ b/dspace-api/src/main/java/org/dspace/search/DSAnalyzer.java @@ -10,10 +10,11 @@ package org.dspace.search; import java.io.Reader; import java.util.Set; -import org.apache.lucene.analysis.LowerCaseFilter; -import org.apache.lucene.analysis.PorterStemFilter; -import org.apache.lucene.analysis.StopFilter; -import org.apache.lucene.analysis.StopwordAnalyzerBase; +import org.apache.lucene.analysis.core.LowerCaseFilter; +import org.apache.lucene.analysis.en.PorterStemFilter; +import org.apache.lucene.analysis.core.StopFilter; +import org.apache.lucene.analysis.util.CharArraySet; +import org.apache.lucene.analysis.util.StopwordAnalyzerBase; import org.apache.lucene.analysis.Tokenizer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.standard.StandardFilter; @@ -23,7 +24,15 @@ import org.dspace.core.ConfigurationManager; /** * Custom Lucene Analyzer that combines the standard filter, lowercase filter, * stemming and stopword filters. + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class DSAnalyzer extends StopwordAnalyzerBase { protected final Version matchVersion; @@ -50,7 +59,7 @@ public class DSAnalyzer extends StopwordAnalyzerBase /* * Stop table */ - protected final Set stopSet; + protected final CharArraySet stopSet; /** * Builds an analyzer @@ -66,7 +75,7 @@ public class DSAnalyzer extends StopwordAnalyzerBase protected TokenStreamComponents createComponents(String fieldName, Reader reader) { final Tokenizer source = new DSTokenizer(matchVersion, reader); TokenStream result = new StandardFilter(matchVersion, source); - + result = new LowerCaseFilter(matchVersion, result); result = new StopFilter(matchVersion, result, stopSet); result = new PorterStemFilter(result); diff --git a/dspace-api/src/main/java/org/dspace/search/DSIndexer.java b/dspace-api/src/main/java/org/dspace/search/DSIndexer.java index 69b6ea988b2ef4c1782ba870336644570967723b..8855a2ef16fa93efd15a0ca5cbd25154121952f4 100644 --- a/dspace-api/src/main/java/org/dspace/search/DSIndexer.java +++ b/dspace-api/src/main/java/org/dspace/search/DSIndexer.java @@ -25,8 +25,8 @@ import java.util.Map; import java.util.TimeZone; import java.text.SimpleDateFormat; import java.text.ParseException; - import java.util.List; + import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.OptionBuilder; @@ -35,16 +35,21 @@ import org.apache.commons.cli.PosixParser; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.apache.lucene.analysis.Analyzer; +import org.apache.lucene.analysis.miscellaneous.LimitTokenCountAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.DateTools; +import org.apache.lucene.index.DirectoryReader; +import org.apache.lucene.index.DocsEnum; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; +import org.apache.lucene.index.IndexableField; +import org.apache.lucene.index.MultiFields; import org.apache.lucene.index.Term; -import org.apache.lucene.index.TermDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; +import org.apache.lucene.util.Bits; import org.apache.lucene.util.Version; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; @@ -65,7 +70,6 @@ import org.dspace.core.LogManager; import org.dspace.handle.HandleManager; import org.dspace.sort.SortOption; import org.dspace.sort.OrderFormat; - import org.dspace.app.util.DCInputsReaderException; import org.dspace.app.util.Util; @@ -74,21 +78,29 @@ import org.dspace.app.util.Util; * collections, communities, etc. It is meant to either be invoked from the * command line (see dspace/bin/index-all) or via the indexContent() methods * within DSpace. - * + * * As of 1.4.2 this class has new incremental update of index functionality * and better detection of locked state thanks to Lucene 2.1 moving write.lock. * It will attempt to attain a lock on the index in the event that an update * is requested and will wait a maximum of 30 seconds (a worst case scenario) - * to attain the lock before giving up and logging the failure to log4j and - * to the DSpace administrator email account. - * + * to attain the lock before giving up and logging the failure to log4j and + * to the DSpace administrator email account. + * * The Administrator can choose to run DSIndexer in a cron that * repeats regularly, a failed attempt to index from the UI will be "caught" up * on in that cron. - * + * * @author Mark Diggory * @author Graham Triggs + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class DSIndexer { private static final Logger log = Logger.getLogger(DSIndexer.class); @@ -103,7 +115,7 @@ public class DSIndexer private static int batchFlushAfterDocuments = ConfigurationManager.getIntProperty("search.batch.documents", 20); private static boolean batchProcessingMode = false; - static final Version luceneVersion = Version.LUCENE_35; + static final Version luceneVersion = Version.LUCENE_44; // Class to hold the index configuration (one instance per config line) private static class IndexConfig @@ -127,11 +139,11 @@ public class DSIndexer this.type = type; } } - + private static String indexDirectory = ConfigurationManager.getProperty("search.dir"); - + private static int maxfieldlength = -1; - + // TODO: Support for analyzers per language, or multiple indices /** The analyzer for this DSpace instance */ private static volatile Analyzer analyzer = null; @@ -154,13 +166,13 @@ public class DSIndexer }; static { - + // calculate maxfieldlength if (ConfigurationManager.getProperty("search.maxfieldlength") != null) { maxfieldlength = ConfigurationManager.getIntProperty("search.maxfieldlength"); } - + // read in indexes from the config ArrayList<String> indexConfigList = new ArrayList<String>(); @@ -169,24 +181,24 @@ public class DSIndexer { indexConfigList.add(ConfigurationManager.getProperty("search.index." + i)); } - + if (indexConfigList.size() > 0) { indexConfigArr = new IndexConfig[indexConfigList.size()]; - + for (int i = 0; i < indexConfigList.size(); i++) { indexConfigArr[i] = new IndexConfig(); String index = indexConfigList.get(i); - + String[] configLine = index.split(":"); - + indexConfigArr[i].indexName = configLine[0]; - + // Get the schema, element and qualifier for the index // TODO: Should check valid schema, element, qualifier? String[] parts = configLine[1].split("\\."); - + switch (parts.length) { case 3: @@ -208,7 +220,7 @@ public class DSIndexer } } } - + /* * Increase the default write lock so that Indexing can be interrupted. */ @@ -219,7 +231,7 @@ public class DSIndexer */ try { - if (!IndexReader.indexExists(FSDirectory.open(new File(indexDirectory)))) + if (!DirectoryReader.indexExists(FSDirectory.open(new File(indexDirectory)))) { if (!new File(indexDirectory).mkdirs()) @@ -246,10 +258,10 @@ public class DSIndexer /** * If the handle for the "dso" already exists in the index, and - * the "dso" has a lastModified timestamp that is newer than - * the document in the index then it is updated, otherwise a + * the "dso" has a lastModified timestamp that is newer than + * the document in the index then it is updated, otherwise a * new document is added. - * + * * @param context Users Context * @param dso DSpace Object (Item, Collection or Community * @throws SQLException @@ -261,10 +273,10 @@ public class DSIndexer } /** * If the handle for the "dso" already exists in the index, and - * the "dso" has a lastModified timestamp that is newer than - * the document in the index then it is updated, otherwise a + * the "dso" has a lastModified timestamp that is newer than + * the document in the index then it is updated, otherwise a * new document is added. - * + * * @param context Users Context * @param dso DSpace Object (Item, Collection or Community * @param force Force update even if not stale. @@ -290,7 +302,7 @@ public class DSIndexer /** * unIndex removes an Item, Collection, or Community only works if the * DSpaceObject has a handle (uses the handle for its unique ID) - * + * * @param context DSpace context * @param dso DSpace Object, can be Community, Item, or Collection * @throws SQLException @@ -311,9 +323,9 @@ public class DSIndexer /** * Unindex a Document in the Lucene Index. - * + * * @param context - * @param handle + * @param handle * @throws SQLException * @throws IOException */ @@ -336,7 +348,7 @@ public class DSIndexer // handle!"); } } - + /** * reIndexContent removes something from the index, then re-indexes it * @@ -356,10 +368,10 @@ public class DSIndexer emailException(exception); } } - + /** * create full index - wiping old index - * + * * @param c context to use */ public static void createIndex(Context c) throws SQLException, IOException @@ -367,15 +379,15 @@ public class DSIndexer /* Create a new index, blowing away the old. */ openIndex(true).close(); - + /* Reindex all content preemptively. */ DSIndexer.updateIndex(c, true); } - + /** - * Optimize the existing index. Important to do regularly to reduce + * Optimize the existing index. Important to do regularly to reduce * filehandle usage and keep performance fast! - * + * * @param c Users Context * @throws SQLException * @throws IOException @@ -387,7 +399,11 @@ public class DSIndexer try { flushIndexingTaskQueue(writer); - writer.optimize(); + //With lucene 4.0 this method has been deleted , as it is horribly inefficient and very + //rarely justified. Lucene's multi-segment search performance has improved + //over time, and the default TieredMergePolicy now targets segments with + //deletions. For more info see http://blog.trifork.com/2011/11/21/simon-says-optimize-is-bad-for-you/ + //writer.optimize(); } finally { @@ -396,13 +412,13 @@ public class DSIndexer } /** - * When invoked as a command-line tool, creates, updates, removes + * When invoked as a command-line tool, creates, updates, removes * content from the whole index * * @param args * the command-line arguments, none used - * @throws IOException - * @throws SQLException + * @throws IOException + * @throws SQLException */ public static void main(String[] args) throws SQLException, IOException { @@ -508,25 +524,25 @@ public class DSIndexer * Iterates over all Items, Collections and Communities. And updates * them in the index. Uses decaching to control memory footprint. * Uses indexContent and isStale ot check state of item in index. - * + * * @param context */ public static void updateIndex(Context context) { updateIndex(context,false); } - + /** * Iterates over all Items, Collections and Communities. And updates * them in the index. Uses decaching to control memory footprint. * Uses indexContent and isStale to check state of item in index. - * + * * At first it may appear counterintuitive to have an IndexWriter/Reader * opened and closed on each DSO. But this allows the UI processes * to step in and attain a lock and write to the index even if other * processes/jvms are running a reindex. - * + * * @param context - * @param force + * @param force */ public static void updateIndex(Context context, boolean force) { try @@ -568,24 +584,30 @@ public class DSIndexer log.error(e.getMessage(), e); } } - + /** - * Iterates over all documents in the Lucene index and verifies they + * Iterates over all documents in the Lucene index and verifies they * are in database, if not, they are removed. - * + * * @param context - * @throws IOException - * @throws SQLException + * @throws IOException + * @throws SQLException */ public static void cleanIndex(Context context) throws IOException, SQLException { IndexReader reader = DSQuery.getIndexReader(); + Bits liveDocs = MultiFields.getLiveDocs(reader); + for(int i = 0 ; i < reader.numDocs(); i++) { - if(!reader.isDeleted(i)) - { - Document doc = reader.document(i); + if (!liveDocs.get(i)) + { + // document is deleted... + log.debug("Encountered deleted doc: " + i); + } + else { + Document doc = reader.document(i); String handle = doc.get("handle"); if (!StringUtils.isEmpty(handle)) { @@ -603,14 +625,10 @@ public class DSIndexer log.debug("Keeping: " + handle); } } - } - else - { - log.debug("Encountered deleted doc: " + i); - } + } } } - + /** * Get the Lucene analyzer to use according to current configuration (or * default). TODO: Should have multiple analyzers (and maybe indices?) for @@ -843,8 +861,8 @@ public class DSIndexer String recipient = ConfigurationManager .getProperty("alert.recipient"); - if (recipient != null) { - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(Locale.getDefault(), "internal_error")); + if (StringUtils.isNotBlank(recipient)) { + Email email = Email.getEmail(I18nUtil.getEmailFilename(Locale.getDefault(), "internal_error")); email.addRecipient(recipient); email.addArgument(ConfigurationManager .getProperty("dspace.url")); @@ -871,11 +889,11 @@ public class DSIndexer } } - + /** * Is stale checks the lastModified time stamp in the database and the index * to determine if the index is stale. - * + * * @param lastModified * @throws SQLException * @throws IOException @@ -883,28 +901,32 @@ public class DSIndexer private static boolean requiresIndexing(Term t, Date lastModified) throws SQLException, IOException { - + boolean reindexItem = false; boolean inIndex = false; - + IndexReader ir = DSQuery.getIndexReader(); - - TermDocs docs = ir.termDocs(t); - - while(docs.next()) - { - inIndex = true; - int id = docs.doc(); - Document doc = ir.document(id); - - Field lastIndexed = doc.getField(LAST_INDEXED_FIELD); - - if (lastIndexed == null || Long.parseLong(lastIndexed.stringValue()) < - lastModified.getTime()) { - reindexItem = true; - } - } + Bits liveDocs = MultiFields.getLiveDocs(ir); + DocsEnum docs = MultiFields.getTermDocsEnum(ir, liveDocs, t.field(), t.bytes()); + + int id; + if (docs != null) + { + while ((id = docs.nextDoc()) != DocsEnum.NO_MORE_DOCS) + { + inIndex = true; + Document doc = ir.document(id); + + IndexableField lastIndexed = doc.getField(LAST_INDEXED_FIELD); + if (lastIndexed == null + || Long.parseLong(lastIndexed.stringValue()) < lastModified + .getTime()) + { + reindexItem = true; + } + } + } return reindexItem || !inIndex; } @@ -915,25 +937,28 @@ public class DSIndexer throws IOException { Directory dir = FSDirectory.open(new File(indexDirectory)); - IndexWriterConfig iwc = new IndexWriterConfig(luceneVersion, getAnalyzer()); - if(wipeExisting){ - iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE); - }else{ - iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); - } - - IndexWriter writer = new IndexWriter(dir, iwc); - + + LimitTokenCountAnalyzer decoratorAnalyzer = null; /* Set maximum number of terms to index if present in dspace.cfg */ if (maxfieldlength == -1) { - writer.setMaxFieldLength(Integer.MAX_VALUE); + decoratorAnalyzer = new LimitTokenCountAnalyzer(getAnalyzer(), Integer.MAX_VALUE); } else { - writer.setMaxFieldLength(maxfieldlength); + decoratorAnalyzer = new LimitTokenCountAnalyzer(getAnalyzer(), maxfieldlength); } + + IndexWriterConfig iwc = new IndexWriterConfig(luceneVersion, decoratorAnalyzer); + if(wipeExisting){ + iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE); + }else{ + iwc.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND); + } + + IndexWriter writer = new IndexWriter(dir, iwc); + return writer; } @@ -1069,7 +1094,7 @@ public class DSIndexer mydc = item.getMetadata(indexConfigArr[i].schema, indexConfigArr[i].element, indexConfigArr[i].qualifier, Item.ANY); } - + //Index the controlled vocabularies localized display values for all localized input-forms.xml (e.g. input-forms_el.xml) if ("inputform".equalsIgnoreCase(indexConfigArr[i].type)){ @@ -1110,7 +1135,7 @@ public class DSIndexer } - + for (j = 0; j < mydc.length; j++) { if (!StringUtils.isEmpty(mydc[j].value)) @@ -1389,7 +1414,7 @@ public class DSIndexer /** * Helper function to retrieve a date using a best guess of the potential date encodings on a field - * + * * @param t * @return */ @@ -1441,7 +1466,7 @@ public class DSIndexer log.error("Unable to parse date format", pe); } } - + return null; } diff --git a/dspace-api/src/main/java/org/dspace/search/DSNonStemmingAnalyzer.java b/dspace-api/src/main/java/org/dspace/search/DSNonStemmingAnalyzer.java index 8b50d78d48dd34e120bb565e6078979b05c2cb39..c0be70b225ac2eb7643c29f5a61d1299c79024b8 100644 --- a/dspace-api/src/main/java/org/dspace/search/DSNonStemmingAnalyzer.java +++ b/dspace-api/src/main/java/org/dspace/search/DSNonStemmingAnalyzer.java @@ -9,8 +9,8 @@ package org.dspace.search; import java.io.Reader; -import org.apache.lucene.analysis.LowerCaseFilter; -import org.apache.lucene.analysis.StopFilter; +import org.apache.lucene.analysis.core.LowerCaseFilter; +import org.apache.lucene.analysis.core.StopFilter; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.Tokenizer; import org.apache.lucene.analysis.standard.StandardFilter; @@ -20,7 +20,15 @@ import org.apache.lucene.util.Version; * Custom Lucene Analyzer that combines the standard filter, lowercase filter * and stopword filter. Intentionally omits the stemming filter (which is used * by DSAnalyzer) + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class DSNonStemmingAnalyzer extends DSAnalyzer { /** diff --git a/dspace-api/src/main/java/org/dspace/search/DSQuery.java b/dspace-api/src/main/java/org/dspace/search/DSQuery.java index ae4831f9ed0a71f75e24fd9de5f8fb384200a3dc..1c7d32fe3b604a335a7c66c764bd05be17be9fad 100644 --- a/dspace-api/src/main/java/org/dspace/search/DSQuery.java +++ b/dspace-api/src/main/java/org/dspace/search/DSQuery.java @@ -16,10 +16,11 @@ import java.util.List; import org.apache.log4j.Logger; import org.apache.lucene.document.Document; +import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; -import org.apache.lucene.queryParser.ParseException; -import org.apache.lucene.queryParser.QueryParser; -import org.apache.lucene.queryParser.TokenMgrError; +import org.apache.lucene.queryparser.classic.ParseException; +import org.apache.lucene.queryparser.classic.QueryParser; +import org.apache.lucene.queryparser.classic.TokenMgrError; import org.apache.lucene.search.BooleanQuery; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; @@ -44,7 +45,14 @@ import org.dspace.sort.SortOption; * DSIndexer contains various static methods for performing queries on indices, * for collections and communities. * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class DSQuery { // Result types @@ -221,16 +229,16 @@ public class DSQuery if (args.getSortOption() == null) { SortField[] sortFields = new SortField[] { - new SortField("search.resourcetype", SortField.INT, true), - new SortField(null, SortField.SCORE, SortOption.ASCENDING.equals(args.getSortOrder())) + new SortField("search.resourcetype", SortField.Type.INT, true), + new SortField(null, SortField.FIELD_SCORE.getType(), SortOption.ASCENDING.equals(args.getSortOrder())) }; hits = searcher.search(myquery, max, new Sort(sortFields)); } else { SortField[] sortFields = new SortField[] { - new SortField("search.resourcetype", SortField.INT, true), - new SortField("sort_" + args.getSortOption().getName(), SortField.STRING, SortOption.DESCENDING.equals(args.getSortOrder())), + new SortField("search.resourcetype", SortField.Type.INT, true), + new SortField("sort_" + args.getSortOption().getName(), SortField.Type.STRING, SortOption.DESCENDING.equals(args.getSortOrder())), SortField.FIELD_SCORE }; hits = searcher.search(myquery, max, new Sort(sortFields)); @@ -396,7 +404,7 @@ public class DSQuery { try { - searcher.close(); + searcher.getIndexReader().close(); searcher = null; } catch (IOException ioe) @@ -439,13 +447,13 @@ public class DSQuery // If it has, we need to close the existing searcher - we will open a new one later Directory searchDir = FSDirectory.open(new File(indexDir)); - - if (searcher != null && lastModified != IndexReader.getCurrentVersion(searchDir)) + DirectoryReader reader = DirectoryReader.open(searchDir); + if (searcher != null && lastModified != reader.getVersion()) { try { // Close the cached IndexSearcher - searcher.close(); + searcher.getIndexReader().close(); } catch (IOException ioe) { @@ -462,30 +470,11 @@ public class DSQuery // There is no existing searcher - either this is the first execution, // or the index has been updated and we closed the old index. if (searcher == null) - { + { // So, open a new searcher - lastModified = IndexReader.getCurrentVersion(searchDir); - String osName = System.getProperty("os.name"); - if (osName != null && osName.toLowerCase().contains("windows")) - { - searcher = new IndexSearcher(searchDir){ - /* - * TODO: Has Lucene fixed this bug yet? - * Lucene doesn't release read locks in - * windows properly on finalize. Our hack - * extend IndexSearcher to force close(). - */ - @Override - protected void finalize() throws Throwable { - this.close(); - super.finalize(); - } - }; - } - else - { - searcher = new IndexSearcher(searchDir); - } + lastModified = reader.getVersion(); + searcher = new IndexSearcher(reader); + } return searcher; diff --git a/dspace-api/src/main/java/org/dspace/search/DSTokenizer.java b/dspace-api/src/main/java/org/dspace/search/DSTokenizer.java index ad0245a976a0ee168c72ebb81b06422efdd8160e..215a653391b36793ed17f78fe8511a21ca211431 100644 --- a/dspace-api/src/main/java/org/dspace/search/DSTokenizer.java +++ b/dspace-api/src/main/java/org/dspace/search/DSTokenizer.java @@ -9,13 +9,21 @@ package org.dspace.search; import java.io.Reader; -import org.apache.lucene.analysis.CharTokenizer; +import org.apache.lucene.analysis.util.CharTokenizer; import org.apache.lucene.util.Version; /** * Customized Lucene Tokenizer, since the standard one rejects numbers from * indexing/querying. + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public final class DSTokenizer extends CharTokenizer { /** diff --git a/dspace-api/src/main/java/org/dspace/search/IndexingTask.java b/dspace-api/src/main/java/org/dspace/search/IndexingTask.java index dc8cbc442fa8a4f6ee64c895d6b3769fde026b59..e3ed938dc2dbb6795ba922757ee79c2c17a3ae2d 100644 --- a/dspace-api/src/main/java/org/dspace/search/IndexingTask.java +++ b/dspace-api/src/main/java/org/dspace/search/IndexingTask.java @@ -10,6 +10,15 @@ package org.dspace.search; import org.apache.lucene.document.Document; import org.apache.lucene.index.Term; +/** +* @deprecated Since DSpace 4 the system use an abstraction layer named +* Discovery to provide access to different search provider. The +* legacy system build upon Apache Lucene is likely to be removed in +* a future version. If you are interested in use Lucene as backend +* for the DSpace search system please consider to build a Lucene +* implementation of the Discovery interfaces +*/ +@Deprecated class IndexingTask { enum Action { ADD, UPDATE, DELETE }; diff --git a/dspace-api/src/main/java/org/dspace/search/QueryArgs.java b/dspace-api/src/main/java/org/dspace/search/QueryArgs.java index 11ad49040fc1fbcbaef3ba9357c492b892d0ed60..04dfee6af1f236e5ed546a8023dd2c09b8dfdb56 100644 --- a/dspace-api/src/main/java/org/dspace/search/QueryArgs.java +++ b/dspace-api/src/main/java/org/dspace/search/QueryArgs.java @@ -15,17 +15,25 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.StringTokenizer; + import javax.servlet.http.HttpServletRequest; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.sort.SortOption; - import org.apache.commons.lang.StringUtils; /** * Contains the arguments for a query. Fill it out and pass to the query engine + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class QueryArgs { // the query string diff --git a/dspace-api/src/main/java/org/dspace/search/QueryResults.java b/dspace-api/src/main/java/org/dspace/search/QueryResults.java index 14e4d73b704c9fe5fcc027ea9cb8d850bf8fa9d9..8c53f5abcd85354b2f0d70a5304d30f2cad03a5c 100644 --- a/dspace-api/src/main/java/org/dspace/search/QueryResults.java +++ b/dspace-api/src/main/java/org/dspace/search/QueryResults.java @@ -15,7 +15,15 @@ import org.dspace.core.ConfigurationManager; /** * Contains the results of a query. Use access methods to examine and retrieve * the results. + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class QueryResults { private long queryTime; // time to search (ms) diff --git a/dspace-api/src/main/java/org/dspace/search/SearchConsumer.java b/dspace-api/src/main/java/org/dspace/search/SearchConsumer.java index 903a59f81708ef518900532744f0c8f81ee8929d..6d75cc2a51baae19771ff5b40a792f826c61a456 100644 --- a/dspace-api/src/main/java/org/dspace/search/SearchConsumer.java +++ b/dspace-api/src/main/java/org/dspace/search/SearchConsumer.java @@ -22,7 +22,15 @@ import org.dspace.event.Event; * Class for updating search indices from content events. * * @version $Revision$ + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class SearchConsumer implements Consumer { /** log4j logger */ diff --git a/dspace-api/src/main/java/org/dspace/search/package.html b/dspace-api/src/main/java/org/dspace/search/package.html index e65ca06967b00042ba207b94ae9021600406f040..a9b4df919ddf3c19f569e21886c9864d78c08568 100644 --- a/dspace-api/src/main/java/org/dspace/search/package.html +++ b/dspace-api/src/main/java/org/dspace/search/package.html @@ -20,8 +20,11 @@ <p>Interface to the Lucene search engine, and the 'harvest' API for retrieving items modified within a given date range.</p> <p> -DSpace uses the Jakarta project's Lucene search engine. -<a href="http://jakarta.apache.org/lucene/docs/index.html">Official Lucene Web Site</a> +Warning: Since DSpace 4 the system uses an abstraction layer named Discovery to provide access to different search providers. An <a href="http://lucene.apache.org/solr/">Apache SOLR</a> backend is provided. +</p> +<p> +The legacy DSpace search system uses the Jakarta project's Lucene search engine. +<a href="http://lucene.apache.org/">Official Lucene Web Site</a> </p> </body> diff --git a/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLogger.java b/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLogger.java index 70151960dd0f422398bd71743f8ae9c0c4eb6448..bb74a2478e33b9ccc9913d7628cb75d2cf9860b8 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLogger.java +++ b/dspace-api/src/main/java/org/dspace/statistics/ElasticSearchLogger.java @@ -22,12 +22,14 @@ import org.dspace.statistics.util.DnsLookup; import org.dspace.statistics.util.LocationUtils; import org.dspace.statistics.util.SpiderDetector; import org.elasticsearch.action.ActionFuture; -import org.elasticsearch.action.admin.indices.exists.IndicesExistsRequest; -import org.elasticsearch.action.admin.indices.exists.IndicesExistsResponse; + +import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest; +import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsResponse; +import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequestBuilder; import org.elasticsearch.action.admin.indices.mapping.put.PutMappingResponse; +import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.client.Client; -import org.elasticsearch.client.action.admin.indices.mapping.put.PutMappingRequestBuilder; -import org.elasticsearch.client.action.index.IndexRequestBuilder; + import org.elasticsearch.client.transport.TransportClient; import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.Settings; @@ -242,7 +244,7 @@ public class ElasticSearchLogger { putMappingRequestBuilder.setSource(stringMappingJSON); PutMappingResponse response = putMappingRequestBuilder.execute().actionGet(); - if(!response.getAcknowledged()) { + if(!response.isAcknowledged()) { log.info("Could not define mapping for type ["+indexName+"]/["+indexType+"]"); } else { log.info("Successfully put mapping for ["+indexName+"]/["+indexType+"]"); @@ -379,6 +381,124 @@ public class ElasticSearchLogger { } } + public void post(DSpaceObject dspaceObject, String ip, String userAgent, String xforwarderfor, EPerson currentUser) { + //log.info("DS-ES post for type:"+dspaceObject.getType() + " -- " + dspaceObject.getName()); + + client = ElasticSearchLogger.getInstance().getClient(); + + boolean isSpiderBot = SpiderDetector.isSpider(ip); + + try { + if (isSpiderBot && + !ConfigurationManager.getBooleanProperty("usage-statistics", "logBots", true)) { + return; + } + + + // Save our basic info that we already have + + if (isUseProxies() && xforwarderfor != null) { + /* This header is a comma delimited list */ + for (String xfip : xforwarderfor.split(",")) { + /* proxy itself will sometime populate this header with the same value in + remote address. ordering in spec is vague, we'll just take the last + not equal to the proxy + */ + if (!xforwarderfor.contains(ip)) { + ip = xfip.trim(); + } + } + } + + XContentBuilder docBuilder = null; + + + docBuilder = XContentFactory.jsonBuilder().startObject(); + + + docBuilder.field("ip", ip); + + docBuilder.field("id", dspaceObject.getID()); + + // The numerical constant that represents the DSpaceObject TYPE. i.e. 0=bitstream, 2=item, ... + docBuilder.field("typeIndex", dspaceObject.getType()); + + // The text that represent the DSpaceObject TYPE. i.e. BITSTREAM, ITEM, COLLECTION, COMMUNITY + docBuilder.field("type", Constants.typeText[dspaceObject.getType()]); + + // Save the current time + docBuilder.field("time", DateFormatUtils.format(new Date(), DATE_FORMAT_8601)); + if (currentUser != null) { + docBuilder.field("epersonid", currentUser.getID()); + } + + try { + String dns = DnsLookup.reverseDns(ip); + docBuilder.field("dns", dns.toLowerCase()); + } catch (Exception e) { + log.error("Failed DNS Lookup for IP:" + ip); + log.debug(e.getMessage(), e); + } + + // Save the location information if valid, save the event without + // location information if not valid + Location location = locationService.getLocation(ip); + if (location != null + && !("--".equals(location.countryCode) + && location.latitude == -180 && location.longitude == -180)) { + try { + docBuilder.field("continent", LocationUtils + .getContinentCode(location.countryCode)); + } catch (Exception e) { + System.out + .println("COUNTRY ERROR: " + location.countryCode); + } + docBuilder.field("countryCode", location.countryCode); + docBuilder.field("city", location.city); + docBuilder.field("latitude", location.latitude); + docBuilder.field("longitude", location.longitude); + docBuilder.field("isBot", isSpiderBot); + + if (userAgent != null) { + docBuilder.field("userAgent", userAgent); + } + } + + if (dspaceObject instanceof Bitstream) { + Bitstream bit = (Bitstream) dspaceObject; + Bundle[] bundles = bit.getBundles(); + docBuilder.field("bundleName").startArray(); + for (Bundle bundle : bundles) { + docBuilder.value(bundle.getName()); + } + docBuilder.endArray(); + } + + storeParents(docBuilder, getParents(dspaceObject)); + + docBuilder.endObject(); + + if (docBuilder != null) { + IndexRequestBuilder irb = client.prepareIndex(indexName, indexType) + .setSource(docBuilder); + //log.info("Executing document insert into index"); + if(client == null) { + log.error("Hey, client is null"); + } + irb.execute().actionGet(); + } + + } catch (RuntimeException re) { + log.error("RunTimer in ESL:\n" + ExceptionUtils.getStackTrace(re)); + throw re; + } catch (Exception e) { + log.error(e.getMessage()); + } finally { + client.close(); + } + } + + public static String getClusterName() { return clusterName; } diff --git a/dspace-api/src/main/java/org/dspace/statistics/SolrLogger.java b/dspace-api/src/main/java/org/dspace/statistics/SolrLogger.java index 73f90cc221ee83c3b4cef8854310c2d856bd4ecd..47eba5ddfaf93e345d95a2f8776cc02a80c492fa 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/SolrLogger.java +++ b/dspace-api/src/main/java/org/dspace/statistics/SolrLogger.java @@ -7,7 +7,6 @@ */ package org.dspace.statistics; -import au.com.bytecode.opencsv.CSVParser; import au.com.bytecode.opencsv.CSVReader; import au.com.bytecode.opencsv.CSVWriter; import com.maxmind.geoip.Location; @@ -24,7 +23,7 @@ import org.apache.commons.lang.time.DateFormatUtils; import org.apache.log4j.Logger; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; +import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.apache.solr.client.solrj.request.AbstractUpdateRequest; import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest; import org.apache.solr.client.solrj.request.CoreAdminRequest; @@ -70,7 +69,7 @@ public class SolrLogger { private static final Logger log = Logger.getLogger(SolrLogger.class); - private static final CommonsHttpSolrServer solr; + private static final HttpSolrServer solr; public static final String DATE_FORMAT_8601 = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; @@ -78,8 +77,6 @@ public class SolrLogger private static final LookupService locationService; - private static Map<String, String> metadataStorageInfo; - private static final boolean useProxies; private static List<String> statisticYearCores = new ArrayList<String>(); @@ -105,13 +102,13 @@ public class SolrLogger log.info("solr-statistics.server:" + ConfigurationManager.getProperty("solr-statistics", "server")); log.info("usage-statistics.dbfile:" + ConfigurationManager.getProperty("usage-statistics", "dbfile")); - CommonsHttpSolrServer server = null; + HttpSolrServer server = null; if (ConfigurationManager.getProperty("solr-statistics", "server") != null) { try { - server = new CommonsHttpSolrServer(ConfigurationManager.getProperty("solr-statistics", "server")); + server = new HttpSolrServer(ConfigurationManager.getProperty("solr-statistics", "server")); SolrQuery solrQuery = new SolrQuery() .setQuery("type:2 AND id:1"); server.query(solrQuery); @@ -243,6 +240,39 @@ public class SolrLogger log.error(e.getMessage(), e); } } + + public static void postView(DSpaceObject dspaceObject, + String ip, String userAgent, String xforwarderfor, EPerson currentUser) { + if (solr == null || locationService == null) { + return; + } + + try { + SolrInputDocument doc1 = getCommonSolrDoc(dspaceObject, ip, userAgent, xforwarderfor, + currentUser); + if (doc1 == null) + return; + if (dspaceObject instanceof Bitstream) { + Bitstream bit = (Bitstream) dspaceObject; + Bundle[] bundles = bit.getBundles(); + for (Bundle bundle : bundles) { + doc1.addField("bundleName", bundle.getName()); + } + } + + doc1.addField("statistics_type", StatisticsType.VIEW.text()); + + solr.add(doc1); + // commits are executed automatically using the solr autocommit + // solr.commit(false, false); + + } catch (RuntimeException re) { + throw re; + } catch (Exception e) { + log.error(e.getMessage(), e); + } + } + /** * Returns a solr input document containing common information about the statistics @@ -346,6 +376,92 @@ public class SolrLogger return doc1; } + private static SolrInputDocument getCommonSolrDoc(DSpaceObject dspaceObject, String ip, String userAgent, String xforwarderfor, EPerson currentUser) throws SQLException { + boolean isSpiderBot = SpiderDetector.isSpider(ip); + if(isSpiderBot && + !ConfigurationManager.getBooleanProperty("usage-statistics", "logBots", true)) + { + return null; + } + + SolrInputDocument doc1 = new SolrInputDocument(); + // Save our basic info that we already have + + + if (isUseProxies() && xforwarderfor != null) { + /* This header is a comma delimited list */ + for (String xfip : xforwarderfor.split(",")) { + /* proxy itself will sometime populate this header with the same value in + remote address. ordering in spec is vague, we'll just take the last + not equal to the proxy + */ + if (!xforwarderfor.contains(ip)) { + ip = xfip.trim(); + } + } + + doc1.addField("ip", ip); + + try + { + String dns = DnsLookup.reverseDns(ip); + doc1.addField("dns", dns.toLowerCase()); + } + catch (Exception e) + { + log.error("Failed DNS Lookup for IP:" + ip); + log.debug(e.getMessage(),e); + } + + // Save the location information if valid, save the event without + // location information if not valid + if(locationService != null) + { + Location location = locationService.getLocation(ip); + if (location != null + && !("--".equals(location.countryCode) + && location.latitude == -180 && location.longitude == -180)) + { + try + { + doc1.addField("continent", LocationUtils + .getContinentCode(location.countryCode)); + } + catch (Exception e) + { + System.out + .println("COUNTRY ERROR: " + location.countryCode); + } + doc1.addField("countryCode", location.countryCode); + doc1.addField("city", location.city); + doc1.addField("latitude", location.latitude); + doc1.addField("longitude", location.longitude); + doc1.addField("isBot",isSpiderBot); + + if(userAgent != null) + { + doc1.addField("userAgent", userAgent); + } + } + } + } + + if(dspaceObject != null){ + doc1.addField("id", dspaceObject.getID()); + doc1.addField("type", dspaceObject.getType()); + storeParents(doc1, dspaceObject); + } + // Save the current time + doc1.addField("time", DateFormatUtils.format(new Date(), DATE_FORMAT_8601)); + if (currentUser != null) + { + doc1.addField("epersonid", currentUser.getID()); + } + + return doc1; + } + + public static void postSearch(DSpaceObject resultObject, HttpServletRequest request, EPerson currentUser, List<String> queries, int rpp, String sortBy, String order, int page, DSpaceObject scope) { try @@ -365,8 +481,8 @@ public class SolrLogger } //Store the scope if(scope != null){ - solrDoc.addField("scopeId", scope.getType()); - solrDoc.addField("scopeType", scope.getID()); + solrDoc.addField("scopeId", scope.getID()); + solrDoc.addField("scopeType", scope.getType()); } if(rpp != -1){ @@ -444,11 +560,6 @@ public class SolrLogger } - public static Map<String, String> getMetadataStorageInfo() - { - return metadataStorageInfo; - } - /** * Method just used to log the parents. * <ul> @@ -557,18 +668,6 @@ public class SolrLogger // We have at least one document good SolrDocument document = response.getResults().get(0); - for (Object storedField : metadataStorageInfo.keySet()) - { - // For each of these fields that are stored we are to create a - // list of the values it holds now - java.util.Collection collection = document - .getFieldValues((String) storedField); - List<String> storedVals = new ArrayList<String>(); - storedVals.addAll(collection); - // Now add it to our hashmap - currentValsStored.put((String) storedField, storedVals); - } - // System.out.println("HERE"); // Get the info we need } @@ -1158,7 +1257,7 @@ public class SolrLogger public static void shardSolrIndex() throws IOException, SolrServerException { /* - Start by faceting by year so we can include each year in a seperate core ! + Start by faceting by year so we can include each year in a separate core ! */ SolrQuery yearRangeQuery = new SolrQuery(); yearRangeQuery.setQuery("*:*"); @@ -1213,7 +1312,7 @@ public class SolrLogger //Start by creating a new core String coreName = "statistics-" + dcStart.getYear(); - CommonsHttpSolrServer statisticsYearServer = createCore(solr, coreName); + HttpSolrServer statisticsYearServer = createCore(solr, coreName); System.out.println("Moving: " + totalRecords + " into core " + coreName); log.info("Moving: " + totalRecords + " records into core " + coreName); @@ -1240,7 +1339,7 @@ public class SolrLogger ContentStreamUpdateRequest contentStreamUpdateRequest = new ContentStreamUpdateRequest("/update/csv"); contentStreamUpdateRequest.setParam("stream.contentType", "text/plain;charset=utf-8"); contentStreamUpdateRequest.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true); - contentStreamUpdateRequest.addFile(tempCsv); + contentStreamUpdateRequest.addFile(tempCsv, "text/plain;charset=utf-8"); statisticsYearServer.request(contentStreamUpdateRequest); } @@ -1257,17 +1356,17 @@ public class SolrLogger FileUtils.deleteDirectory(tempDirectory); } - private static CommonsHttpSolrServer createCore(CommonsHttpSolrServer solr, String coreName) throws IOException, SolrServerException { + private static HttpSolrServer createCore(HttpSolrServer solr, String coreName) throws IOException, SolrServerException { String solrDir = ConfigurationManager.getProperty("dspace.dir") + File.separator + "solr" +File.separator; String baseSolrUrl = solr.getBaseURL().replace("statistics", ""); CoreAdminRequest.Create create = new CoreAdminRequest.Create(); create.setCoreName(coreName); create.setInstanceDir("statistics"); create.setDataDir(solrDir + coreName + File.separator + "data"); - CommonsHttpSolrServer solrServer = new CommonsHttpSolrServer(baseSolrUrl); + HttpSolrServer solrServer = new HttpSolrServer(baseSolrUrl); create.process(solrServer); log.info("Created core with name: " + coreName); - return new CommonsHttpSolrServer(baseSolrUrl + "/" + coreName); + return new HttpSolrServer(baseSolrUrl + "/" + coreName); } @@ -1378,7 +1477,7 @@ public class SolrLogger ContentStreamUpdateRequest contentStreamUpdateRequest = new ContentStreamUpdateRequest("/update/csv"); contentStreamUpdateRequest.setParam("stream.contentType", "text/plain;charset=utf-8"); contentStreamUpdateRequest.setAction(AbstractUpdateRequest.ACTION.COMMIT, true, true); - contentStreamUpdateRequest.addFile(tempCsv); + contentStreamUpdateRequest.addFile(tempCsv, "text/plain;charset=utf-8"); solr.request(contentStreamUpdateRequest); } diff --git a/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerUsageEventListener.java b/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerUsageEventListener.java index c686065515b656d5a2e23736b1171236745c00a4..060dec8ff9e0336664afc7761c8f09d7f7d70086 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerUsageEventListener.java +++ b/dspace-api/src/main/java/org/dspace/statistics/SolrLoggerUsageEventListener.java @@ -31,13 +31,18 @@ public class SolrLoggerUsageEventListener extends AbstractUsageEventListener { if(event instanceof UsageEvent) { + log.debug("Usage event received " + ((UsageEvent)event).getName()); try{ UsageEvent ue = (UsageEvent)event; EPerson currentUser = ue.getContext() == null ? null : ue.getContext().getCurrentUser(); if(UsageEvent.Action.VIEW == ue.getAction()){ - SolrLogger.postView(ue.getObject(), ue.getRequest(), currentUser); + if(ue.getRequest()!=null){ + SolrLogger.postView(ue.getObject(), ue.getRequest(), currentUser); + } else { + SolrLogger.postView(ue.getObject(), ue.getIp(), ue.getUserAgent(), ue.getXforwarderfor(), currentUser); + } }else if(UsageEvent.Action.SEARCH == ue.getAction()){ UsageSearchEvent usageSearchEvent = (UsageSearchEvent) ue; diff --git a/dspace-api/src/main/java/org/dspace/statistics/StatisticsLoggingConsumer.java b/dspace-api/src/main/java/org/dspace/statistics/StatisticsLoggingConsumer.java index 0a61900f404051939cc966df90f12bc8c3693c82..b8210f94486b7ea5fcb7fa48ade2eeb35e6e03ca 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/StatisticsLoggingConsumer.java +++ b/dspace-api/src/main/java/org/dspace/statistics/StatisticsLoggingConsumer.java @@ -37,6 +37,7 @@ public class StatisticsLoggingConsumer implements Consumer private Set<String> toRemoveQueries = null; + @Override public void initialize() throws Exception { @@ -45,6 +46,7 @@ public class StatisticsLoggingConsumer implements Consumer // TODO: checkout whether moving of collections, communities and bitstreams works // TODO: use async threaded consumer as this might require some processing time // TODO: we might be able to improve the performance: changing the collection will trigger 4 update commands + @Override public void consume(Context ctx, Event event) throws Exception { if (toRemoveQueries == null) @@ -78,45 +80,9 @@ public class StatisticsLoggingConsumer implements Consumer updateQuery, null, null); // Get all the metadata - Map<String, String> metadataStorageInfo = SolrLogger.getMetadataStorageInfo(); List<String> storageFieldList = new ArrayList<String>(); List<List<Object>> storageValuesList = new ArrayList<List<Object>>(); - for (Map.Entry<String, String> entry : metadataStorageInfo.entrySet()) - { - String[] metadataFieldInfo = entry.getValue().split("\\."); - - List<Object> values = new ArrayList<Object>(); - List<Object> valuesLow = new ArrayList<Object>(); - for (int i = 0; i < item.getMetadata(metadataFieldInfo[0], - metadataFieldInfo[1], metadataFieldInfo[2], Item.ANY).length; i++) - { - values.add(item.getMetadata(metadataFieldInfo[0], - metadataFieldInfo[1], metadataFieldInfo[2], - Item.ANY)[i].value); - - valuesLow.add(item.getMetadata(metadataFieldInfo[0], - metadataFieldInfo[1], metadataFieldInfo[2], - Item.ANY)[i].value.toLowerCase()); - } - - List<String> indexedVals = indexedValues.get(entry.getKey()); - - boolean update = true; - if (values.size() == indexedVals.size() && values.containsAll(indexedVals)) - { - update = false; - } - - if (update) - { - storageFieldList.add(entry.getKey()); - storageFieldList.add(entry.getKey() + "_search"); - storageValuesList.add(values); - storageValuesList.add(valuesLow); - } - } - SolrLogger.update(updateQuery, "replace", storageFieldList, storageValuesList); @@ -202,6 +168,7 @@ public class StatisticsLoggingConsumer implements Consumer findComms(comm.getParentCommunity(), parentComms); } + @Override public void end(Context ctx) throws Exception { if (toRemoveQueries != null) @@ -215,6 +182,7 @@ public class StatisticsLoggingConsumer implements Consumer toRemoveQueries = null; } + @Override public void finish(Context ctx) throws Exception { } diff --git a/dspace-api/src/main/java/org/dspace/statistics/content/StatisticsBSAdapter.java b/dspace-api/src/main/java/org/dspace/statistics/content/StatisticsBSAdapter.java index 694825eac2a330d01353558bff4c98dced777197..7f011befb398a84b0d2f9fdde3f5927bf08299bf 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/content/StatisticsBSAdapter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/content/StatisticsBSAdapter.java @@ -20,9 +20,7 @@ import org.dspace.statistics.content.filter.StatisticsFilter; * Class that will hold the data needed to show * statistics in the browse and search pages. * - * User: @author kevinvandevelde at atmire.com (kevin at atmire.com) - * Date: 20-mei-2009 - * Time: 16:44:29 + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class StatisticsBSAdapter { diff --git a/dspace-api/src/main/java/org/dspace/statistics/content/filter/StatisticsSolrDateFilter.java b/dspace-api/src/main/java/org/dspace/statistics/content/filter/StatisticsSolrDateFilter.java index 81b04d8ebce75d8f7ab5f20ed2374a368eafd5cf..4a76aa257b640a5d7faefabb40f69f42a33e33b1 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/content/filter/StatisticsSolrDateFilter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/content/filter/StatisticsSolrDateFilter.java @@ -15,10 +15,8 @@ import java.util.Calendar; /** * Encapsulate a range of dates for Solr query filtering. - * Created by IntelliJ IDEA. - * User: kevinvandevelde - * Date: 13-mrt-2009 - * Time: 13:14:14 + * + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class StatisticsSolrDateFilter implements StatisticsFilter { private Date startDate; diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/ApacheLogRobotsProcessor.java b/dspace-api/src/main/java/org/dspace/statistics/util/ApacheLogRobotsProcessor.java index 493a76c20579786e643a00c0f3b8acc761e0f611..243bf7378c63935e86b32b03d8bcd70fcee93cb3 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/ApacheLogRobotsProcessor.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/ApacheLogRobotsProcessor.java @@ -80,7 +80,7 @@ public class ApacheLogRobotsProcessor { if (spiderIpFile.exists()) { - logSpiders = SpiderDetector.readIpAddresses(spiderIpFile); + logSpiders = SpiderDetector.readPatterns(spiderIpFile); } else { diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/ClassicDSpaceLogConverter.java b/dspace-api/src/main/java/org/dspace/statistics/util/ClassicDSpaceLogConverter.java index 13607f2791dbbd66658f8753ccc7e6d096ed8faa..69b48f3901d2fb5b7c7d7968565d2779b4fda2c7 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/ClassicDSpaceLogConverter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/ClassicDSpaceLogConverter.java @@ -27,6 +27,9 @@ import java.text.ParsePosition; * by log4j) files into an intermediate format for ingestion into * the new solr stats. * + * @see StatisticsImporter + * @see StatisticsImporterElasticSearch + * * @author Stuart Lewis */ public class ClassicDSpaceLogConverter { diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/DnsLookup.java b/dspace-api/src/main/java/org/dspace/statistics/util/DnsLookup.java index 435bf036861d5a10fa576cb07fea4fbb357aa84a..eb605b6b022acbf88c336990cf4d295d1f024b14 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/DnsLookup.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/DnsLookup.java @@ -14,12 +14,20 @@ import java.io.IOException; /** * XBill DNS resolver to retrieve hostnames for client IP addresses. + * TODO: deal with IPv6 addresses. * * @author kevinvandevelde at atmire.com * @author ben at atmire.com */ public class DnsLookup { + /** + * Resolve an IP address to a host name. + * + * @param hostIp dotted decimal IPv4 address. + * @return name if resolved, or the address. + * @throws IOException from infrastructure. + */ public static String reverseDns(String hostIp) throws IOException { Resolver res = new ExtendedResolver(); @@ -44,4 +52,45 @@ public class DnsLookup { return answers[0].rdataToString(); } } + + /** + * Resolve a host name to an IPv4 address. + * @throws IOException from infrastructure or no resolution. + */ + public static String forward(String hostname) + throws IOException + { + Resolver res = new ExtendedResolver(); + int timeout = ConfigurationManager.getIntProperty("usage-statistics", + "resolver.timeout", 200); + res.setTimeout(0, timeout); + + Name name = Name.fromString(hostname, Name.root); + Record rec = Record.newRecord(name, Type.A, DClass.IN); + Message query = Message.newQuery(rec); + Message response = res.send(query); + + Record[] answers = response.getSectionArray(Section.ANSWER); + if (answers.length == 0) + { + throw new IOException("Unresolvable host name (empty response)"); + } + + String resolution = null; + for (Record answer : answers) + { + if (answer.getType() == Type.A) + { + resolution = answer.rdataToString(); + break; + } + } + + if (null == resolution) + { + throw new IOException("Unresolvable host name (no A record)"); + } + + return resolution; + } } diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java index c6c921f7fa2aabf4ef5d100d1313eade7207032f..da144cd3f3a7fc9f659e971ec48c9417d1e72e8f 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/SpiderDetector.java @@ -7,20 +7,23 @@ */ package org.dspace.statistics.util; -import org.apache.log4j.Logger; -import org.dspace.core.ConfigurationManager; - -import javax.servlet.http.HttpServletRequest; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.regex.Pattern; +import javax.servlet.http.HttpServletRequest; +import org.dspace.core.ConfigurationManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * SpiderDetector is used to find IP's that are spiders... - * In future someone may add UserAgents and Host Domains + * In future someone may add Host Domains * to the detection criteria here. * * @author kevinvandevelde at atmire.com @@ -29,7 +32,7 @@ import java.util.Set; */ public class SpiderDetector { - private static Logger log = Logger.getLogger(SpiderDetector.class); + private static Logger log = LoggerFactory.getLogger(SpiderDetector.class); private static Boolean useProxies; @@ -38,34 +41,38 @@ public class SpiderDetector { */ private static IPTable table = null; + /** Collection of regular expressions to match known spiders' agents. */ + private static List<Pattern> agents = new ArrayList<Pattern>(); + + /** Collection of regular expressions to match known spiders' domain names. */ + private static List<Pattern> domains = new ArrayList<Pattern>(); + /** - * Utility method which Reads the ip addresses out a file & returns them in a Set + * Utility method which reads lines from a file & returns them in a Set. * - * @param spiderIpFile the location of our spider file - * @return a vector full of ip's + * @param patternFile the location of our spider file + * @return a vector full of patterns * @throws IOException could not happen since we check the file be4 we use it */ - public static Set<String> readIpAddresses(File spiderIpFile) throws IOException { - Set<String> ips = new HashSet<String>(); + public static Set<String> readPatterns(File patternFile) + throws IOException + { + Set<String> patterns = new HashSet<String>(); - if (!spiderIpFile.exists() || !spiderIpFile.isFile()) + if (!patternFile.exists() || !patternFile.isFile()) { - return ips; + return patterns; } - //Read our file & get all them ip's - BufferedReader in = new BufferedReader(new FileReader(spiderIpFile)); + //Read our file & get all them patterns. + BufferedReader in = new BufferedReader(new FileReader(patternFile)); String line; while ((line = in.readLine()) != null) { if (!line.startsWith("#")) { line = line.trim(); - if (!line.equals("") && !Character.isDigit(line.charAt(0))) { - // is a hostname - // add this functionality later... - } else if (!line.equals("")) { - ips.add(line); - // is full v4 ip (too tired to deal with v6)... + if (!line.equals("")) { + patterns.add(line); } } else { // ua.add(line.replaceFirst("#","").replaceFirst("UA","").trim()); @@ -73,11 +80,13 @@ public class SpiderDetector { } } in.close(); - return ips; + return patterns; } /** - * Get an immutable Set representing all the Spider Addresses here. + * Get an immutable Set representing all the Spider Addresses here + * + * @return */ public static Set<String> getSpiderIpAddresses() { @@ -86,12 +95,11 @@ public class SpiderDetector { } /* - private loader to populate the table from files. + * private loader to populate the table from files. */ private static void loadSpiderIpAddresses() { - if (table == null) { table = new IPTable(); @@ -102,44 +110,112 @@ public class SpiderDetector { if (spidersDir.exists() && spidersDir.isDirectory()) { for (File file : spidersDir.listFiles()) { - for (String ip : readIpAddresses(file)) { - table.add(ip); + if (file.isFile()) + { + for (String ip : readPatterns(file)) { + log.debug("Loading {}", ip); + if (!Character.isDigit(ip.charAt(0))) + { + try { + ip = DnsLookup.forward(ip); + log.debug("Resolved to {}", ip); + } catch (IOException e) { + log.warn("Not loading {}: {}", ip, e.getMessage()); + continue; + } + } + table.add(ip); + } + log.info("Loaded Spider IP file: " + file); } - log.info("Loaded Spider IP file: " + file); } } else { log.info("No spider file loaded"); } - - } catch (Exception e) { log.error("Error Loading Spiders:" + e.getMessage(), e); } - } } + /** + * Load agent name patterns from all files in a single subdirectory of config/spiders. + * + * @param directory simple directory name (e.g. "agents"). + * "${dspace.dir}/config/spiders" will be prepended to yield the path to + * the directory of pattern files. + * @param patternList patterns read from the files in {@code directory} will + * be added to this List. + */ + private static void loadPatterns(String directory, List<Pattern> patternList) + { + String dspaceHome = ConfigurationManager.getProperty("dspace.dir"); + File spidersDir = new File(dspaceHome, "config/spiders"); + File patternsDir = new File(spidersDir, directory); + if (patternsDir.exists() && patternsDir.isDirectory()) + { + for (File file : patternsDir.listFiles()) + { + Set<String> patterns; + try + { + patterns = readPatterns(file); + } catch (IOException ex) + { + log.error("Patterns not read from {}: {}", + file.getPath(), ex.getMessage()); + continue; + } + for (String pattern : patterns) + { + patternList.add(Pattern.compile(pattern)); + } + log.info("Loaded pattern file: {}", file.getPath()); + } + } + else + { + log.info("No patterns loaded from {}", patternsDir.getPath()); + } + } /** * Static Service Method for testing spiders against existing spider files. - * <p/> - * In the future this will be extended to support User Agent and - * domain Name detection. - * <p/> + * <p> * In future spiders HashSet may be optimized as byte offset array to * improve performance and memory footprint further. * - * @param request - * @return true|false if the request was detected to be from a spider + * @param clientIP address of the client. + * @param proxyIPs comma-list of X-Forwarded-For addresses, or null. + * @param hostname domain name of host, or null. + * @param agent User-Agent header value, or null. + * @return true if the client matches any spider characteristics list. */ - public static boolean isSpider(HttpServletRequest request) { + public static boolean isSpider(String clientIP, String proxyIPs, + String hostname, String agent) + { + // See if any agent patterns match + if (null != agent) + { + if (agents.isEmpty()) + loadPatterns("agents", agents); + + for (Pattern candidate : agents) + { + if (candidate.matcher(agent).find()) + { + return true; + } + } + } - if (isUseProxies() && request.getHeader("X-Forwarded-For") != null) { + // No. See if any IP addresses match + if (isUseProxies() && proxyIPs != null) { /* This header is a comma delimited list */ - for (String xfip : request.getHeader("X-Forwarded-For").split(",")) { + for (String xfip : proxyIPs.split(",")) { if (isSpider(xfip)) { return true; @@ -147,8 +223,42 @@ public class SpiderDetector { } } - return isSpider(request.getRemoteAddr()); + if (isSpider(clientIP)) + return true; + + // No. See if any DNS names match + if (null != hostname) + { + if (domains.isEmpty()) + { + loadPatterns("domains", domains); + } + + for (Pattern candidate : domains) + { + if (candidate.matcher(hostname).find()) + { + return true; + } + } + } + + // Not a known spider. + return false; + } + /** + * Static Service Method for testing spiders against existing spider files. + * + * @param request + * @return true|false if the request was detected to be from a spider. + */ + public static boolean isSpider(HttpServletRequest request) + { + return isSpider(request.getRemoteAddr(), + request.getHeader("X-Forwarded-For"), + request.getRemoteHost(), + request.getHeader("User-Agent")); } /** @@ -191,5 +301,4 @@ public class SpiderDetector { return useProxies; } - } diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsDataGenerator.java b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsDataGenerator.java index ddd4392bce10a775426b4998ca67bed67b52ba13..4ac33cd9f1992db0a4d0b144a6abebcf6bebd0ea 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsDataGenerator.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsDataGenerator.java @@ -10,19 +10,16 @@ package org.dspace.statistics.util; import org.apache.commons.cli.*; import org.apache.commons.lang.time.DateFormatUtils; import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; +import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.dspace.core.Context; import org.dspace.core.Constants; import org.dspace.core.ConfigurationManager; import org.dspace.content.DSpaceObject; import org.dspace.content.Bitstream; -import org.dspace.content.DCValue; -import org.dspace.content.Item; import org.dspace.eperson.EPerson; import org.dspace.statistics.SolrLogger; import java.util.Date; -import java.util.Map; import java.text.SimpleDateFormat; import com.maxmind.geoip.LookupService; @@ -191,13 +188,11 @@ public class StatisticsDataGenerator { // We got all our parameters now get the rest Context context = new Context(); // Find our solr server - CommonsHttpSolrServer solr = new CommonsHttpSolrServer( + HttpSolrServer solr = new HttpSolrServer( ConfigurationManager.getProperty("solr-statistics", "server")); solr.deleteByQuery("*:*"); solr.commit(); - Map<String, String> metadataStorageInfo = SolrLogger.getMetadataStorageInfo(); - String prevIp = null; String dbfile = ConfigurationManager.getProperty("usage-statistics", "dbfile"); LookupService cl = new LookupService(dbfile, @@ -366,24 +361,6 @@ public class StatisticsDataGenerator { doc1.addField("dns", dns.toLowerCase()); } - if (dso instanceof Item) { - Item item = (Item) dso; - // Store the metadata - for (Map.Entry<String, String> entry : metadataStorageInfo.entrySet()) - { - String dcField = entry.getValue(); - - DCValue[] vals = item.getMetadata(dcField.split("\\.")[0], - dcField.split("\\.")[1], dcField.split("\\.")[2], - Item.ANY); - for (DCValue val1 : vals) { - String val = val1.value; - doc1.addField(entry.getKey(), val); - doc1.addField(entry.getKey() + "_search", val.toLowerCase()); - } - } - } - SolrLogger.storeParents(doc1, dso); solr.add(doc1); diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java index f00ef0e78ea62e590d8a32290e06081dd30efb00..53151983711862c5664375faac17074aa6cdb084 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporter.java @@ -11,7 +11,7 @@ import org.apache.commons.cli.*; import org.apache.commons.lang.time.DateFormatUtils; import org.apache.log4j.Logger; import org.apache.solr.common.SolrInputDocument; -import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; +import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.apache.solr.client.solrj.SolrServerException; import org.dspace.content.*; import org.dspace.content.Collection; @@ -29,7 +29,9 @@ import com.maxmind.geoip.LookupService; import com.maxmind.geoip.Location; /** - * Class to load intermediate statistics files into solr + * Class to load intermediate statistics files (produced from log files by {@link ClassicDSpaceLogConverter}) into Solr. + * + * @see ClassicDSpaceLogConverter * * @author Stuart Lewis */ @@ -38,17 +40,14 @@ public class StatisticsImporter private static final Logger log = Logger.getLogger(StatisticsImporter.class); /** Date format (for solr) */ - private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); /** Solr server connection */ - private static CommonsHttpSolrServer solr; + private static HttpSolrServer solr; /** GEOIP lookup service */ private static LookupService geoipLookup; - /** Metadata storage information */ - private static Map<String, String> metadataStorageInfo; - /** Whether to skip the DNS reverse lookup or not */ private static boolean skipReverseDNS = false; @@ -65,7 +64,7 @@ public class StatisticsImporter private List<Integer> localBitstreams; /** Whether or not to replace item IDs with local values (for testing) */ - private boolean useLocal; + private final boolean useLocal; /** * Constructor. Optionally loads local data to replace foreign data @@ -337,24 +336,6 @@ public class StatisticsImporter sid.addField("dns", dns.toLowerCase()); } - if (dso instanceof Item) { - Item item = (Item) dso; - // Store the metadata - for (String storedField : metadataStorageInfo.keySet()) { - String dcField = metadataStorageInfo.get(storedField); - - DCValue[] vals = item.getMetadata(dcField.split("\\.")[0], - dcField.split("\\.")[1], dcField.split("\\.")[2], - Item.ANY); - for (DCValue val1 : vals) { - String val = val1.value; - sid.addField(String.valueOf(storedField), val); - sid.addField(String.valueOf(storedField + "_search"), - val.toLowerCase()); - } - } - } - SolrLogger.storeParents(sid, dso); solr.add(sid); errors--; @@ -467,9 +448,8 @@ public class StatisticsImporter { System.out.println("Writing to solr server at: " + sserver); } - solr = new CommonsHttpSolrServer(sserver); + solr = new HttpSolrServer(sserver); - metadataStorageInfo = SolrLogger.getMetadataStorageInfo(); String dbfile = ConfigurationManager.getProperty("usage-statistics", "dbfile"); try { @@ -493,6 +473,7 @@ public class StatisticsImporter File dir = sample.getParentFile(); FilenameFilter filter = new FilenameFilter() { + @Override public boolean accept(File dir, String name) { return name.startsWith(sample.getName()); @@ -520,7 +501,7 @@ public class StatisticsImporter */ static class DNSCache<K,V> extends LinkedHashMap<K,V> { - private int maxCapacity; + private final int maxCapacity; public DNSCache(int initialCapacity, float loadFactor, int maxCapacity) { diff --git a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporterElasticSearch.java b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporterElasticSearch.java index 83373551151f85436caa07f0d44dc6949cc45fc9..9ba2fd433a8d0d9e8f7b721360889af659fdb4cb 100644 --- a/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporterElasticSearch.java +++ b/dspace-api/src/main/java/org/dspace/statistics/util/StatisticsImporterElasticSearch.java @@ -21,12 +21,14 @@ import org.dspace.core.Context; import org.dspace.eperson.EPerson; import org.dspace.statistics.ElasticSearchLogger; import org.dspace.statistics.SolrLogger; +import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.client.Client; -import org.elasticsearch.client.action.bulk.BulkRequestBuilder; + +import org.elasticsearch.common.geo.GeoPoint; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; -import org.elasticsearch.index.mapper.geo.GeoPoint; + import java.io.*; import java.text.DecimalFormat; @@ -39,11 +41,11 @@ import java.util.Random; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; /** - * Created by IntelliJ IDEA. - * User: peterdietz - * Date: 8/15/12 - * Time: 2:46 PM - * To change this template use File | Settings | File Templates. + * Class to load intermediate statistics files (produced from log files by <code>ClassicDSpaceLogConverter</code>) into Elastic Search + * + * @see ClassicDSpaceLogConverter + * + * @author Peter Dietz (pdietz84@gmail.com) */ public class StatisticsImporterElasticSearch { private static final Logger log = Logger.getLogger(StatisticsImporterElasticSearch.class); @@ -429,8 +431,8 @@ public class StatisticsImporterElasticSearch { /** * Inner class to hold a cache of reverse lookups of IP addresses - * @param <K> - * @param <V> + * @param <K> IP address + * @param <V> hostname looked up via DNS */ static class DNSCache<K,V> extends LinkedHashMap<K,V> { diff --git a/dspace-api/src/main/java/org/dspace/submit/step/AccessStep.java b/dspace-api/src/main/java/org/dspace/submit/step/AccessStep.java index 8f98a1fa2ea4c7c7a6b879b25f68b79d18f264fe..2c4e81ffde77fc76997055ca3a16b812d72a2f37 100644 --- a/dspace-api/src/main/java/org/dspace/submit/step/AccessStep.java +++ b/dspace-api/src/main/java/org/dspace/submit/step/AccessStep.java @@ -153,12 +153,17 @@ public class AccessStep extends AbstractProcessingStep // if arrive here Next, Previous or Save has been pressed - boolean isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); + boolean isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); // if it is a simple form we should create the policy for Anonymous // if Anonymous does not have right on this collection, create policies for any other groups with // DEFAULT_ITEM_READ specified. if(!isAdvancedFormEnabled){ + int result = checkForm(request); + if (result != 0) + { + return result; + } AuthorizeManager.generateAutomaticPolicies(context, getEmbargoUntilDate(request), reason, item, (Collection)HandleManager.resolveToObject(context, subInfo.getCollectionHandle())); } // else{ diff --git a/dspace-api/src/main/java/org/dspace/submit/step/CCLicenseStep.java b/dspace-api/src/main/java/org/dspace/submit/step/CCLicenseStep.java index 6bc3607d3a4252c08d12ca6e18f1dcee88f8d414..5efbe35b6f5e99b3c7b296234351c17ad7ff0cde 100644 --- a/dspace-api/src/main/java/org/dspace/submit/step/CCLicenseStep.java +++ b/dspace-api/src/main/java/org/dspace/submit/step/CCLicenseStep.java @@ -100,7 +100,8 @@ public class CCLicenseStep extends AbstractProcessingStep session.setAttribute("inProgress", "TRUE"); // check what submit button was pressed in User Interface String buttonPressed = Util.getSubmitButton(request, NEXT_BUTTON); - if (buttonPressed.equals("submit_grant")) + if ("submit_grant".equalsIgnoreCase(buttonPressed) + || "submit_no_cc".equalsIgnoreCase(buttonPressed)) { return processCC(context, request, response, subInfo); } @@ -247,7 +248,7 @@ public class CCLicenseStep extends AbstractProcessingStep CCLookup ccLookup = new CCLookup(); CreativeCommons.MdField uriField = CreativeCommons.getCCField("uri"); CreativeCommons.MdField nameField = CreativeCommons.getCCField("name"); - ccLookup.issue(licenseclass, map, ConfigurationManager.getProperty("default.locale")); + ccLookup.issue(licenseclass, map, ConfigurationManager.getProperty("cc.license.locale")); Item item = subInfo.getSubmissionItem().getItem(); if (licenseclass.equals("xmlui.Submission.submit.CCLicenseStep.no_license")) { diff --git a/dspace-api/src/main/java/org/dspace/submit/step/DescribeStep.java b/dspace-api/src/main/java/org/dspace/submit/step/DescribeStep.java index e0f84bac8439567eb1d597dae3c4b986760470cf..546be33edd0f5b9a5568d5de6a30f11848bfab34 100644 --- a/dspace-api/src/main/java/org/dspace/submit/step/DescribeStep.java +++ b/dspace-api/src/main/java/org/dspace/submit/step/DescribeStep.java @@ -117,6 +117,10 @@ public class DescribeStep extends AbstractProcessingStep throws ServletException, IOException, SQLException, AuthorizeException { + if(!request.getParameterNames().hasMoreElements()){ + //In case of an empty request do NOT just remove all metadata, just return to the submission page + return STATUS_MORE_INPUT_REQUESTED; + } // check what submit button was pressed in User Interface String buttonPressed = Util.getSubmitButton(request, NEXT_BUTTON); diff --git a/dspace-api/src/main/java/org/dspace/submit/step/InitialQuestionsStep.java b/dspace-api/src/main/java/org/dspace/submit/step/InitialQuestionsStep.java index fd5019aabcecda2f940d747f5fe59c83b717df52..677e2f6a7c96aa7ca991e44d57d3f3b753d3c5b1 100644 --- a/dspace-api/src/main/java/org/dspace/submit/step/InitialQuestionsStep.java +++ b/dspace-api/src/main/java/org/dspace/submit/step/InitialQuestionsStep.java @@ -199,7 +199,7 @@ public class InitialQuestionsStep extends AbstractProcessingStep request.setAttribute("will.remove.titles", Boolean.valueOf(willRemoveTitles)); request.setAttribute("will.remove.date", Boolean.valueOf(willRemoveDate)); request.setAttribute("will.remove.files", Boolean.valueOf(willRemoveFiles)); - + return STATUS_VERIFY_PRUNE; // we will need to do pruning! } } @@ -214,6 +214,20 @@ public class InitialQuestionsStep extends AbstractProcessingStep subInfo.getSubmissionItem().setMultipleFiles(multipleFiles); } + // If this work has not been published before & no issued date is set, + // then the assumption is that TODAY is the issued date. + // (This logic is necessary since the date field is hidden on DescribeStep when publishedBefore==false) + if(!publishedBefore) + { + DCValue[] dateIssued = subInfo.getSubmissionItem().getItem() + .getDC("date", "issued", Item.ANY); + if(dateIssued.length==0) + { + //Set issued date to "today" (NOTE: InstallItem will determine the actual date for us) + subInfo.getSubmissionItem().getItem().addDC("date", "issued", null, "today"); + } + } + // commit all changes to DB subInfo.getSubmissionItem().update(); context.commit(); diff --git a/dspace-api/src/main/java/org/dspace/submit/step/UploadStep.java b/dspace-api/src/main/java/org/dspace/submit/step/UploadStep.java index 71b2e610c38c694c2d6bf8cb062ad3efb8fb7a5a..3a2fd46707c7e755465787d164928c4855067fc9 100644 --- a/dspace-api/src/main/java/org/dspace/submit/step/UploadStep.java +++ b/dspace-api/src/main/java/org/dspace/submit/step/UploadStep.java @@ -95,7 +95,7 @@ public class UploadStep extends AbstractProcessingStep private static Logger log = Logger.getLogger(UploadStep.class); /** is the upload required? */ - private boolean fileRequired = ConfigurationManager.getBooleanProperty("webui.submit.upload.required", true); + protected boolean fileRequired = ConfigurationManager.getBooleanProperty("webui.submit.upload.required", true); /** * Do any processing of the information input by the user, and/or perform @@ -150,10 +150,11 @@ public class UploadStep extends AbstractProcessingStep return status; } } - + // if user pressed jump-to button in process bar, // return success (so that jump will occur) - if (buttonPressed.startsWith(PROGRESS_BAR_PREFIX)) + if (buttonPressed.startsWith(PROGRESS_BAR_PREFIX) || + buttonPressed.startsWith(PREVIOUS_BUTTON)) { // check if a file is required to be uploaded if (fileRequired && !item.hasUploadedFiles()) @@ -316,7 +317,8 @@ public class UploadStep extends AbstractProcessingStep // files have been uploaded. // --------------------------------------------------- //check if a file is required to be uploaded - if (fileRequired && !item.hasUploadedFiles()) + if (fileRequired && !item.hasUploadedFiles() + && !buttonPressed.equals(SUBMIT_MORE_BUTTON)) { return STATUS_NO_FILES_ERROR; } @@ -470,7 +472,7 @@ public class UploadStep extends AbstractProcessingStep String fileDescription = (String) request.getAttribute(param + "-description"); if(fileDescription==null ||fileDescription.length()==0) { - request.getParameter("description"); + fileDescription = request.getParameter("description"); } // if information wasn't passed by User Interface, we had a problem @@ -584,7 +586,7 @@ public class UploadStep extends AbstractProcessingStep /* If we created a new Bitstream but now realised there is a problem then remove it. */ - private void backoutBitstream(SubmissionInfo subInfo, Bitstream b, Item item) throws SQLException, AuthorizeException, IOException + protected void backoutBitstream(SubmissionInfo subInfo, Bitstream b, Item item) throws SQLException, AuthorizeException, IOException { // remove bitstream from bundle.. // delete bundle if it's now empty diff --git a/dspace-api/src/main/java/org/dspace/submit/step/UploadWithEmbargoStep.java b/dspace-api/src/main/java/org/dspace/submit/step/UploadWithEmbargoStep.java index 41236f259aeb66237143f952d17189705256a877..416e9203745ff7cd4af73b347740ecee6b16c151 100644 --- a/dspace-api/src/main/java/org/dspace/submit/step/UploadWithEmbargoStep.java +++ b/dspace-api/src/main/java/org/dspace/submit/step/UploadWithEmbargoStep.java @@ -19,7 +19,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.lang.time.DateUtils; import org.apache.log4j.Logger; - import org.dspace.app.util.SubmissionInfo; import org.dspace.app.util.Util; import org.dspace.authorize.AuthorizeException; @@ -30,11 +29,10 @@ import org.dspace.core.Context; import org.dspace.core.ConfigurationManager; import org.dspace.curate.Curator; import org.dspace.handle.HandleManager; -import org.dspace.submit.AbstractProcessingStep; /** - * Upload step for DSpace. Processes the actual upload of files - * for an item being submitted into DSpace. + * Upload step with the advanced embargo system for DSpace. Processes the actual + * upload of files for an item being submitted into DSpace. * <P> * This class performs all the behind-the-scenes processing that * this particular step requires. This class's methods are utilized @@ -42,57 +40,15 @@ import org.dspace.submit.AbstractProcessingStep; * * @see org.dspace.app.util.SubmissionConfig * @see org.dspace.app.util.SubmissionStepConfig + * @see org.dspace.submit.step.UploadStep * @see org.dspace.submit.AbstractProcessingStep * * @author Tim Donohue + * @author Keiji Suzuki * @version $Revision$ */ -public class UploadWithEmbargoStep extends AbstractProcessingStep +public class UploadWithEmbargoStep extends UploadStep { - /** Button to upload a file * */ - public static final String SUBMIT_UPLOAD_BUTTON = "submit_upload"; - - /** Button to skip uploading a file * */ - public static final String SUBMIT_SKIP_BUTTON = "submit_skip"; - - /** Button to submit more files * */ - public static final String SUBMIT_MORE_BUTTON = "submit_more"; - - /** Button to cancel editing of file info * */ - public static final String CANCEL_EDIT_BUTTON = "submit_edit_cancel"; - - /*************************************************************************** - * STATUS / ERROR FLAGS (returned by doProcessing() if an error occurs or - * additional user interaction may be required) - * - * (Do NOT use status of 0, since it corresponds to STATUS_COMPLETE flag - * defined in the JSPStepManager class) - **************************************************************************/ - // integrity error occurred - public static final int STATUS_INTEGRITY_ERROR = 1; - - // error in uploading file - public static final int STATUS_UPLOAD_ERROR = 2; - - // error - no files uploaded! - public static final int STATUS_NO_FILES_ERROR = 5; - - // format of uploaded file is unknown - public static final int STATUS_UNKNOWN_FORMAT = 10; - - // virus checker unavailable ? - public static final int STATUS_VIRUS_CHECKER_UNAVAILABLE = 14; - - // file failed virus check - public static final int STATUS_CONTAINS_VIRUS = 16; - - // edit file information - public static final int STATUS_EDIT_BITSTREAM = 20; - - // return from editing file information - public static final int STATUS_EDIT_COMPLETE = 25; - - public static final int STATUS_EDIT_POLICIES = 30; public static final int STATUS_EDIT_POLICIES_ERROR_SELECT_GROUP = 31; @@ -103,10 +59,7 @@ public class UploadWithEmbargoStep extends AbstractProcessingStep /** log4j logger */ - private static Logger log = Logger.getLogger(UploadStep.class); - - /** is the upload required? */ - private boolean fileRequired = ConfigurationManager.getBooleanProperty("webui.submit.upload.required", true); + private static Logger log = Logger.getLogger(UploadWithEmbargoStep.class); /** * Do any processing of the information input by the user, and/or perform @@ -164,7 +117,8 @@ public class UploadWithEmbargoStep extends AbstractProcessingStep // if user pressed jump-to button in process bar, // return success (so that jump will occur) - if (buttonPressed.startsWith(PROGRESS_BAR_PREFIX)) + if (buttonPressed.startsWith(PROGRESS_BAR_PREFIX) || + buttonPressed.startsWith(PREVIOUS_BUTTON)) { // check if a file is required to be uploaded if (fileRequired && !item.hasUploadedFiles()) @@ -345,98 +299,6 @@ public class UploadWithEmbargoStep extends AbstractProcessingStep return STATUS_COMPLETE; } - - - /** - * Retrieves the number of pages that this "step" extends over. This method - * is used to build the progress bar. - * <P> - * This method may just return 1 for most steps (since most steps consist of - * a single page). But, it should return a number greater than 1 for any - * "step" which spans across a number of HTML pages. For example, the - * configurable "Describe" step (configured using input-forms.xml) overrides - * this method to return the number of pages that are defined by its - * configuration file. - * <P> - * Steps which are non-interactive (i.e. they do not display an interface to - * the user) should return a value of 1, so that they are only processed - * once! - * - * @param request - * The HTTP Request - * @param subInfo - * The current submission information object - * - * @return the number of pages in this step - */ - public int getNumberOfPages(HttpServletRequest request, - SubmissionInfo subInfo) throws ServletException - { - // Despite using many JSPs, this step only appears - // ONCE in the Progress Bar, so it's only ONE page - return 1; - } - - // **************************************************************** - // **************************************************************** - // METHODS FOR UPLOADING FILES (and associated information) - // **************************************************************** - // **************************************************************** - - /** - * Remove a file from an item - * - * @param context - * current DSpace context - * @param item - * Item where file should be removed from - * @param bitstreamID - * The id of bitstream representing the file to remove - * @return Status or error flag which will be processed by - * UI-related code! (if STATUS_COMPLETE or 0 is returned, - * no errors occurred!) - */ - protected int processRemoveFile(Context context, Item item, int bitstreamID) - throws IOException, SQLException, AuthorizeException - { - Bitstream bitstream; - - // Try to find bitstream - try - { - bitstream = Bitstream.find(context, bitstreamID); - } - catch (NumberFormatException nfe) - { - bitstream = null; - } - - if (bitstream == null) - { - // Invalid or mangled bitstream ID - // throw an error and return immediately - return STATUS_INTEGRITY_ERROR; - } - - // remove bitstream from bundle.. - // delete bundle if it's now empty - Bundle[] bundles = bitstream.getBundles(); - - bundles[0].removeBitstream(bitstream); - - Bitstream[] bitstreams = bundles[0].getBitstreams(); - - // remove bundle if it's now empty - if (bitstreams.length < 1) - { - item.removeBundle(bundles[0]); - item.update(); - } - - // no errors occurred - return STATUS_COMPLETE; - } - /** * Process the upload of a new file! * @@ -611,7 +473,7 @@ public class UploadWithEmbargoStep extends AbstractProcessingStep private void processAccessFields(Context context, HttpServletRequest request, SubmissionInfo subInfo, Bitstream b) throws SQLException, AuthorizeException { // ResourcePolicy Management - boolean isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); + boolean isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); // if it is a simple form we should create the policy for Anonymous // if Anonymous does not have right on this collection, create policies for any other groups with // DEFAULT_ITEM_READ specified. @@ -628,116 +490,6 @@ public class UploadWithEmbargoStep extends AbstractProcessingStep } - /* - If we created a new Bitstream but now realised there is a problem then remove it. - */ - private void backoutBitstream(SubmissionInfo subInfo, Bitstream b, Item item) throws SQLException, AuthorizeException, IOException - { - // remove bitstream from bundle.. - // delete bundle if it's now empty - Bundle[] bnd = b.getBundles(); - - bnd[0].removeBitstream(b); - - Bitstream[] bitstreams = bnd[0].getBitstreams(); - - // remove bundle if it's now empty - if (bitstreams.length < 1) - { - item.removeBundle(bnd[0]); - item.update(); - } - - subInfo.setBitstream(null); - } - - /** - * Process input from get file type page - * - * @param context - * current DSpace context - * @param request - * current servlet request object - * @param response - * current servlet response object - * @param subInfo - * submission info object - * - * @return Status or error flag which will be processed by - * UI-related code! (if STATUS_COMPLETE or 0 is returned, - * no errors occurred!) - */ - protected int processSaveFileFormat(Context context, - HttpServletRequest request, HttpServletResponse response, - SubmissionInfo subInfo) throws ServletException, IOException, - SQLException, AuthorizeException - { - if (subInfo.getBitstream() != null) - { - // Did the user select a format? - int typeID = Util.getIntParameter(request, "format"); - - BitstreamFormat format = BitstreamFormat.find(context, typeID); - - if (format != null) - { - subInfo.getBitstream().setFormat(format); - } - else - { - String userDesc = request.getParameter("format_description"); - - subInfo.getBitstream().setUserFormatDescription(userDesc); - } - - // update database - subInfo.getBitstream().update(); - } - else - { - return STATUS_INTEGRITY_ERROR; - } - - return STATUS_COMPLETE; - } - - /** - * Process input from the "change file description" page - * - * @param context - * current DSpace context - * @param request - * current servlet request object - * @param response - * current servlet response object - * @param subInfo - * submission info object - * - * @return Status or error flag which will be processed by - * UI-related code! (if STATUS_COMPLETE or 0 is returned, - * no errors occurred!) - */ - protected int processSaveFileDescription(Context context, - HttpServletRequest request, HttpServletResponse response, - SubmissionInfo subInfo) throws ServletException, IOException, - SQLException, AuthorizeException - { - if (subInfo.getBitstream() != null) - { - subInfo.getBitstream().setDescription( - request.getParameter("description")); - subInfo.getBitstream().update(); - - context.commit(); - } - else - { - return STATUS_INTEGRITY_ERROR; - } - - return STATUS_COMPLETE; - } - private int editBitstreamPolicies(HttpServletRequest request, Context context, SubmissionInfo subInfo, String buttonPressed) throws SQLException, AuthorizeException { diff --git a/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java b/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java index 154fbdcad86c05e6b8172f74726ffa741c598034..5ecbae7410d8f8b6428a781452054605d34ff063 100644 --- a/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java +++ b/dspace-api/src/main/java/org/dspace/usage/UsageEvent.java @@ -52,6 +52,12 @@ public class UsageEvent extends Event { private transient HttpServletRequest request; + private transient String ip; + + private transient String userAgent; + + private transient String xforwarderfor; + private transient Context context; private transient DSpaceObject object; @@ -86,6 +92,39 @@ public class UsageEvent extends Event { eventName.append(objText).append(":"); } eventName.append(action.text()); + + return eventName.toString(); + } + + private static String checkParams(Action action, Context context, DSpaceObject object) + { + StringBuilder eventName = new StringBuilder(); + if(action == null) + { + throw new IllegalStateException("action cannot be null"); + } + +// if(action != Action.WORKFLOW) +// { +// throw new IllegalStateException("request cannot be null"); +// } + + + if(context == null) + { + throw new IllegalStateException("context cannot be null"); + } + + if(action != Action.WORKFLOW && action != Action.SEARCH && object == null) + { + throw new IllegalStateException("object cannot be null"); + }else + if(object != null){ + String objText = Constants.typeText[object.getType()].toLowerCase(); + eventName.append(objText).append(":"); + } + eventName.append(action.text()); + return eventName.toString(); } @@ -124,10 +163,72 @@ public class UsageEvent extends Event { this.object = object; } + public UsageEvent(Action action, String ip, String userAgent, String xforwarderfor, Context context, DSpaceObject object) + { + + super(checkParams(action, context, object)); + + this.action = action; + + this.setResourceReference(object != null ? Constants.typeText[object.getType()].toLowerCase() + ":" + object.getID() : null); + + switch(action) + { + case CREATE: + case UPDATE: + case DELETE: + case WITHDRAW: + case REINSTATE: + case ADD: + case REMOVE: + this.setModify(true); + break; + default : + this.setModify(false); + } + + if(context != null && context.getCurrentUser() != null) + { + this.setUserId( + String.valueOf(context.getCurrentUser().getID())); + } + this.request = null; + this.ip = ip; + this.userAgent = userAgent; + this.xforwarderfor = xforwarderfor; + this.context = context; + this.object = object; + } + + public HttpServletRequest getRequest() { return request; } + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getUserAgent() { + return userAgent; + } + + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + + public String getXforwarderfor() { + return xforwarderfor; + } + + public void setXforwarderfor(String xforwarderfor) { + this.xforwarderfor = xforwarderfor; + } + public void setRequest(HttpServletRequest request) { this.request = request; } diff --git a/dspace-api/src/main/java/org/dspace/workflow/WorkflowManager.java b/dspace-api/src/main/java/org/dspace/workflow/WorkflowManager.java index 350dacf80a412cbb94ea02358dff7828f117afa3..25409ec5a3ef296c9755e0cd9db189a02931e345 100644 --- a/dspace-api/src/main/java/org/dspace/workflow/WorkflowManager.java +++ b/dspace-api/src/main/java/org/dspace/workflow/WorkflowManager.java @@ -46,26 +46,26 @@ import org.dspace.utils.DSpace; /** * Workflow state machine - * + * * Notes: - * + * * Determining item status from the database: - * + * * When an item has not been submitted yet, it is in the user's personal * workspace (there is a row in PersonalWorkspace pointing to it.) - * + * * When an item is submitted and is somewhere in a workflow, it has a row in the * WorkflowItem table pointing to it. The state of the workflow can be * determined by looking at WorkflowItem.getState() - * + * * When a submission is complete, the WorkflowItem pointing to the item is * destroyed and the archive() method is called, which hooks the item up to the * archive. - * + * * Notification: When an item enters a state that requires notification, * (WFSTATE_STEP1POOL, WFSTATE_STEP2POOL, WFSTATE_STEP3POOL,) the workflow needs * to notify the appropriate groups that they have a pending task to claim. - * + * * Revealing lists of approvers, editors, and reviewers. A method could be added * to do this, but it isn't strictly necessary. (say public List * getStateEPeople( WorkflowItem wi, int state ) could return people affected by @@ -138,7 +138,7 @@ public class WorkflowManager /** * startWorkflow() begins a workflow - in a single transaction do away with * the PersonalWorkspace entry and turn it into a WorkflowItem. - * + * * @param c * Context * @param wsi @@ -176,7 +176,7 @@ public class WorkflowManager // now get the workflow started wfi.setState(WFSTATE_SUBMIT); - advance(c, wfi, null); + advance(c, wfi, null); // Return the workflow item return wfi; @@ -201,7 +201,7 @@ public class WorkflowManager * getOwnedTasks() returns a List of WorkflowItems containing the tasks * claimed and owned by an EPerson. The GUI displays this info on the * MyDSpace page. - * + * * @param e * The EPerson we want to fetch owned tasks for. */ @@ -212,7 +212,7 @@ public class WorkflowManager String myquery = "SELECT * FROM WorkflowItem WHERE owner= ? "; - TableRowIterator tri = DatabaseManager.queryTable(c, + TableRowIterator tri = DatabaseManager.queryTable(c, "workflowitem", myquery,e.getID()); try @@ -236,7 +236,7 @@ public class WorkflowManager /** * getPooledTasks() returns a List of WorkflowItems an EPerson could claim * (as a reviewer, etc.) for display on a user's MyDSpace page. - * + * * @param e * The Eperson we want to fetch the pooled tasks for. */ @@ -265,13 +265,13 @@ public class WorkflowManager tri.close(); } } - + return mylist; } /** * claim() claims a workflow task for an EPerson - * + * * @param wi * WorkflowItem to do the claim on * @param e @@ -322,7 +322,7 @@ public class WorkflowManager * the item arrives at the submit state, then remove the WorkflowItem and * call the archive() method to put it in the archive, and email notify the * submitter of a successful submission - * + * * @param c * Context * @param wi @@ -335,26 +335,26 @@ public class WorkflowManager { advance(c, wi, e, true, true); } - + /** * advance() sends an item forward in the workflow (reviewers, * approvers, and editors all do an 'approve' to move the item forward) if * the item arrives at the submit state, then remove the WorkflowItem and * call the archive() method to put it in the archive, and email notify the * submitter of a successful submission - * + * * @param c * Context * @param wi * WorkflowItem do do the approval on * @param e * EPerson doing the approval - * + * * @param curate * boolean indicating whether curation tasks should be done - * + * * @param record - * boolean indicating whether to record action + * boolean indicating whether to record action */ public static boolean advance(Context c, WorkflowItem wi, EPerson e, boolean curate, boolean record) @@ -362,7 +362,7 @@ public class WorkflowManager { int taskstate = wi.getState(); boolean archived = false; - + // perform curation tasks if needed if (curate && WorkflowCurator.needsCuration(wi)) { @@ -381,9 +381,9 @@ public class WorkflowManager { case WFSTATE_SUBMIT: archived = doState(c, wi, WFSTATE_STEP1POOL, e); - + break; - + case WFSTATE_STEP1: // authorize DSpaceActions.SUBMIT_REVIEW @@ -430,7 +430,7 @@ public class WorkflowManager /** * unclaim() returns an owned task/item to the pool - * + * * @param c * Context * @param wi @@ -481,7 +481,7 @@ public class WorkflowManager * abort() aborts a workflow, completely deleting it (administrator do this) * (it will basically do a reject from any state - the item ends up back in * the user's PersonalWorkspace - * + * * @param c * Context * @param wi @@ -540,7 +540,7 @@ public class WorkflowManager { // get a list of all epeople in group (or any subgroups) EPerson[] epa = Group.allMembers(c, mygroup); - + // there were reviewers, change the state // and add them to the list createTasks(c, wi, epa); @@ -582,7 +582,7 @@ public class WorkflowManager { //get a list of all epeople in group (or any subgroups) EPerson[] epa = Group.allMembers(c, mygroup); - + // there were approvers, change the state // timestamp, and add them to the list createTasks(c, wi, epa); @@ -619,7 +619,7 @@ public class WorkflowManager { // get a list of all epeople in group (or any subgroups) EPerson[] epa = Group.allMembers(c, mygroup); - + // there were editors, change the state // timestamp, and add them to the list createTasks(c, wi, epa); @@ -707,7 +707,7 @@ public class WorkflowManager * Commit the contained item to the main archive. The item is associated * with the relevant collection, added to the search index, and any other * tasks such as assigning dates are performed. - * + * * @return the fully archived item. */ private static Item archive(Context c, WorkflowItem wfi) @@ -742,8 +742,8 @@ public class WorkflowManager EPerson ep = i.getSubmitter(); // Get the Locale Locale supportedLocale = I18nUtil.getEPersonLocale(ep); - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_archive")); - + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_archive")); + // Get the item handle to email to user String handle = HandleManager.findHandle(c, i); @@ -780,7 +780,7 @@ public class WorkflowManager /** * Return the workflow item to the workspace of the submitter. The workflow * item is removed, and a workspace item created. - * + * * @param c * Context * @param wfi @@ -825,7 +825,7 @@ public class WorkflowManager * rejects an item - rejection means undoing a submit - WorkspaceItem is * created, and the WorkflowItem is removed, user is emailed * rejection_message. - * + * * @param c * Context * @param wi @@ -899,10 +899,10 @@ public class WorkflowManager static void deleteTasks(Context c, WorkflowItem wi) throws SQLException { String myrequest = "DELETE FROM TaskListItem WHERE workflow_id= ? "; - + DatabaseManager.updateQuery(c, myrequest, wi.getID()); } - + // send notices of curation activity public static void notifyOfCuration(Context c, WorkflowItem wi, EPerson[] epa, String taskName, String action, String message) throws SQLException, IOException @@ -921,7 +921,7 @@ public class WorkflowManager for (int i = 0; i < epa.length; i++) { Locale supportedLocale = I18nUtil.getEPersonLocale(epa[i]); - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(supportedLocale, + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "flowtask_notify")); email.addArgument(title); email.addArgument(coll.getMetadata("name")); @@ -935,7 +935,7 @@ public class WorkflowManager } catch (MessagingException e) { - log.warn(LogManager.getHeader(c, "notifyOfCuration", "cannot email users" + + log.warn(LogManager.getHeader(c, "notifyOfCuration", "cannot email users" + " of workflow_item_id" + wi.getID())); } } @@ -971,7 +971,7 @@ public class WorkflowManager for (int i = 0; i < epa.length; i++) { Locale supportedLocale = I18nUtil.getEPersonLocale(epa[i]); - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_task")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_task")); email.addArgument(title); email.addArgument(coll.getMetadata("name")); email.addArgument(submitter); @@ -981,17 +981,17 @@ public class WorkflowManager { case WFSTATE_STEP1POOL: message = messages.getString("org.dspace.workflow.WorkflowManager.step1"); - + break; - + case WFSTATE_STEP2POOL: message = messages.getString("org.dspace.workflow.WorkflowManager.step2"); - + break; - + case WFSTATE_STEP3POOL: message = messages.getString("org.dspace.workflow.WorkflowManager.step3"); - + break; } email.addArgument(message); @@ -1030,7 +1030,7 @@ public class WorkflowManager // Get rejector's name String rejector = getEPersonName(e); Locale supportedLocale = I18nUtil.getEPersonLocale(e); - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(supportedLocale,"submit_reject")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale,"submit_reject")); email.addRecipient(getSubmitterEPerson(wi).getEmail()); email.addArgument(title); @@ -1072,7 +1072,7 @@ public class WorkflowManager /** * get the title of the item in this workflow - * + * * @param wi the workflow item object */ public static String getItemTitle(WorkflowItem wi) throws SQLException @@ -1093,7 +1093,7 @@ public class WorkflowManager /** * get the name of the eperson who started this workflow - * + * * @param wi the workflow item */ public static String getSubmitterName(WorkflowItem wi) throws SQLException diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java index 55ec75a7e60cffd899be7f8085332bf8df02026d..9ddef25bc4923b80292400f46989863c68c9e29b 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/WorkflowUtils.java @@ -14,12 +14,14 @@ import org.dspace.core.Context; import org.dspace.core.ConfigurationManager; import org.dspace.core.Email; import org.dspace.core.I18nUtil; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.dspace.eperson.Group; import org.dspace.xmlworkflow.state.Workflow; import org.dspace.xmlworkflow.storedcomponents.CollectionRole; import javax.servlet.http.HttpServletRequest; + import java.io.IOException; import java.sql.SQLException; import java.util.*; @@ -154,9 +156,9 @@ public class WorkflowUtils extends Util{ String recipient = ConfigurationManager .getProperty("alert.recipient"); - if (recipient != null) + if (StringUtils.isNotBlank(recipient)) { - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(c.getCurrentLocale(), "internal_error")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(c.getCurrentLocale(), "internal_error")); email.addRecipient(recipient); email.addArgument(ConfigurationManager diff --git a/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowManager.java b/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowManager.java index ad42112961cc3a274fc317d5ebeb8c6c45bd6b61..2e1ab1c4dd2ce2f288a4c7f27835055af8c86551 100644 --- a/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowManager.java +++ b/dspace-api/src/main/java/org/dspace/xmlworkflow/XmlWorkflowManager.java @@ -107,7 +107,7 @@ public class XmlWorkflowManager { // suppress email, and delete key noEMail.remove(wfi.getItem().getID()); } else { - Email mail = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(c.getCurrentLocale(), emailTemplate)); + Email mail = Email.getEmail(I18nUtil.getEmailFilename(c.getCurrentLocale(), emailTemplate)); for (String argument : arguments) { mail.addArgument(argument); } @@ -396,7 +396,7 @@ public class XmlWorkflowManager { EPerson ep = i.getSubmitter(); // Get the Locale Locale supportedLocale = I18nUtil.getEPersonLocale(ep); - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_archive")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale, "submit_archive")); // Get the item handle to email to user String handle = HandleManager.findHandle(c, i); @@ -856,7 +856,7 @@ public class XmlWorkflowManager { // Get rejector's name String rejector = getEPersonName(e); Locale supportedLocale = I18nUtil.getEPersonLocale(e); - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(supportedLocale,"submit_reject")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(supportedLocale,"submit_reject")); email.addRecipient(wi.getSubmitter().getEmail()); email.addArgument(title); diff --git a/dspace-api/src/main/resources/Messages.properties b/dspace-api/src/main/resources/Messages.properties index ebc7d8cec1770232dae9e3859eac48740123fbbe..c99aaeaa20a60336786b1b1cc996a401fb3d6a68 100644 --- a/dspace-api/src/main/resources/Messages.properties +++ b/dspace-api/src/main/resources/Messages.properties @@ -78,9 +78,12 @@ itemlist.dc.type.degree = Degree itemlist.et-al = et al itemlist.thumbnail = Preview -jsp.adminhelp = Admin Help... +itemlist.title.undefined = Undefined + +jsp.adminhelp = <span class="glyphicon glyphicon-question-sign"></span> jsp.administer = Administer jsp.admintools = Admin Tools +jsp.actiontools = Actions jsp.browse.authors.enter = or enter first few letters: jsp.browse.authors.jump = Jump to: jsp.browse.authors.show = Showing authors {0}-{1} of {2}. @@ -127,6 +130,7 @@ jsp.browse.subject.jump = Jump to: jsp.browse.subject.show = Showing subjects {0}-{1} of {2}. jsp.browse.subject.title = Browse by Subject jsp.collection-home.editsub.button = Edit Submitters +jsp.collection-home.content.range = Collection's Items (Sorted by {0} in {1} order): {2} to {3} of {4} jsp.collection-home.feeds = RSS Feeds jsp.collection-home.heading1 = Collection home page jsp.collection-home.info = See Subscriptions @@ -137,7 +141,7 @@ jsp.collection-home.subscribe = Subscribe jsp.collection-home.subscribe.msg = Subscribe to this collection to receive daily e-mail notification of new additions jsp.collection-home.subscribed = You are subscribed to this collection. jsp.collection-home.unsub = Unsubscribe -jsp.collection-home.display-statistics = View Statistics +jsp.collection-home.display-statistics = <span class="glyphicon glyphicon-stats"></span> jsp.community-home.create1.button = Create collection jsp.community-home.create2.button = Create Sub-community jsp.community-home.feeds = RSS Feeds @@ -145,7 +149,7 @@ jsp.community-home.heading1 = Community home jsp.community-home.heading2 = Collections in this community jsp.community-home.heading3 = Sub-communities within this community jsp.community-home.recentsub = Recent Submissions -jsp.community-home.display-statistics = View Statistics +jsp.community-home.display-statistics = <span class="glyphicon glyphicon-stats"></span> jsp.community-list.create.button = Create Top-Level Community... jsp.community-list.text1 = Shown below is a list of communities and the collections and sub-communities within them. Click on a name to view that community or collection home page. jsp.community-list.title = Communities and Collections @@ -187,12 +191,12 @@ jsp.display-item.suggest = Recommend this jsp.display-item.text1 = Show simple item record jsp.display-item.text2 = Show full item record jsp.display-item.text3 = This item is licensed under a -jsp.display-item.display-statistics = View Statistics +jsp.display-item.display-statistics = <span class="glyphicon glyphicon-stats"></span> jsp.dspace-admin.authorize-advanced.add = Add Policy jsp.dspace-admin.authorize-advanced.advanced = Advanced Policy Manager jsp.dspace-admin.authorize-advanced.clear = Clear Policies jsp.dspace-admin.authorize-advanced.col = Collection: -jsp.dspace-admin.authorize-advanced.text = Allows you to do wildcard additions to and clearing of policies for types of content contained in a collection. Warning, dangerous - removing READ permissions from items will make them not viewable! +jsp.dspace-admin.authorize-advanced.text = Allows you to do wildcard additions to and clearing of policies for items or bitstreams contained in a collection. Warning, dangerous - removing READ permissions from items will make them not viewable! jsp.dspace-admin.authorize-advanced.type = Content Type: jsp.dspace-admin.authorize-advanced.type1 = item jsp.dspace-admin.authorize-advanced.type2 = bitstream @@ -236,6 +240,10 @@ jsp.dspace-admin.confirm-delete-mdschema.confirm = Are you sure t jsp.dspace-admin.confirm-delete-mdschema.heading = Delete Metadata Schema: <code>{0}</code> jsp.dspace-admin.confirm-delete-mdschema.title = Delete Metadata Schema jsp.dspace-admin.confirm-delete-mdschema.warning = This will result in an error if any metadata fields exist within this schema +jsp.dspace-admin.curate.main.title = Curation Tasks +jsp.dspace-admin.curate.main.heading = System Curation Tasks +jsp.dspace-admin.curate.main.info1 = Handle of DSpace Object +jsp.dspace-admin.curate.main.info2 = Hint: Enter [your-handle-prefix]/0 to run a task across entire site (not all tasks may support this capability) jsp.dspace-admin.eperson-browse.canlogin = Can Log In? jsp.dspace-admin.eperson-browse.email = E-mail Address jsp.dspace-admin.eperson-browse.heading = Browse EPeople {0}-{1} of {2} @@ -294,6 +302,12 @@ jsp.dspace-admin.group-eperson-select.title = Select EPerson jsp.dspace-admin.group-group-select.add = Add Group jsp.dspace-admin.group-group-select.heading = Select Group to Add to Group {0} jsp.dspace-admin.group-group-select.title = Select Group +jsp.dspace-admin.batchmetadataimport.title = Batch import metadata (BTE) +jsp.dspace-admin.batchmetadataimport.success = The job was taken over, an email will be sent to the end of work +jsp.dspace-admin.batchmetadataimport.genericerror = An error occured! Please, try again! +jsp.dspace-admin.batchmetadataimport.selectfile = Select data file to upload +jsp.dspace-admin.batchmetadataimport.selectinputfile = Select the type of the input data +jsp.dspace-admin.batchmetadataimport.selectcollection = Select the collection the items will be imported to jsp.dspace-admin.metadataimport.title = Import metadata jsp.dspace-admin.metadataimport.apply = Apply changes jsp.dspace-admin.metadataimport.unknownerror = An unknown error has occurred @@ -322,7 +336,7 @@ jsp.dspace-admin.metadataimport.reinstated = Item Reinstate jsp.dspace-admin.metadataimport.toomany = There are too many changes. Please import fewer changes, adjust the limit, or perform the input directly on the server. jsp.dspace-admin.metadataimport.finished = {0} changes completed successfully. jsp.dspace-admin.index.heading = Administration Tools -jsp.dspace-admin.index.text = Please select an operation from the navigation bar on the left. +jsp.dspace-admin.index.text = Please select an operation from the main menu. jsp.dspace-admin.item-select.enter = Enter the Handle or internal item ID of the item you wish to select. jsp.dspace-admin.item-select.find = Find jsp.dspace-admin.item-select.handle = Handle: @@ -407,6 +421,11 @@ jsp.dspace-admin.supervise-list.heading = Current Superv jsp.dspace-admin.supervise-list.policies.button = Policies jsp.dspace-admin.supervise-list.subheading = This page lists all current supervisory settings, with the option to remove any setting jsp.dspace-admin.supervise-list.title = Item Title +jsp.dspace-admin.supervise-no-workspaceitem.no-wsitems = The supervision order could not be appliled because no workspace item exists. +jsp.dspace-admin.supervise-no-workspaceitem.unselected = The supervision order could not be applied because no workspace item was selected. +jsp.dspace-admin.supervise-no-workspaceitem.heading = Operation Failed +jsp.dspace-admin.supervise-no-workspaceitem.return = Return to the Supervisor Admin page +jsp.dspace-admin.supervise-no-workspaceitem.title = Administer Supervision Orders jsp.dspace-admin.supervise-main.add.button = Add a Supervision Order jsp.dspace-admin.supervise-main.clean.button = Clean Supervision Order Database jsp.dspace-admin.supervise-main.heading = Administer Supervision Orders @@ -524,6 +543,7 @@ jsp.feedback.form.text1 = Thanks for tak jsp.feedback.form.text2 = Please fill out all of the information below. jsp.feedback.form.title = Feedback Form jsp.general.authors.button = Authors +jsp.general.browse = Browse jsp.general.date.button = By Date jsp.general.edit.button = Edit... jsp.general.genericScope = All of DSpace @@ -544,7 +564,7 @@ jsp.general.untitled = Untitled jsp.general.update = Update jsp.general.without-contributor = Anonymous jsp.general.without-date = No date given -jsp.help = Help... +jsp.help = <span class="glyphicon glyphicon-question-sign"></span> jsp.help.formats.contact1 = Please contact your jsp.help.formats.contact2 = DSpace Administrator jsp.help.formats.contact3 = if you have questions about a particular format. @@ -569,11 +589,15 @@ jsp.home.search1 = Search jsp.home.search2 = Enter some text in the box below to search DSpace. jsp.home.title = Home jsp.layout.footer-default.feedback = Feedback -jsp.layout.footer-default.text = <a target="_blank" href="http://www.dspace.org/">DSpace Software</a> Copyright © 2002-2010 <a target="_blank" href="http://www.duraspace.org/">Duraspace</a> +jsp.layout.footer-default.text = <a target="_blank" href="http://www.dspace.org/">DSpace Software</a> Copyright © 2002-2013 <a target="_blank" href="http://www.duraspace.org/">Duraspace</a> +jsp.layout.footer-default.theme-by = Theme by jsp.layout.header-default.about = About DSpace Software jsp.layout.header-default.alt = DSpace +jsp.layout.header-default.brand.heading = DSpace <small>JSPUI</small> +jsp.layout.header-default.brand.description = <h4>DSpace preserves and enables easy and open access to all types of digital content including text, images, moving images, mpegs and data sets</h4> <a href="http://www.dspace.org"><button class="btn btn-primary">Learn More</button></a> jsp.layout.navbar-admin.authorization = Authorization -jsp.layout.navbar-admin.communities-collections = Communities/<br/>Collections +jsp.layout.navbar-admin.communities-collections = Communities & Collections +jsp.layout.navbar-admin.curate = Curation Tasks jsp.layout.navbar-admin.editlicense = Edit Default<br />License jsp.layout.navbar-admin.editnews = Edit News jsp.layout.navbar-admin.epeople = E-people @@ -582,7 +606,9 @@ jsp.layout.navbar-admin.groups = Groups jsp.layout.navbar-admin.help = Help jsp.layout.navbar-admin.items = Items jsp.layout.navbar-admin.logout = Log Out +jsp.layout.navbar-admin.privateitems = Private Items jsp.layout.navbar-admin.metadataimport = Import metadata +jsp.layout.navbar-admin.batchmetadataimport = Batch import metadata (BTE) jsp.layout.navbar-admin.metadataregistry = Metadata<br/>Registry jsp.layout.navbar-admin.statistics = Statistics jsp.layout.navbar-admin.supervisors = Supervisors @@ -630,7 +656,7 @@ jsp.login.not-in-records.text = You have a val jsp.login.not-in-records.title = No User Record Available jsp.login.password.heading = Log In to DSpace jsp.login.password.title = Log In -jsp.morehelp = More Help... +jsp.morehelp = <span class="glyphicon glyphicon-question-sign"></span> jsp.mydspace = My DSpace jsp.mydspace.general.approve = Approve jsp.mydspace.general.backto-mydspace = Back to My DSpace @@ -714,6 +740,7 @@ jsp.mydspace.request.export.migratecollection = Export (migrat jsp.mydspace.request.export.migrateitem = Export (migrate) Item jsp.mydspace.subscriptions.info1 = Your subscriptions have been updated. jsp.mydspace.subscriptions.info2 = To subscribe to a collection, visit the collection's home page, and click on the "Subscribe" button. +jsp.mydspace.subscriptions.select_collection = ( Select Collection ) jsp.mydspace.subscriptions.info3 = Below are the collections you are subscribed to. You will be sent an e-mail each day detailing new items that have become available in these collections. On days that no new items have appeared, no e-mail will be sent. jsp.mydspace.subscriptions.info4 = You are not currently subscribed to any collections. jsp.mydspace.subscriptions.remove.button = Remove All Subscriptions @@ -814,6 +841,7 @@ jsp.search.advanced.type.series = Series jsp.search.advanced.type.sponsor = Sponsor jsp.search.advanced.type.keyword = Subject jsp.search.advanced.type.title = Title +jsp.search.didyoumean = Did you mean: <b><i>{0}</i></b> jsp.search.error.invalid-search-string = Invalid search string jsp.search.error.number-format-exception = Number format exception jsp.search.error.query-too-broad = Your query was too broad. Try a narrower query. @@ -841,6 +869,7 @@ jsp.search.filter.heading = Add filters: jsp.search.filter.hint = Use filters to refine the search results. jsp.search.filter.add = Add jsp.search.filter.applied = Current filters: +jsp.search.filter.any = Any fields jsp.search.filter.title = Title jsp.search.filter.author = Author jsp.search.filter.subject = Subject @@ -851,6 +880,40 @@ jsp.search.filter.op.contains = Contains jsp.search.filter.op.notcontains = Not Contains jsp.search.filter.op.authority = ID jsp.search.filter.op.notauthority = Not ID +jsp.sherpa.title = SHERPA/RoMEO Publisher Policy Database +jsp.sherpa.loading = <p>Fetching policy information from the SHERPA/RoMEO database</p><img alt="loading" src="{0}/sherpa/image/ajax-loader-big.gif" /> +jsp.sherpa.heading = <p class="sherpaDisclaimer"><a href="http://www.sherpa.ac.uk/romeo.php" target="_blank"><img align="left" src="{0}/sherpa/image/romeosmall.gif" width="100" height="54" alt="SHERPA/RoMEO Database" border="0"></a> All SHERPA/RoMEO information is correct to the best of our knowledge but should not be relied upon for legal advice. SHERPA cannot be held responsible for the re-use of RoMEO data, or for alternative interpretations which are derived from this information.</p> +jsp.sherpa.error = <p class="sherpaError">Sorry, we have had trouble querying the SHERPA/RoMEO Database. No data are availables, try later or check directly the <a href="http://www.sherpa.ac.uk/romeo.php" target="_blank">SHERPA/RoMEO WebSite</a>.</p> +jsp.sherpa.noresult = <p class="sherpaNoResult">Sorry, there are not data in the <a href="http://www.sherpa.ac.uk/romeo.php" target="_blank">SHERPA/RoMEO Database</a> for the ISSNs that you have entered.</p> +jsp.sherpa.oneresult = <p>The <a href="http://www.sherpa.ac.uk/romeo.php" target="_blank">SHERPA/RoMEO</a> Database provide the following data for the journal that you have entered.</p> +jsp.sherpa.moreresults = <p>The ISSNs that you have entered match with multiple journals, please review them. For any journals you can find below the publisher policy.</p> +jsp.sherpa.jornaltitle = <p><b>Journal:</b> {0} +jsp.sherpa.jornalissn = (ISSN\: {0})</p> +jsp.sherpa.publisher = <p><b>Publisher:</b> <a href="{1}" target="_blank">{0}</a></p> +jsp.sherpa.publisher.onlyname = <p><b>Publisher:</b> {0}</p> +jsp.sherpa.publisher.unknow = <p><b>Publisher:</b> Unknow</p> +jsp.sherpa.publisher.nodata = <p>Sorry, there are not data about this publisher in the <a href="http://www.sherpa.ac.uk/romeo.php" target="_blank">SHERPA/RoMEO</a> Database. If you know its policies or you want suggest to add the Publisher to the SHERPA/RoMEO Database you can use <a href="http://www.sherpa.ac.uk/romeoupdate.php" target="_blank">this form</a></p> +jsp.sherpa.pre-print.can = <p><b>Author''s Pre-prints:</b><img src="{0}/sherpa/image/can.gif" alt="can" border="0" /> Author <b>can</b> archive pre-print (ie pre-refereeing)</p> +jsp.sherpa.pre-print.cannot = <p><b>Author''s Pre-prints:</b><img src="{0}/sherpa/image/cannot.gif" alt="cannot" border="0" /> Author <b>cannot</b> archive pre-print (ie pre-refereeing)</p> +jsp.sherpa.pre-print.restricted = <p><b>Author''s Pre-prints:</b><img src="{0}/sherpa/image/restricted.gif" alt="restricted" border="0" /> <b>Subject to Restrictions below</b>, author <b>can</b> archive pre-print (ie pre-refereeing)</p> +jsp.sherpa.pre-print.unclear = <p><b>Author''s Pre-prints:</b><img src="{0}/sherpa/image/unclear.gif" alt="unclear" border="0" /> Archiving status unclear</p> +jsp.sherpa.pre-print.unknown = <p><b>Author''s Pre-prints:</b> - No information</p> +jsp.sherpa.post-print.can = <p><b>Author''s Post-prints:</b><img src="{0}/sherpa/image/can.gif" alt="can" border="0" /> Author <b>can</b> archive post-print (ie final draft post-refereeing)</p> +jsp.sherpa.post-print.cannot = <p><b>Author''s Post-prints:</b><img src="{0}/sherpa/image/cannot.gif" alt="cannot" border="0" /> Author <b>cannot</b> archive post-print (ie final draft post-refereeing)</p> +jsp.sherpa.post-print.restricted = <p><b>Author''s Post-prints:</b><img src="{0}/sherpa/image/restricted.gif" alt="restricted" border="0" /> <b>Subject to Restrictions below</b>, author <b>can</b> archive post-print (ie final draft post-refereeing)</p> +jsp.sherpa.post-print.unclear = <p><b>Author''s Post-prints:</b><img src="{0}/sherpa/image/unclear.gif" alt="unclear" border="0" /> Archiving status unclear</p> +jsp.sherpa.post-print.unknown = <p><b>Author''s Post-prints:</b> - No information</p> +jsp.sherpa.publisher-version.can = <p><b>Publisher''s Version:</b><img src="{0}/sherpa/image/can.gif" alt="can" border="0" /> Author <b>can</b> archive publisher''s version/PDF</p> +jsp.sherpa.publisher-version.cannot = <p><b>Publisher''s Version:</b><img src="{0}/sherpa/image/cannot.gif" alt="cannot" border="0" /> Author <b>cannot</b> archive publisher''s version/PDF</p> +jsp.sherpa.publisher-version.restricted = <p><b>Publisher''s Version:</b><img src="{0}/sherpa/image/restricted.gif" alt="restricted" border="0" /> <b>Subject to Restrictions below</b>, author <b>can</b> archive publisher''s version/PDF</p> +jsp.sherpa.publisher-version.unclear = <p><b>Publisher''s Version:</b><img src="{0}/sherpa/image/unclear.gif" alt="unclear" border="0" /> Archiving status unclear</p> +jsp.sherpa.publisher-version.unknown = <p><b>Publisher''s Version:</b> - No information</p> + +jsp.sherpa.generalconditions = <p><b>General conditions:</b></p> +jsp.sherpa.paidoption = <p><b>Paid open access:</b> <a href="{1}" target="_blank">{0}</a>. {2}</p> +jsp.sherpa.copyright = <p><b>Copyright:</b></p> +jsp.sherpa.publisher.romeocolour = <p><b>RoMEO:</b> This is a RoMEO {0} publisher</p> +jsp.sherpa.legend = <div class="sherpaLegend"><table class="romeoColour table"><thead><tr><th>ROMEO colour</th><th>Archiving policy</th></tr></thead><tbody><tr><td class="greenRomeoPublisher">green</td><td>can archive pre-print <i>and</i> post-print or publisher's version/PDF</td></tr><tr><td class="blueRomeoPublisher">blue</td><td>can archive post-print (ie final draft post-refereeing) or publisher's version/PDF</td></tr><tr><td class="yellowRomeoPublisher">yellow</td><td>can archive pre-print (ie pre-refereeing)</td></tr><tr><td class="grayRomeoPublisher">gray</td><td>publishers found in DOAJ that have not yet been analyzed by RoMEO</td></tr><tr><td class="whiteRomeoPublisher">white</td><td>archiving not formally supported</td></tr></tbody></table></div> jsp.statistics.title = Statistics jsp.statistics.heading.visits = Total Visits jsp.statistics.heading.monthlyvisits = Total Visits per Month @@ -863,6 +926,30 @@ jsp.statistics.no-report.title = No reports cur jsp.statistics.report.info1 = Most recent general report jsp.statistics.report.info2 = Monthly reports: jsp.statistics.report.title = Statistical Summary +jsp.submit.access.title = Access +jsp.submit.access.error_1 = Invalid Start Date Format +jsp.submit.access.error_2 = Missing Start Date +jsp.submit.access.error_3 = Invalid Group Selected +jsp.submit.access.error_4 = Duplicate Policy +jsp.submit.access.error_5 = Duplicate Policy +jsp.submit.access.plist.heading = Group policies +jsp.submit.access.access_setting.heading = Access Setting +jsp.submit.access.private_setting.heading = Private Item +jsp.submit.access.private_setting.help = If selected, the item won't be searchable. +jsp.submit.access.private_setting.label = Private\: +jsp.submit.access.private_setting.review.discoverable = The item will be searchable +jsp.submit.access.private_setting.review.notdiscoverable = The item will <b>not</b> be searchable +jsp.submit.access.review.button = Edit access settings +jsp.submit.access.review.embargoed = Access is allowed from {0} +jsp.submit.access.embargo_setting.heading = Embargo +jsp.submit.access.policy_setting.help = Policies listed in this section override any default policies for the collection you're submitting to. If you wish to set an embargo but the target collection allows access for any user, you must set a policy that allows access for the Anonymous group only from a specific date onwards. +jsp.submit.access.policy_setting.label_name = Name\: +jsp.submit.access.policy_setting.label_group = Group\: +jsp.submit.access.policy_setting.label_date = Embargo Access until Specific Date\: +jsp.submit.access.policy_setting.label_date.help = Accepted format: yyyy, yyyy-mm, yyyy-mm-dd +jsp.submit.access.policy_setting.label_reason = Reason\: +jsp.submit.access.submit_add_policy.button = Confirm Policy & add another +jsp.submit.access.edit_policy.heading = Edit Policy jsp.submit.cancel.continue.button = Oops, continue submission jsp.submit.cancel.info = Do you want the half-finished submission removed, or do you want to keep it so you can carry on working on it later? You can also return to where you where during the submission process if you clicked Cancel by accident. jsp.submit.cancel.remove.button = Remove the submission @@ -886,7 +973,15 @@ 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.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.skip = Skip file upload > +jsp.submit.choose-file.skip = Skip file upload > +jsp.submit.choose-file.upload-ajax.button.cancel = Cancel +jsp.submit.choose-file.upload-ajax.button.select-file = Select a file... +jsp.submit.choose-file.upload-ajax.dialog.close = Ok +jsp.submit.choose-file.upload-ajax.fileRequired.title = File required +jsp.submit.choose-file.upload-ajax.fileRequired.info = You must upload at least one file for this item +jsp.submit.choose-file.upload-ajax.uploadInit = Upload is starting... +jsp.submit.choose-file.upload-ajax.uploadInProgress = Upload in progress... <b>{0}%</b> [{1} bytes of {2}] +jsp.submit.choose-file.upload-ajax.uploadCompleted = Upload completed. 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.again = Submit another item to the same collection @@ -901,18 +996,21 @@ jsp.submit.creative-commons.info2 = To license you jsp.submit.creative-commons.info3 = Your browser must support IFrames to use this feature jsp.submit.creative-commons.skip.button = Skip Creative Commons > jsp.submit.creative-commons.title = Use a Creative Commons License +jsp.submit.edit-bitstream-access.title = Edit Bitstream Access +jsp.submit.edit-bitstream-access.heading = Edit Bitstream Access +jsp.submit.edit-bitstream-access.save.button = Save jsp.submit.edit-metadata.button.add = Add More -jsp.submit.edit-metadata.button.remove = Remove This Entry +jsp.submit.edit-metadata.button.remove = Remove Entry jsp.submit.edit-metadata.button.remove2 = Remove jsp.submit.edit-metadata.cancelsave = Cancel/Save jsp.submit.edit-metadata.controlledvocabulary = Subject Categories jsp.submit.edit-metadata.day = Day: -jsp.submit.edit-metadata.firstname = First name(s) + "Jr"<br/> e.g. <strong>Donald Jr</strong> +jsp.submit.edit-metadata.firstname = First name(s) + "Jr", e.g. Donald Jr jsp.submit.edit-metadata.heading = Submit: Describe this Item -jsp.submit.edit-metadata.help = (More Help...) +jsp.submit.edit-metadata.help = <span class="glyphicon glyphicon-question-sign"></span> jsp.submit.edit-metadata.info1 = Please fill in the requested information about this submission below. In most browsers, you can use the tab key to move the cursor to the next input box or button, to save you having to use the mouse each time. jsp.submit.edit-metadata.info2 = Please fill further information about this submission below. -jsp.submit.edit-metadata.lastname = Last name<br/>e.g. <strong>Smith</strong> +jsp.submit.edit-metadata.lastname = Last name, e.g. Smith jsp.submit.edit-metadata.month = Month: jsp.submit.edit-metadata.next = Next > jsp.submit.edit-metadata.no_month = (No Month) @@ -925,6 +1023,8 @@ jsp.submit.general.cancel-or-save.button = Cancel/Save jsp.submit.general.next = Next > jsp.submit.general.previous = < Previous jsp.submit.general.submit = Submit +jsp.submit.general.cancel = Cancel +jsp.submit.general.save = Save jsp.submit.get-file-format.choose.button = Choose automatically-recognized type jsp.submit.get-file-format.format = File Format: jsp.submit.get-file-format.heading = Submit: Select File Format @@ -954,6 +1054,7 @@ jsp.submit.no-theses.info3 = Please note th jsp.submit.no-theses.info4 = For more information please <strong>contact the DSpace site administrators</strong>: jsp.submit.no-theses.info5 = Thank you for your interest in DSpace! jsp.submit.no-theses.title = Theses Not Accepted in DSpace +jsp.submit.progressbar.access = Access jsp.submit.progressbar.complete = Complete jsp.submit.progressbar.CClicense = License jsp.submit.progressbar.describe = Describe @@ -986,6 +1087,9 @@ jsp.submit.review.title = Verify Submiss jsp.submit.review.unknown = (Unknown) jsp.submit.review.upload1 = Uploaded Files: jsp.submit.review.upload2 = Uploaded File: +jsp.submit.review.policies.founded = Found {0} access settings +jsp.submit.review.policies.openaccess = Open Access +jsp.submit.review.policies.embargoed = Access is allowed from {0} jsp.submit.saved.info = Your submission has been saved for you to finish later. You can continue the submission by going to your "My DSpace" page and clicking on the relevant "Resume" button. jsp.submit.saved.title = Submission Saved jsp.submit.select-collection.collection = Collection @@ -1002,8 +1106,9 @@ jsp.submit.show-license.info2 = <strong>Not gr jsp.submit.show-license.notgrant.button = I Do Not Grant the License jsp.submit.show-license.title = DSpace Distribution License jsp.submit.show-uploaded-file.checksum = Checksum -jsp.submit.show-uploaded-file.click1.button = Click here if this is the wrong format -jsp.submit.show-uploaded-file.click2.button = Click here if this is the wrong file +jsp.submit.show-uploaded-file.click1.button = Change format +jsp.submit.show-uploaded-file.click2.button = Change file +jsp.submit.show-uploaded-file.click3.button = Embargo settings jsp.submit.show-uploaded-file.file = File jsp.submit.show-uploaded-file.format = File Format jsp.submit.show-uploaded-file.heading1 = Submit: File Uploaded Successfully @@ -1040,6 +1145,7 @@ jsp.submit.upload-file-list.button4 = Add Another Fi jsp.submit.upload-file-list.button5 = < Previous jsp.submit.upload-file-list.button6 = Next > jsp.submit.upload-file-list.button7 = Cancel/Save +jsp.submit.upload-file-list.button8 = Policies jsp.submit.upload-file-list.empty1 = <em>None</em> jsp.submit.upload-file-list.heading1 = Submit: File Uploaded Successfully jsp.submit.upload-file-list.heading2 = Submit: Uploaded Files @@ -1060,6 +1166,7 @@ jsp.submit.upload-file-list.tableheading3 = Size jsp.submit.upload-file-list.tableheading4 = Description jsp.submit.upload-file-list.tableheading5 = File Format jsp.submit.upload-file-list.tableheading6 = Checksum +jsp.submit.upload-file-list.tableheading7 = Access Settings jsp.submit.upload-file-list.title = Uploaded Files jsp.submit.verify-prune.heading = Submit: Caution jsp.submit.verify-prune.info1 = The changes you've made to the first "Describe Your Item" page will affect your submission: @@ -1104,9 +1211,36 @@ jsp.tools.confirm-delete-item.title = Delete Item jsp.tools.confirm-withdraw-item.question = Are you sure this item should be withdrawn from the archive? jsp.tools.confirm-withdraw-item.title = Withdraw Item jsp.tools.confirm-withdraw-item.withdraw.button = Withdraw +jsp.tools.confirm-privating-item.question = Are you sure this item should be made private? +jsp.tools.confirm-privating-item.title = Make item Private +jsp.tools.confirm-privating-item.privating.button = Make item Private jsp.tools.creative-commons-edit.heading1 = Add or Replace Creative Commons License jsp.tools.creative-commons-edit.title = DSpace Distribution License +jsp.tools.curate.collection.title = Curate Collection +jsp.tools.curate.collection.heading = Curate Collection: {0} +jsp.tools.curate.community.title = Curate Community +jsp.tools.curate.community.heading = Curate Community: {0} +jsp.tools.curate.item.title = Curate Item +jsp.tools.curate.item.heading = Curate Item: {0} +jsp.tools.curate.perform.button = Perform +jsp.tools.curate.perform.failure = The task exited unexpectedly or failed. For more information, please contact the site administrator or check your system logs. +jsp.tools.curate.perform.message.failure = STATUS: Failure, RESULT: {1} +jsp.tools.curate.perform.message.success = STATUS: {0}, RESULT: {1} +jsp.tools.curate.perform.success = The task was completed successfully. +jsp.tools.curate.queue.button = Queue +jsp.tools.curate.queue.failure = The task could not be queued. An error occurred. For more information, please contact the site administrator or check your system logs. +jsp.tools.curate.queue.message.failure = RESULT: FAILED to queue Object ''{0}'' in ''{1}'' Queue +jsp.tools.curate.queue.message.success = RESULT: Object ''{0}'' queued in ''{1}'' Queue +jsp.tools.curate.queue.success = The task was queued successfully. +jsp.tools.curate.return.collection.button = Return to Edit Collection Page +jsp.tools.curate.return.community.button = Return to Edit Community Page +jsp.tools.curate.return.item.button = Return to Edit Item Page +jsp.tools.curate.select-group.tag = Choose from the following groups +jsp.tools.curate.select-task.tag = Task +jsp.tools.curate.task.name = Task: {0} jsp.tools.edit-collection.button.delete = Delete this Collection... +jsp.tools.edit-collection.form.basic-metadata = Collection's Metadata +jsp.tools.edit-collection.form.collection-settings = Collection's settings jsp.tools.edit-collection.form.button.add-logo = Upload new logo... jsp.tools.edit-collection.form.button.cancel = Cancel jsp.tools.edit-collection.form.button.create = Create... @@ -1116,6 +1250,7 @@ jsp.tools.edit-collection.form.button.delete-logo = Delete (no log jsp.tools.edit-collection.form.button.edit = Edit... jsp.tools.edit-collection.form.button.set-logo = Upload a logo... jsp.tools.edit-collection.form.button.update = Update +jsp.tools.edit-collection.form.button.curate = Curate... jsp.tools.edit-collection.form.label1 = Name: jsp.tools.edit-collection.form.label10 = Submitters: jsp.tools.edit-collection.form.label11 = Step: @@ -1123,7 +1258,7 @@ jsp.tools.edit-collection.form.label12 = Collection Adm jsp.tools.edit-collection.form.label13 = Item template: jsp.tools.edit-collection.form.label14 = Collection's Authorizations: jsp.tools.edit-collection.form.label15 = Harvesting Settings -jsp.tools.edit-collection.form.label16 = Content Source +jsp.tools.edit-collection.form.label16 = Content<br/> Source jsp.tools.edit-collection.form.label17 = This is a standard DSpace collection jsp.tools.edit-collection.form.label18 = This collection harvests its content from an external source jsp.tools.edit-collection.form.label19 = OAI Provider @@ -1132,11 +1267,12 @@ jsp.tools.edit-collection.form.label21 = Metadata Forma jsp.tools.edit-collection.form.label21.select.qdc = Qualified Dublin Core jsp.tools.edit-collection.form.label21.select.dc = Dublin Core jsp.tools.edit-collection.form.label21.select.dim = DSpace Intermediate Format -jsp.tools.edit-collection.form.label22 = Content being Harvested +jsp.tools.edit-collection.form.label22 = Content<br/> being<br/> Harvested jsp.tools.edit-collection.form.label23 = Harvest metadata only. jsp.tools.edit-collection.form.label24 = Harvest metadata and references to bitstreams (requires ORE support). jsp.tools.edit-collection.form.label25 = Harvest metadata and bitstreams (requires ORE support). jsp.tools.edit-collection.form.label26 = Last Harvest Result +jsp.tools.edit-collection.form.label27 = Collection's Curations: jsp.tools.edit-collection.form.label2 = Short Description jsp.tools.edit-collection.form.label3 = Introductory text (HTML): jsp.tools.edit-collection.form.label4 = Copyright text (plain text): @@ -1152,6 +1288,8 @@ jsp.tools.edit-collection.wf-role1 = Accept/Reject jsp.tools.edit-collection.wf-role2 = Accept/Reject/Edit Metadata jsp.tools.edit-collection.wf-role3 = Edit Metadata jsp.tools.edit-community.button.delete = Delete this Community... +jsp.tools.edit-community.form.basic-metadata = Community's metadata +jsp.tools.edit-community.form.community-settings = Community's settings jsp.tools.edit-community.form.button.add-logo = Upload new logo... jsp.tools.edit-community.form.button.cancel = Cancel jsp.tools.edit-community.form.button.create = Create @@ -1160,6 +1298,7 @@ jsp.tools.edit-community.form.button.delete-logo = Delete (no log jsp.tools.edit-community.form.button.edit = Edit... jsp.tools.edit-community.form.button.set-logo = Upload a logo... jsp.tools.edit-community.form.button.update = Update +jsp.tools.edit-community.form.button.curate = Curate... jsp.tools.edit-community.form.label1 = Name: jsp.tools.edit-community.form.label2 = Short Description jsp.tools.edit-community.form.label3 = Introductory text (HTML): @@ -1167,12 +1306,14 @@ jsp.tools.edit-community.form.label4 = Copyright text jsp.tools.edit-community.form.label5 = Side bar text (HTML): jsp.tools.edit-community.form.label6 = Logo: jsp.tools.edit-community.form.label7 = Community's Authorizations: -jsp.tools.edit-community.form.label8 = Community Administrators: +jsp.tools.edit-community.form.label8 = Community Administrators: +jsp.tools.edit-community.form.label9 = Community's Curations: jsp.tools.edit-community.heading1 = Create Community jsp.tools.edit-community.heading2 = Edit Community {0} jsp.tools.edit-community.title = Edit Community jsp.tools.edit-item-form.addbit.button = Add Bitstream jsp.tools.edit-item-form.addcc.button = Add Creative Commons License +jsp.tools.edit-item-form.form.button.curate = Curate... jsp.tools.edit-item-form.collections = In Collections: jsp.tools.edit-item-form.delete-w-confirm.button = Delete (Expunge)... jsp.tools.edit-item-form.elem0 = Schema @@ -1187,9 +1328,11 @@ jsp.tools.edit-item-form.elem7 = Name jsp.tools.edit-item-form.elem8 = Source jsp.tools.edit-item-form.elem9 = Description jsp.tools.edit-item-form.elem12 = Order +jsp.tools.edit-item-form.form.label1 = Item's Curations: jsp.tools.edit-item-form.handle = Handle: jsp.tools.edit-item-form.heading = Bitstreams -jsp.tools.edit-item-form.item = Item's Authorizations: +jsp.tools.edit-item-form.details = Item's Details +jsp.tools.edit-item-form.item = Authorizations... jsp.tools.edit-item-form.itemID = Item internal ID: jsp.tools.edit-item-form.itempage = Item page: jsp.tools.edit-item-form.modified = Last modified: @@ -1206,6 +1349,8 @@ jsp.tools.edit-item-form.unlock = Unlock the aut jsp.tools.edit-item-form.move-up = Move up jsp.tools.edit-item-form.move-down = Move down jsp.tools.edit-item-form.order-update = Update bitstream order +jsp.tools.edit-item-form.privating-w-confirm.button = Make item Private... +jsp.tools.edit-item-form.publicize.button = Make item Public jsp.tools.eperson-list.close.button = Close 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. @@ -1271,7 +1416,7 @@ jsp.tools.group-select-list.th.name = Name jsp.tools.group-select-list.th.name.sortedby = Name ↑ jsp.tools.group-select-list.title = Select Groups jsp.tools.itemmap-browse.add = Check the box next to items you wish to add to {0}, and choose ''Add''. -jsp.tools.itemmap-browse.heading-authors = Browse Items matching author ''{0}'' +jsp.tools.itemmap-browse.heading-search = Browse Items matching query: ''{0}'' jsp.tools.itemmap-browse.heading-collection = Items Mapped to Collection {1} from Collection {0} jsp.tools.itemmap-browse.remove = Check the box next to items you wish to unmap from {0}, and choose ''Remove''. jsp.tools.itemmap-browse.th.action = Action @@ -1280,6 +1425,9 @@ jsp.tools.itemmap-browse.th.date = Date jsp.tools.itemmap-browse.th.remove = Unmap jsp.tools.itemmap-browse.th.title = Title jsp.tools.itemmap-browse.title = Browse Items +jsp.tools.itemmap-browse.info.change-page = Your query return lot of results. You can navigate your result with the following buttons. Please note that checked items will be mapped only clicking on the Add button. +jsp.tools.itemmap-browse.previous.button = Previous page +jsp.tools.itemmap-browse.next.button = Next page jsp.tools.itemmap-info.button.continue = Continue jsp.tools.itemmap-info.heading = Item Map Info jsp.tools.itemmap-info.msg.added = Add item {0} @@ -1291,12 +1439,12 @@ jsp.tools.itemmap-info.title = Item Map Info jsp.tools.itemmap-main.collection = Collection: "{0}" jsp.tools.itemmap-main.heading = Item Mapper - Map Items from Other Collections jsp.tools.itemmap-main.info1 = There are {0} items owned by this collection, and {1} items mapped in from other collections. -jsp.tools.itemmap-main.info4 = Import By Author Match -jsp.tools.itemmap-main.info5 = Enter part of an author's name for a list of matching items +jsp.tools.itemmap-main.info4 = Import By Search +jsp.tools.itemmap-main.info5 = Enter a search query for a list of matching items jsp.tools.itemmap-main.info6 = Browse Items Imported From Collections: jsp.tools.itemmap-main.info7 = Click on collection names to browse for items to remove that were mapped in from that collection. jsp.tools.itemmap-main.info8 = This collection has no items mapped into it. -jsp.tools.itemmap-main.search.button = Search Authors +jsp.tools.itemmap-main.search.button = Search jsp.tools.itemmap-main.title = Item Mapper jsp.tools.move-item.button = Move jsp.tools.move-item.collection.from.msg = Collection to move from @@ -1350,6 +1498,7 @@ news-side.html = news-side.html news-top.html = news-top.html +org.dspace.app.itemexport.no-result = The DSpaceObject that you specified has no items. org.dspace.app.webui.jsptag.CollectionListTag.collectionName = Collection Name org.dspace.app.webui.jsptag.CommunityListTag.communityName = Community Name org.dspace.app.webui.jsptag.ItemListTag.authors = Authors @@ -1393,6 +1542,7 @@ org.dspace.app.webui.servlet.FeedServlet.search.title org.dspace.app.webui.servlet.FeedServlet.search.title.default = The DSpace search engine org.dspace.app.webui.servlet.SuggestServlet.recipient = colleague org.dspace.app.webui.servlet.SuggestServlet.sender = A DSpace user +org.dspace.app.webui.servlet.admin.CurationServlet.null-result = Nothing to do for this DSpace object. org.dspace.app.webui.servlet.admin.MetadataFieldRegistryServlet.badelemchar = The element cannot contain periods, underscores or spaces. org.dspace.app.webui.servlet.admin.MetadataFieldRegistryServlet.badqualchar = The qualifier cannot contain periods, underscores or spaces. org.dspace.app.webui.servlet.admin.MetadataFieldRegistryServlet.createfailed = The requested field could not be created due to an already existing field with an identical name. @@ -1517,3 +1667,183 @@ 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) + +# reset password +jsp.dspace-admin.eperson-main.ResetPassword.title = Reset password +jsp.dspace-admin.eperson-main.ResetPassword.head = Reset password +jsp.dspace-admin.eperson-main.ResetPassword.submit = Reset password +jsp.dspace-admin.eperson-main.ResetPassword.success_notice = An email message has been sent to the user containing a token that may be used to choose a new password. +jsp.dspace-admin.eperson-main.ResetPassword-error.errormsg = Sorry, an error has occurred when the system try to send email with instructions. +jsp.dspace-admin.eperson-main.ResetPassword.returntoedit = Return to the Administer EPeople page + +# login as +jsp.dspace-admin.eperson-main.LoginAs.submit = Login As +jsp.dspace-admin.eperson-main.loginAs.authorize.errormsg = Reason: you may not assume the login as another administrator. +jsp.dspace-admin.eperson-main.loginAs.authorize.title = Authorization Error +jsp.dspace-admin.eperson-main.loginAs.backtoeditpeople = Back to E-people Admin page + +org.dspace.app.webui.jsptag.access-setting.legend = Embargo +org.dspace.app.webui.jsptag.access-setting.label_name = Name\: +org.dspace.app.webui.jsptag.access-setting.label_group = Groups\: +org.dspace.app.webui.jsptag.access-setting.label_embargo = Access for selected group: +org.dspace.app.webui.jsptag.access-setting.label_reason = Reason\: +org.dspace.app.webui.jsptag.access-setting.label_date = Embargo Date\: +org.dspace.app.webui.jsptag.access-setting.radio0 = Allow access once item is accepted into archive +org.dspace.app.webui.jsptag.access-setting.radio1 = Embargo until specific date +org.dspace.app.webui.jsptag.access-setting.radio_help = The first day from which access is allowed. Accepted format: yyyy, yyyy-mm, yyyy-mm-dd +org.dspace.app.webui.jsptag.access-setting.button_confirm = Confirm Policy & another +org.dspace.app.webui.jsptag.policies-list.label_name = Name +org.dspace.app.webui.jsptag.policies-list.label_action = Action +org.dspace.app.webui.jsptag.policies-list.label_group = Group +org.dspace.app.webui.jsptag.policies-list.label_sdate = Start Date +org.dspace.app.webui.jsptag.policies-list.label_edate = End Date +org.dspace.app.webui.jsptag.policies-list.no_policies = No group policies have been set up for this item + +org.dspace.app.webui.jsptag.access-setting.name_help = A short, descriptive name for the policy (up to 30 characters). May be shown to end users. Example: "Staff-only". Optional but recommended. +org.dspace.app.webui.jsptag.access-setting.reason_help = The reason for the embargo, typically for internal use only. Optional. + +jsp.layout.navbar-admin.accesscontrol = Access Control +jsp.layout.navbar-admin.contents = Content +jsp.layout.navbar-admin.settings = General Settings + +jsp.submit.start-lookup-submission.title = New submission +jsp.submit.start-lookup-submission.heading = New submission: get data from bibliographic external service +jsp.submit.start-lookup-submission.tabs.search = Search Form +jsp.submit.start-lookup-submission.tabs.result = Results +jsp.submit.start-lookup-submission.identifiers = Search for identifier + +jsp.submit.start-lookup-submission.identifiers.hints = Fill in publication identifiers (DOI is preferable) and then press "Search". A list of all matching publications will be shown to you to select in order to proceed with the submission process. +jsp.submit.start-lookup-submission.identifier-doi = DOI (Digital Object Identifier) +jsp.submit.start-lookup-submission.identifier-doi.hint = e.g. 10.1021/ac0354342 +jsp.submit.start-lookup-submission.identifier-pubmed = PubMed ID +jsp.submit.start-lookup-submission.identifier-pubmed.hint = e.g. 20524090 +jsp.submit.start-lookup-submission.identifier-arxiv = arXiv ID +jsp.submit.start-lookup-submission.identifier-arxiv.hint = e.g. arXiv:1302.1497 +jsp.submit.start-lookup-submission.identifier-cinii = CiNii NAID +jsp.submit.start-lookup-submission.identifier-cinii.hint = e.g. 110004744915 +jsp.submit.start-lookup-submission.search = Free search + +jsp.submit.start-lookup-submission.search.hints = Insert base info about publication: either <b>title</b> or <b>author/year</b> is required.<br/>If you know any unique identifier about publication like <b>DOI</b>, <b>Pubmed</b>, or <b>arXiv</b> you can switch on the <span id="link-ricerca-identificatore">identifier search mode</span>. +jsp.submit.start-lookup-submission.search.title = Title +jsp.submit.start-lookup-submission.search.year = Year +jsp.submit.start-lookup-submission.search.authors = Authors/Publishers +jsp.submit.start-lookup-submission.identifier.lookup = Search +jsp.submit.start-lookup-submission.search-go = Search +jsp.submit.start-lookup-submission.exit = Exit +jsp.submit.start-lookup-submission.search-loading.title = Loading... +jsp.submit.start-lookup-submission.search-loading.hint = Quering the external service to retrieve the requested publications. Please, wait for the request to complete. if you close this window, the request will be aborted. +jsp.submit.edit-metadata.affiliation.select = Multiple possible matches, please select one to proceed! +jsp.submit.edit-metadata.affiliation.other = Other +jsp.submit.start-lookup-submission.no-collection = No collection selected +jsp.submit.start-lookup-submission.no-collection-warn.title = Warning, no collection +jsp.submit.start-lookup-submission.no-collection-warn.hint = The collection of the publication is required. +jsp.submit.start-lookup-submission.manual-submission = Default mode Submission +jsp.submit.start-lookup-submission.button.manual-submission = Manual submission +jsp.submit.start-lookup-submission.select.collection.label = Select collections: +jsp.submit.start-lookup-submission.select.collection.defaultoption = Select... +jsp.submit.start-lookup-submission.noresult = No results available! + +jsp.submit.start-lookup-submission.js.errormessage = Sorry, an error occurred. Try again. If this message shows again, please, contact administrators and continue to insert the submission manually. Thank you! +jsp.submit.start-lookup-submission.js.detailsbuttonmessage = See details & import the record +jsp.submit.start-lookup-submission.js.filldataandstartbuttonmessage = Fill data and start submission +jsp.submit.start-lookup-submission.js.titlepopupmessage = Publication details +jsp.submit.start-lookup-submission.no-collection.dialog.return = I understand + +jsp.submit.start-lookup-submission.byfile = Upload a file +jsp.submit.start-lookup-submission.byfile.process = Process +jsp.submit.start-lookup-submission.byfile.hints = Select a file to upload and its type from the drop-down menu. If "Preview Mode" is enabled, the list of the publications in the file will be shown to you to select the one for submission. If it is disabled, all publications will be imported in your MyDSpace page as "Unfinished Submissions" while the first one will go through the submission process. +jsp.submit.start-lookup-submission.byfile.chooseprovider = Select data type +jsp.submit.start-lookup-submission.byfile.file = File +jsp.submit.start-lookup-submission.byfile.filepreview = Preview mode +jsp.submit.start-lookup-submission.byfile.filecollection = Collection + +#Versioning +jsp.general.version.button = Create version of this item +jsp.general.version.history.button = Show version history + +jsp.dspace-admin.version-summary.title = Create Version +jsp.dspace-admin.version-summary.heading = Version +jsp.dspace-admin.version-summary.text3 = Create new version of item: {0} +jsp.version.version-summary.submit_version = Version + +jsp.dspace-admin.version-summary.text = Reason for creating new version + +jsp.version.history.delete.success.message = Ok, version/versions has been removed +jsp.version.history.delete.warning.head1 = Confirm Deletion(s) +jsp.version.history.delete.warning.para1 = Are you sure you want to delete these versions? +jsp.version.history.delete.warning.para2 = PLEASE NOTE: That by deleting these versions, the associated items will no longer be accessible. + +jsp.version.history.title = Version History +jsp.version.history.head2 = Version History +jsp.version.history.column1 = Version +jsp.version.history.column2 = Item +jsp.version.history.column3 = Editor +jsp.version.history.column4 = Date +jsp.version.history.column5 = Summary +jsp.version.history.restore = Restore +jsp.version.history.update = Edit +jsp.version.history.legend = <span class="glyphicon glyphicon-asterisk"></span> Selected version +jsp.version.history.delete = Delete Versions +jsp.version.history.return = Return +jsp.version.history.popup.delete = Yes +jsp.version.history.popup.close = No + +jsp.version.notice.new_version_head = Notice +jsp.version.notice.new_version_help = This is not the latest version of this item. The latest version can be found at: +jsp.version.notice.workflow_version_head = Notice +jsp.version.notice.workflow_version_help = A more recent version of this item is in the Workflow. + +itemRequest.all = All files +itemRequest.response.subject.approve = Request copy of document +itemRequest.response.body.approve = Dear {0},\n\ +In response to your request I have the pleasure to send you in attachment a copy of the file(s) concerning the document: "{2}" ({1}), of which I am author (or co-author).\n\n\ +Best regards,\n\ +{3} <{4}> + +itemRequest.response.subject.reject = Request copy of document +itemRequest.response.body.reject = Dear {0},\n\ +In response to your request I regret to inform you that it''s not possible to send you a copy of the file(s) you have requested, concerning the document: "{2}" ({1}), of which I am author (or co-author).\n\n\ +Best regards,\n\ +{3} <{4}> +jsp.request.item.request-form.info2 = Request a document copy: {0} +jsp.request.item.request-form.problem = You must fill all the missing fields. +jsp.request.item.request-form.reqname = Requester name: +jsp.request.item.request-form.email = Requester e-mail: +jsp.request.item.request-form.coment = Message: +jsp.request.item.request-form.go = Send +jsp.request.item.request-form.cancel = Cancel +jsp.request.item.request-form.allfiles = Files: +jsp.request.item.request-form.yes = all files (of this document) in restricted access +jsp.request.item.request-form.no = the file(s) you requested +jsp.request.item.request-form.title = Request a document copy +jsp.request.item.request-information.info1 = Subject: Request a document copy +jsp.request.item.request-information.info2 = IF YOU ARE AN AUTHOR OF THE DOCUMENT, {0}, use one of the buttons below to answer the request for a copy made by the user, {1}. +jsp.request.item.request-information.note = This repository will propose an appropriate model reply, which you may edit. +jsp.request.item.request-information.yes = Send a copy +jsp.request.item.request-information.no = Don’t send a copy +jsp.request.item.request-information.title = Request a document copy +jsp.request.item.request-letter.accept.heading = Accept the request +jsp.request.item.request-letter.accept.info = This is the email that will be sent to the requester along with the file(s). +jsp.request.item.request-letter.reject.heading = Reject the request +jsp.request.item.request-letter.reject.info = This is the email that will be sent to the requester. +jsp.request.item.request-letter.subject = Subject: +jsp.request.item.request-letter.message = Message: +jsp.request.item.request-letter.title = Copy of the requested document +jsp.request.item.request-letter.next = Send +jsp.request.item.request-letter.back = Back +jsp.request.item.return-item = Return to the item +jsp.request.item.response-send.info1 = Your answer was sent successfully! +jsp.request.item.response-send.info2 = Your answer was sent successfully to the e-mail indicated by the requester.<br><br>Thank you. +jsp.request.item.response-send.title = Request a document copy +jsp.request.item.request-send.info1 = Your request was sent successfully! +jsp.request.item.request-send.info2 = Your request was sent successfully to the author(s).<br><br>Thank you. +jsp.request.item.request-send.title = Request a document copy +jsp.request.item.request-free-acess.title = Your answer was sent successfully! +jsp.request.item.request-free-acess.info1 = Your answer was sent successfully to the e-mail indicated by the requester. Thank you. +jsp.request.item.request-free-acess.info2 = You may use this occasion to reconsider the access restrictions on the document (to avoid having to respond to these requests), if there is no reason to keep it restricted. To do so, after inserting your name and e-mail (for authentication), click the button "Change to Open Access". +jsp.request.item.request-free-acess.close = Close. +jsp.request.item.request-free-acess.free = Change to Open Access +jsp.request.item.request-free-acess.name = Name: +jsp.request.item.request-free-acess.email = E-mail: +org.dspace.app.requestitem.RequestItemMetadataStrategy.unnamed = Corresponding Author +org.dspace.app.webui.jsptag.ItemTag.restrict = <span class="glyphicon glyphicon-lock"> </span> Request a copy diff --git a/dspace-api/src/test/java/org/dspace/AbstractUnitTest.java b/dspace-api/src/test/java/org/dspace/AbstractUnitTest.java index d53abfcad5955e2a17b251a1608791a144b2ab3a..cbb7f3b30198b576eef75f774b6f3f8352968e8c 100644 --- a/dspace-api/src/test/java/org/dspace/AbstractUnitTest.java +++ b/dspace-api/src/test/java/org/dspace/AbstractUnitTest.java @@ -33,6 +33,8 @@ import org.dspace.content.MetadataField; import org.dspace.content.NonUniqueMetadataException; import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; +import org.dspace.core.I18nUtil; +import org.dspace.discovery.MockIndexEventConsumer; import org.dspace.eperson.EPerson; import org.dspace.search.DSIndexer; import org.dspace.servicemanager.DSpaceKernelImpl; @@ -52,7 +54,7 @@ import org.xml.sax.SAXException; * * @author pvillega */ -@UsingMocksAndStubs({MockDatabaseManager.class, MockBrowseCreateDAOOracle.class}) +@UsingMocksAndStubs({MockDatabaseManager.class, MockBrowseCreateDAOOracle.class, MockIndexEventConsumer.class}) public class AbstractUnitTest { /** log4j category */ @@ -147,6 +149,7 @@ public class AbstractUnitTest eperson.setLastName("last"); eperson.setEmail("test@email.com"); eperson.setCanLogIn(true); + eperson.setLanguage(I18nUtil.getDefaultLocale().getLanguage()); } //Create search and browse indexes @@ -349,6 +352,7 @@ public class AbstractUnitTest if(context != null && context.isValid()) { context.abort(); + context = null; } } diff --git a/dspace-api/src/test/java/org/dspace/authenticate/IPMatcherTest.java b/dspace-api/src/test/java/org/dspace/authenticate/IPMatcherTest.java index df853a30a2ff31e459601b520b97afa68f17022e..512786d14cb5efd2d16c559203f237c46254e8b6 100644 --- a/dspace-api/src/test/java/org/dspace/authenticate/IPMatcherTest.java +++ b/dspace-api/src/test/java/org/dspace/authenticate/IPMatcherTest.java @@ -10,16 +10,20 @@ */ package org.dspace.authenticate; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - import org.dspace.AbstractUnitTest; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import java.util.ArrayList; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + /** * @author Mark Wood + * @author Ben Bosman + * @author Roeland Dillen */ public class IPMatcherTest extends AbstractUnitTest { @@ -27,6 +31,8 @@ public class IPMatcherTest extends AbstractUnitTest private static final String IP6_FULL_ADDRESS2 = "2001:18e8:3:171:218:8bff:fe2a:56a3"; private static final String IP6_MASKED_ADDRESS = "2001:18e8:3::/48"; + private final static int increment = 6; + private static IPMatcher ip6FullMatcher; private static IPMatcher ip6MaskedMatcher; @@ -116,7 +122,221 @@ public class IPMatcherTest extends AbstractUnitTest assertTrue("IPv6 masked match fails", ip6MaskedMatcher .match(IP6_FULL_ADDRESS2)); } - + + @Test + public void testIPv4MatchingSuccess() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("1.1.1.1"); + + assertTrue(ipMatcher.match("1.1.1.1")); + ArrayList<String> exceptions = new ArrayList<String>(); + exceptions.add("1.1.1.1"); + verifyAllIp4Except(exceptions, false, ipMatcher); + } + + @Test + public void testIPv4MatchingFailure() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("1.1.1.1"); + + assertFalse(ipMatcher.match("1.1.1.0")); + } + + @Test + public void testIPv6MatchingSuccess() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("::2"); + + assertTrue(ipMatcher.match("0:0:0:0:0:0:0:2")); + } + + @Test + public void testShortFormIPv6MatchingSuccess() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("::2"); + + assertTrue(ipMatcher.match("::2")); + } + + @Test + public void testIPv6MatchingFailure() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("::2"); + + assertFalse(ipMatcher.match("0:0:0:0:0:0:0:1")); + } + + + + @Test + public void testAsteriskMatchingSuccess() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("172.16"); + + assertTrue(ipMatcher.match("172.16.1.1")); + } + + @Test + public void testAsteriskMatchingFailure() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("172.16"); + + assertFalse(ipMatcher.match("172.15.255.255")); + } + + @Test + public void testIPv4CIDRMatchingSuccess() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("192.1.2.3/8"); + + assertTrue(ipMatcher.match("192.1.1.1")); + } + + @Test + public void testIPv4CIDRMatchingFailure() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("192.1.2.3/8"); + + assertTrue(ipMatcher.match("192.2.0.0")); + } + + @Test + public void test2IPv4CIDRMatchingSuccess() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("192.86.100.72/29"); + + assertTrue(ipMatcher.match("192.86.100.75")); + assertFalse(ipMatcher.match("192.86.100.71")); + assertFalse(ipMatcher.match("192.86.100.80")); + ArrayList<String> exceptions = new ArrayList<String>(); + exceptions.add("192.86.100.72"); + exceptions.add("192.86.100.73"); + exceptions.add("192.86.100.74"); + exceptions.add("192.86.100.75"); + exceptions.add("192.86.100.76"); + exceptions.add("192.86.100.77"); + exceptions.add("192.86.100.78"); + exceptions.add("192.86.100.79"); + verifyAllIp4Except(exceptions, false, ipMatcher); + } + + @Test + public void test3IPv4CIDRMatchingSuccess() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("192.86.100.72/255.255.255.248"); + + assertTrue(ipMatcher.match("192.86.100.75")); + assertFalse(ipMatcher.match("192.86.100.71")); + assertFalse(ipMatcher.match("192.86.100.80")); + ArrayList<String> exceptions = new ArrayList<String>(); + exceptions.add("192.86.100.72"); + exceptions.add("192.86.100.73"); + exceptions.add("192.86.100.74"); + exceptions.add("192.86.100.75"); + exceptions.add("192.86.100.76"); + exceptions.add("192.86.100.77"); + exceptions.add("192.86.100.78"); + exceptions.add("192.86.100.79"); + verifyAllIp4Except(exceptions, false, ipMatcher); + } + + @Test + public void testIPv6CIDRMatchingSuccess() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("0:0:0:1::/64"); + + assertTrue(ipMatcher.match("0:0:0:1:ffff:ffff:ffff:ffff")); + } + + @Test + public void testIPv6CIDRMatchingFailure() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("0:0:0:1::/64"); + + assertFalse(ipMatcher.match("0:0:0:2::")); + } + + + + @Test + public void testIPv4IPv6Matching() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("0.0.0.1"); + + assertTrue(ipMatcher.match("::1")); + } + + + + @Test + public void testSubnetZeroIPv6CIDRMatching() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("::1/0"); + + assertTrue(ipMatcher.match("::2")); + } + + @Test + public void testAllOnesSubnetIPv4CIDRMatchingSuccess() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("192.1.2.3/32"); + + assertTrue(ipMatcher.match("192.1.2.3")); + } + + @Test + public void testAllOnesSubnetIPv4CIDRMatchingFailure() throws Exception + { + final IPMatcher ipMatcher = new IPMatcher("192.1.2.3/32"); + + assertFalse(ipMatcher.match("192.1.2.2")); + } + + + + private ArrayList<String> getAllIp4Except(ArrayList<String> exceptions) { + int d1 = 0, d2 = 0, d3 = 0, d4 = 0; + ArrayList<String> ips = new ArrayList<String>(); + for (d1 = 0; d1 <= 255; d1+=increment) + for (d2 = 0; d2 <= 255; d2+=increment) + for (d3 = 0; d3 <= 255; d3+=increment) + for (d4 = 0; d4 <= 255; d4+=increment) { + String IP = d1+"."+d2+"."+d3+"."+d4; + if (exceptions == null || !exceptions.contains(IP)) { + ips.add(IP); + } + } + return ips; + } + + private void verifyAllIp4Except(ArrayList<String> exceptions, boolean asserted, IPMatcher ipMatcher) throws IPMatcherException { + int d1 = 0, d2 = 0, d3 = 0, d4 = 0; + for (d1 = 0; d1 <= 255; d1+=increment) + for (d2 = 0; d2 <= 255; d2+=increment) + for (d3 = 0; d3 <= 255; d3+=increment) + for (d4 = 0; d4 <= 255; d4+=increment) { + String IP = d1+"."+d2+"."+d3+"."+d4; + if (exceptions != null && exceptions.contains(IP)) { + if (asserted) { + assertFalse(ipMatcher.match(IP)); + } else { + assertTrue(ipMatcher.match(IP)); + } + } else { + if (asserted) { + assertTrue(ipMatcher.match(IP)); + } else { + assertFalse(ipMatcher.match(IP)); + } + } + + } + } + + + + + @AfterClass static public void cleanup() { diff --git a/dspace-api/src/test/java/org/dspace/content/BitstreamFormatTest.java b/dspace-api/src/test/java/org/dspace/content/BitstreamFormatTest.java index 6ab15fe9493f3f69a232d48fad14892d0bb2f544..6d015b56e9bfc545531c01102a4723a9fa45fb47 100644 --- a/dspace-api/src/test/java/org/dspace/content/BitstreamFormatTest.java +++ b/dspace-api/src/test/java/org/dspace/content/BitstreamFormatTest.java @@ -61,7 +61,7 @@ public class BitstreamFormatTest extends AbstractUnitTest catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/BitstreamTest.java b/dspace-api/src/test/java/org/dspace/content/BitstreamTest.java index 1a12ef8fcfbb0c34f5dff9868bcdf121dda3a1d1..df48d95c67ce42b7762327d84a857ddee06ead18 100644 --- a/dspace-api/src/test/java/org/dspace/content/BitstreamTest.java +++ b/dspace-api/src/test/java/org/dspace/content/BitstreamTest.java @@ -58,12 +58,12 @@ public class BitstreamTest extends AbstractDSpaceObjectTest } catch (IOException ex) { log.error("IO Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } @@ -128,6 +128,8 @@ public class BitstreamTest extends AbstractDSpaceObjectTest { File f = new File(testProps.get("test.bitstream").toString()); Bitstream created = Bitstream.create(context, new FileInputStream(f)); + context.commit(); + //the item created by default has no name nor type set assertThat("testCreate 0", created.getFormat().getMIMEType(), equalTo("application/octet-stream")); assertThat("testCreate 1", created.getName(), nullValue()); diff --git a/dspace-api/src/test/java/org/dspace/content/BundleTest.java b/dspace-api/src/test/java/org/dspace/content/BundleTest.java index bff9b15f9c8269e14d9348a19c0b884c69d60256..b6b91db4093f1460981bce5e014549de6c140018 100644 --- a/dspace-api/src/test/java/org/dspace/content/BundleTest.java +++ b/dspace-api/src/test/java/org/dspace/content/BundleTest.java @@ -66,7 +66,7 @@ public class BundleTest extends AbstractDSpaceObjectTest catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } @@ -215,7 +215,7 @@ public class BundleTest extends AbstractDSpaceObjectTest b.addBitstream(bs); assertThat("testGetHandle 1", b.getBitstreamByName(name), notNullValue()); assertThat("testGetHandle 2", b.getBitstreamByName(name), equalTo(bs)); - assertThat("testGetHandle 3", b.getBitstreamByName(name).getName(), equalTo(name)); + assertThat("testGetHandle 3", b.getBitstreamByName(name).getName(), equalTo(name)); context.commit(); } diff --git a/dspace-api/src/test/java/org/dspace/content/CollectionTest.java b/dspace-api/src/test/java/org/dspace/content/CollectionTest.java index f33647b9187ddacc9834307532bb8b9bb6cf28d2..5a2549c4ae783fd4f8cd6a9fbd53617f8af31396 100644 --- a/dspace-api/src/test/java/org/dspace/content/CollectionTest.java +++ b/dspace-api/src/test/java/org/dspace/content/CollectionTest.java @@ -20,8 +20,8 @@ import static org.hamcrest.CoreMatchers.*; import mockit.*; import org.dspace.app.util.AuthorizeUtil; import org.dspace.authorize.AuthorizeManager; -import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; +import org.dspace.core.LicenseManager; /** * Unit Tests for class Collection @@ -63,12 +63,12 @@ public class CollectionTest extends AbstractDSpaceObjectTest catch (AuthorizeException ex) { log.error("Authorization Error in init", ex); - fail("Authorization Error in init"); + fail("Authorization Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } @@ -198,7 +198,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest */ @Test @Override - public void testGetID() + public void testGetID() { assertTrue("testGetID 0", c.getID() >= 1); } @@ -208,7 +208,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest */ @Test @Override - public void testGetHandle() + public void testGetHandle() { //default instance has a random handle assertTrue("testGetHandle 0", c.getHandle().contains("123456789/")); @@ -471,6 +471,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest context.turnOffAuthorisationSystem(); int step = 1; Group g = Group.create(context); + context.commit(); context.restoreAuthSystemState(); c.setWorkflowGroup(step, g); assertThat("testSetWorkflowGroup 0",c.getWorkflowGroup(step), notNullValue()); @@ -662,17 +663,17 @@ public class CollectionTest extends AbstractDSpaceObjectTest * Test of getLicense method, of class Collection. */ @Test - public void testGetLicense() + public void testGetLicense() { assertThat("testGetLicense 0", c.getLicense(), notNullValue()); - assertThat("testGetLicense 1", c.getLicense(), equalTo(ConfigurationManager.getDefaultSubmissionLicense())); + assertThat("testGetLicense 1", c.getLicense(), equalTo(LicenseManager.getDefaultSubmissionLicense())); } /** * Test of getLicenseCollection method, of class Collection. */ @Test - public void testGetLicenseCollection() + public void testGetLicenseCollection() { assertThat("testGetLicenseCollection 0", c.getLicenseCollection(), notNullValue()); assertThat("testGetLicenseCollection 1", c.getLicenseCollection(), equalTo("")); @@ -682,7 +683,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest * Test of hasCustomLicense method, of class Collection. */ @Test - public void testHasCustomLicense() + public void testHasCustomLicense() { assertFalse("testHasCustomLicense 0", c.hasCustomLicense()); } @@ -691,7 +692,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest * Test of setLicense method, of class Collection. */ @Test - public void testSetLicense() + public void testSetLicense() { String license = "license for test"; c.setLicense(license); @@ -705,7 +706,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest * Test of getTemplateItem method, of class Collection. */ @Test - public void testGetTemplateItem() throws Exception + public void testGetTemplateItem() throws Exception { assertThat("testGetTemplateItem 0", c.getTemplateItem(), nullValue()); } @@ -1336,7 +1337,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest assertFalse("testCanEditBooleanNoAuth_boolean 0",c.canEditBoolean(false)); } - + /** * Test of canEditBoolean method, of class Collection. */ @@ -1789,7 +1790,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest */ @Test @Override - public void testGetType() + public void testGetType() { assertThat("testGetType 0", c.getType(), equalTo(Constants.COLLECTION)); } @@ -1798,7 +1799,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest * Test of findAuthorized method, of class Collection. */ @Test - public void testFindAuthorized() throws Exception + public void testFindAuthorized() throws Exception { context.turnOffAuthorisationSystem(); Community com = Community.create(null, context); @@ -1868,6 +1869,7 @@ public class CollectionTest extends AbstractDSpaceObjectTest context.turnOffAuthorisationSystem(); Community parent = Community.create(null, context); parent.addCollection(c); + context.commit(); context.restoreAuthSystemState(); assertThat("testGetParentObject 1", c.getParentObject(), notNullValue()); assertThat("testGetParentObject 2", (Community)c.getParentObject(), equalTo(parent)); diff --git a/dspace-api/src/test/java/org/dspace/content/CommunityTest.java b/dspace-api/src/test/java/org/dspace/content/CommunityTest.java index 9ec00adbfd6d73e307c17743ec479ee899d08c6a..46ebfd0b65d1e8e0dc6e55ae64db08fc2ba64aa3 100644 --- a/dspace-api/src/test/java/org/dspace/content/CommunityTest.java +++ b/dspace-api/src/test/java/org/dspace/content/CommunityTest.java @@ -63,12 +63,12 @@ public class CommunityTest extends AbstractDSpaceObjectTest catch (AuthorizeException ex) { log.error("Authorization Error in init", ex); - fail("Authorization Error in init"); + fail("Authorization Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } @@ -766,6 +766,37 @@ public class CommunityTest extends AbstractDSpaceObjectTest assertThat("testGetAllParents 4", son.getAllParents()[0], equalTo(c)); } + /** + * Test of getAllCollections method, of class Community. + */ + @Test + public void testGetAllCollections() throws Exception + { + new NonStrictExpectations() + { + AuthorizeManager authManager; + { + AuthorizeManager.authorizeAction((Context) any, (Community) any, + Constants.ADD); result = null; + AuthorizeManager.authorizeActionBoolean((Context) any, (Community) any, + Constants.ADD); result = true; + } + }; + + //empty by default + assertThat("testGetAllCollections 0",c.getAllCollections(), notNullValue()); + assertTrue("testGetAllCollections 1", c.getAllCollections().length == 0); + + //community has a collection and a subcommunity, subcommunity has a collection + Collection collOfC = c.createCollection(); + Community sub = Community.create(c, context); + Collection collOfSub = sub.createCollection(); + assertThat("testGetAllCollections 2",c.getAllCollections(), notNullValue()); + assertTrue("testGetAllCollections 3", c.getAllCollections().length == 2); + assertThat("testGetAllCollections 4", c.getAllCollections()[0], equalTo(collOfSub)); + assertThat("testGetAllCollections 5", c.getAllCollections()[1], equalTo(collOfC)); + } + /** * Test of createCollection method, of class Community. */ diff --git a/dspace-api/src/test/java/org/dspace/content/InstallItemTest.java b/dspace-api/src/test/java/org/dspace/content/InstallItemTest.java index ddd9631532de6cd57dcf3c19ce7041cc0edda413..305390b57cd6ed2ad70c38244186babfddc1aede 100644 --- a/dspace-api/src/test/java/org/dspace/content/InstallItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/InstallItemTest.java @@ -87,7 +87,7 @@ public class InstallItemTest extends AbstractUnitTest String handle = "1345/567"; Collection col = Collection.create(context); WorkspaceItem is = WorkspaceItem.create(context, col, false); - + //Test assigning a specified handle to an item // (this handle should not already be used by system, as it doesn't start with "1234567689" prefix) Item result = InstallItem.installItem(context, is, handle); @@ -198,4 +198,87 @@ public class InstallItemTest extends AbstractUnitTest assertThat("testGetBitstreamProvenanceMessage 0", InstallItem.getBitstreamProvenanceMessage(item), equalTo(testMessage)); } + /** + * Test passing in "today" as an issued date to InstallItem. + */ + @Test + public void testInstallItem_todayAsIssuedDate() throws Exception + { + //create a dummy WorkspaceItem + context.turnOffAuthorisationSystem(); + String handle = "1345/567"; + Collection col = Collection.create(context); + WorkspaceItem is = WorkspaceItem.create(context, col, false); + + // Set "today" as "dc.date.issued" + is.getItem().addMetadata("dc", "date", "issued", Item.ANY, "today"); + is.getItem().addMetadata("dc", "date", "issued", Item.ANY, "2011-01-01"); + + //get current date + DCDate now = DCDate.getCurrent(); + String dayAndTime = now.toString(); + //parse out just the date, remove the time (format: yyyy-mm-ddT00:00:00Z) + String date = dayAndTime.substring(0, dayAndTime.indexOf("T")); + + Item result = InstallItem.installItem(context, is, handle); + context.restoreAuthSystemState(); + + //Make sure the string "today" was replaced with today's date + DCValue[] issuedDates = result.getMetadata("dc", "date", "issued", Item.ANY); + + assertThat("testInstallItem_todayAsIssuedDate 0", issuedDates[0].value, equalTo(date)); + assertThat("testInstallItem_todayAsIssuedDate 1", issuedDates[1].value, equalTo("2011-01-01")); + } + + /** + * Test null issue date (when none set) in InstallItem + */ + @Test + public void testInstallItem_nullIssuedDate() throws Exception + { + //create a dummy WorkspaceItem with no dc.date.issued + context.turnOffAuthorisationSystem(); + String handle = "1345/567"; + Collection col = Collection.create(context); + WorkspaceItem is = WorkspaceItem.create(context, col, false); + + Item result = InstallItem.installItem(context, is, handle); + context.restoreAuthSystemState(); + + //Make sure dc.date.issued is NOT set + DCValue[] issuedDates = result.getMetadata("dc", "date", "issued", Item.ANY); + assertThat("testInstallItem_nullIssuedDate 0", issuedDates.length, equalTo(0)); + } + + /** + * Test passing in "today" as an issued date to restoreItem. + */ + @Test + public void testRestoreItem_todayAsIssuedDate() throws Exception + { + //create a dummy WorkspaceItem + context.turnOffAuthorisationSystem(); + String handle = "1345/567"; + Collection col = Collection.create(context); + WorkspaceItem is = WorkspaceItem.create(context, col, false); + + // Set "today" as "dc.date.issued" + is.getItem().addMetadata("dc", "date", "issued", Item.ANY, "today"); + is.getItem().addMetadata("dc", "date", "issued", Item.ANY, "2011-01-01"); + + //get current date + DCDate now = DCDate.getCurrent(); + String dayAndTime = now.toString(); + //parse out just the date, remove the time (format: yyyy-mm-ddT00:00:00Z) + String date = dayAndTime.substring(0, dayAndTime.indexOf("T")); + + Item result = InstallItem.restoreItem(context, is, handle); + context.restoreAuthSystemState(); + + //Make sure the string "today" was replaced with today's date + DCValue[] issuedDates = result.getMetadata("dc", "date", "issued", Item.ANY); + + assertThat("testRestoreItem_todayAsIssuedDate 0", issuedDates[0].value, equalTo(date)); + assertThat("testRestoreItem_todayAsIssuedDate 1", issuedDates[1].value, equalTo("2011-01-01")); + } } \ No newline at end of file diff --git a/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java b/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java index 06f5a047d7bc1ebfcdd4faed87953598272e40cc..b01337ca19bb0ad43554b77ef47fb2dd5d1b41ed 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemComparatorTest.java @@ -59,12 +59,12 @@ public class ItemComparatorTest extends AbstractUnitTest catch (AuthorizeException ex) { log.error("Authorization Error in init", ex); - fail("Authorization Error in init"); + fail("Authorization Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init:" + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/ItemIteratorTest.java b/dspace-api/src/test/java/org/dspace/content/ItemIteratorTest.java index 321f79429ca12cc0b2a90e3e158f727fae6fe027..9da988a8da172ef3abacdd6b0b7012318de9323b 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemIteratorTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemIteratorTest.java @@ -83,12 +83,12 @@ public class ItemIteratorTest extends AbstractUnitTest catch (AuthorizeException ex) { log.error("Authorization Error in init", ex); - fail("Authorization Error in init"); + fail("Authorization Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/ItemTest.java b/dspace-api/src/test/java/org/dspace/content/ItemTest.java index 479f5c3e8b9b4bec3e3a133a1b06af7d376035ee..100c6510e7756bf0ab558deb50efd2927feea7b2 100644 --- a/dspace-api/src/test/java/org/dspace/content/ItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ItemTest.java @@ -76,12 +76,12 @@ public class ItemTest extends AbstractDSpaceObjectTest catch (AuthorizeException ex) { log.error("Authorization Error in init", ex); - fail("Authorization Error in init"); + fail("Authorization Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/LicenseUtilsTest.java b/dspace-api/src/test/java/org/dspace/content/LicenseUtilsTest.java index f85bb1c997a7a15b8123dfc8e6f6360977526a84..1b00cced4ad1738d71f9068566bd7b2f95a9a7c7 100644 --- a/dspace-api/src/test/java/org/dspace/content/LicenseUtilsTest.java +++ b/dspace-api/src/test/java/org/dspace/content/LicenseUtilsTest.java @@ -13,13 +13,13 @@ import java.sql.SQLException; import java.util.HashMap; import org.dspace.authorize.AuthorizeException; import org.dspace.eperson.EPerson; -import org.dspace.core.ConfigurationManager; import org.dspace.AbstractUnitTest; import java.util.LinkedHashMap; import java.util.Locale; import java.util.Map; import org.apache.log4j.Logger; +import org.dspace.core.LicenseManager; import org.junit.*; import static org.junit.Assert.* ; import static org.hamcrest.CoreMatchers.*; @@ -81,7 +81,7 @@ public class LicenseUtilsTest extends AbstractUnitTest String templateLong = "Template license: %1$s %2$s %3$s %5$s %6$s %8$s %9$s %10$s %11$s"; String templateResult = "Template license: first name last name test@email.com "; String templateLongResult = "Template license: first name last name test@email.com arg1 arg2 arg3 arg4"; - String defaultLicense = ConfigurationManager.getDefaultSubmissionLicense(); + String defaultLicense = LicenseManager.getDefaultSubmissionLicense(); context.turnOffAuthorisationSystem(); //TODO: the tested method doesn't verify the input, will throw NPE if any parameter is null @@ -154,10 +154,10 @@ public class LicenseUtilsTest extends AbstractUnitTest additionalInfo = new LinkedHashMap<String, Object>(); additionalInfo.put("arg1", "arg1"); additionalInfo.put("arg2", "arg2"); - additionalInfo.put("arg3", "arg3"); + additionalInfo.put("arg3", "arg3"); additionalInfo.put("arg4", "arg4"); assertThat("testGetLicenseText_5args 5", LicenseUtils.getLicenseText(locale, collection, item, person, additionalInfo), equalTo(templateLongResult)); - + context.restoreAuthSystemState(); } @@ -175,7 +175,7 @@ public class LicenseUtilsTest extends AbstractUnitTest String template = "Template license: %1$s %2$s %3$s %5$s %6$s"; String templateResult = "Template license: first name last name test@email.com "; - String defaultLicense = ConfigurationManager.getDefaultSubmissionLicense(); + String defaultLicense = LicenseManager.getDefaultSubmissionLicense(); context.turnOffAuthorisationSystem(); //TODO: the tested method doesn't verify the input, will throw NPE if any parameter is null @@ -207,7 +207,7 @@ public class LicenseUtilsTest extends AbstractUnitTest person = EPerson.create(context); person.setFirstName("first name"); person.setLastName("last name"); - person.setEmail("test@email.com"); + person.setEmail("test@email.com"); assertThat("testGetLicenseText_5args 3", LicenseUtils.getLicenseText(locale, collection, item, person), equalTo(templateResult)); locale = Locale.GERMAN; @@ -227,11 +227,11 @@ public class LicenseUtilsTest extends AbstractUnitTest * Test of grantLicense method, of class LicenseUtils. */ @Test - public void testGrantLicense() throws Exception + public void testGrantLicense() throws Exception { context.turnOffAuthorisationSystem(); Item item = Item.create(context); - String defaultLicense = ConfigurationManager.getDefaultSubmissionLicense(); + String defaultLicense = LicenseManager.getDefaultSubmissionLicense(); LicenseUtils.grantLicense(context, item, defaultLicense); diff --git a/dspace-api/src/test/java/org/dspace/content/MetadataFieldTest.java b/dspace-api/src/test/java/org/dspace/content/MetadataFieldTest.java index c16a96ce3faf8a8785577159b9ffbd7fec7d8a75..99490e863d8df4056709819f5a5550386c052db2 100644 --- a/dspace-api/src/test/java/org/dspace/content/MetadataFieldTest.java +++ b/dspace-api/src/test/java/org/dspace/content/MetadataFieldTest.java @@ -70,12 +70,12 @@ public class MetadataFieldTest extends AbstractUnitTest catch (AuthorizeException ex) { log.error("Authorize Error in init", ex); - fail("Authorize Error in init"); + fail("Authorize Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/MetadataSchemaTest.java b/dspace-api/src/test/java/org/dspace/content/MetadataSchemaTest.java index 4b8d4caaddc925360c83f89fa8bc17e25cdc8405..5f9a82b409a6bc06c46260ddc817c68e872bc9fd 100644 --- a/dspace-api/src/test/java/org/dspace/content/MetadataSchemaTest.java +++ b/dspace-api/src/test/java/org/dspace/content/MetadataSchemaTest.java @@ -51,7 +51,7 @@ public class MetadataSchemaTest extends AbstractUnitTest catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/MetadataValueTest.java b/dspace-api/src/test/java/org/dspace/content/MetadataValueTest.java index f8800371302580d7787175a34c354ef1a12aa36d..6c3e7aad0259d17a047a62818c1cfdd6f09fa1cd 100644 --- a/dspace-api/src/test/java/org/dspace/content/MetadataValueTest.java +++ b/dspace-api/src/test/java/org/dspace/content/MetadataValueTest.java @@ -73,12 +73,12 @@ public class MetadataValueTest extends AbstractUnitTest catch (AuthorizeException ex) { log.error("Authorize Error in init", ex); - fail("Authorize Error in init"); + fail("Authorize Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/SiteTest.java b/dspace-api/src/test/java/org/dspace/content/SiteTest.java index 5d83f7d57cd610ed3e99126b5ab6d40af4c83009..4bcfa8b45df35c1e10465207ffa9a2cbe696ec95 100644 --- a/dspace-api/src/test/java/org/dspace/content/SiteTest.java +++ b/dspace-api/src/test/java/org/dspace/content/SiteTest.java @@ -56,7 +56,7 @@ public class SiteTest extends AbstractUnitTest catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/SupervisedItemTest.java b/dspace-api/src/test/java/org/dspace/content/SupervisedItemTest.java index 7e6b40cc09c69b8b5762c00e07ec3e39e1127f3e..b4a2ae812d18dc95f0f82e52a61828f939695bae 100644 --- a/dspace-api/src/test/java/org/dspace/content/SupervisedItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/SupervisedItemTest.java @@ -84,12 +84,12 @@ public class SupervisedItemTest extends AbstractUnitTest } catch (IOException ex) { log.error("IO Error in init", ex); - fail("IO Error in init"); + fail("IO Error in init: " + ex.getMessage()); } catch (AuthorizeException ex) { log.error("Authorization Error in init", ex); - fail("Authorization Error in init"); + fail("Authorization Error in init: " + ex.getMessage()); } catch (SQLException ex) { diff --git a/dspace-api/src/test/java/org/dspace/content/ThumbnailTest.java b/dspace-api/src/test/java/org/dspace/content/ThumbnailTest.java index ca3f7d6eda15a95ea24e2a5b0e1fa3cbab884ac5..1bab5558114c78cff7dabf1f4a79c5965e41e2f9 100644 --- a/dspace-api/src/test/java/org/dspace/content/ThumbnailTest.java +++ b/dspace-api/src/test/java/org/dspace/content/ThumbnailTest.java @@ -66,12 +66,12 @@ public class ThumbnailTest extends AbstractUnitTest } catch (IOException ex) { log.error("IO Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/VersioningTest.java b/dspace-api/src/test/java/org/dspace/content/VersioningTest.java index 45c4cd1bb61297c7b2ffdfe9b595b313bf4a6a15..7b1f2ba9d830b4b802515e483600c5e409ab7e1a 100644 --- a/dspace-api/src/test/java/org/dspace/content/VersioningTest.java +++ b/dspace-api/src/test/java/org/dspace/content/VersioningTest.java @@ -75,15 +75,15 @@ public class VersioningTest extends AbstractUnitTest { catch (AuthorizeException ex) { log.error("Authorization Error in init", ex); - fail("Authorization Error in init"); + fail("Authorization Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } catch (IOException ex) { log.error("IO Error in init", ex); - fail("IO Error in init"); + fail("IO Error in init: " + ex.getMessage()); } } diff --git a/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java b/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java index 7e45fe936b630fe5d9d018bae21ca5a06edc6695..d46f267f550f102d5b2f3f0b6c01333cd89cbd67 100644 --- a/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java +++ b/dspace-api/src/test/java/org/dspace/content/WorkspaceItemTest.java @@ -55,22 +55,22 @@ public class WorkspaceItemTest extends AbstractUnitTest Collection col = Collection.create(context); this.wi = WorkspaceItem.create(context, col, true); //we need to commit the changes so we don't block the table for testing - context.restoreAuthSystemState(); context.commit(); + context.restoreAuthSystemState(); } catch (IOException ex) { log.error("IO Error in init", ex); - fail("IO Error in init"); + fail("IO Error in init: " + ex.getMessage()); } catch (AuthorizeException ex) { log.error("Authorization Error in init", ex); - fail("Authorization Error in init"); + fail("Authorization Error in init: " + ex.getMessage()); } catch (SQLException ex) { log.error("SQL Error in init", ex); - fail("SQL Error in init"); + fail("SQL Error in init: " + ex.getMessage()); } } @@ -125,6 +125,7 @@ public class WorkspaceItemTest extends AbstractUnitTest coll = Collection.create(context); template = false; created = WorkspaceItem.create(context, coll, template); + context.commit(); assertThat("testCreate 0",created,notNullValue()); assertTrue("testCreate 1",created.getID() >= 0); assertThat("testCreate 2",created.getCollection(),equalTo(coll)); @@ -132,6 +133,7 @@ public class WorkspaceItemTest extends AbstractUnitTest coll = Collection.create(context); template = true; created = WorkspaceItem.create(context, coll, template); + context.commit(); assertThat("testCreate 3",created,notNullValue()); assertTrue("testCreate 4",created.getID() >= 0); assertThat("testCreate 5",created.getCollection(),equalTo(coll)); @@ -157,6 +159,7 @@ public class WorkspaceItemTest extends AbstractUnitTest WorkspaceItem created = null; coll = Collection.create(context); + context.commit(); template = false; created = WorkspaceItem.create(context, coll, template); fail("Exception expected"); diff --git a/dspace-api/src/test/java/org/dspace/storage/rdbms/MockDatabaseManager.java b/dspace-api/src/test/java/org/dspace/storage/rdbms/MockDatabaseManager.java index d43016f6525dad1de535373c32e30c3882cf99fb..f88019fae635ee2765ec9503f58e99a0b7d8739e 100644 --- a/dspace-api/src/test/java/org/dspace/storage/rdbms/MockDatabaseManager.java +++ b/dspace-api/src/test/java/org/dspace/storage/rdbms/MockDatabaseManager.java @@ -1695,7 +1695,7 @@ public class MockDatabaseManager //exist in the file String[] stmts = sb.toString().split(";"); - //stablish the connection using the pool + //establish the connection using the pool Connection con = DriverManager.getConnection("jdbc:apache:commons:dbcp:" + poolName); Statement st = con.createStatement(); diff --git a/dspace-jspui/pom.xml b/dspace-jspui/pom.xml index 50960097f40cab979dbb3e65d270c9e4173bf23f..6b73631b7be6a46bfabe6e27d280a2b8397d44ac 100644 --- a/dspace-jspui/pom.xml +++ b/dspace-jspui/pom.xml @@ -13,7 +13,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> @@ -64,6 +64,7 @@ <exclude>**/readme*</exclude> <exclude>**/scriptaculous/**</exclude> <exclude>**/jquery*</exclude> + <exclude>**/bootstrap/**</exclude> </excludes> </configuration> </plugin> @@ -128,9 +129,8 @@ <type>jar</type> </dependency> <dependency> - <groupId>net.sf.flexjson</groupId> - <artifactId>flexjson</artifactId> - <version>2.1</version> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> </dependency> </dependencies> diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSubmissionsManager.java b/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSubmissionsManager.java index 2802e12ebe2f3210bfe32c24b561ba41b157e535..e61031e4e745a732f72a73f3de0f24e62d2a6dc2 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSubmissionsManager.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/components/RecentSubmissionsManager.java @@ -52,7 +52,7 @@ public class RecentSubmissionsManager * If the object you pass in is not a Community or Collection (e.g. an Item * is a DSpaceObject which cannot be used here), an exception will be thrown * - * @param dso DSpaceObject: Community or Collection + * @param dso DSpaceObject: Community, Collection or null for SITE * @return The recently submitted items * @throws RecentSubmissionsException */ @@ -74,7 +74,10 @@ public class RecentSubmissionsManager bs.setBrowseIndex(bi); bs.setOrder(SortOption.DESCENDING); bs.setResultsPerPage(Integer.parseInt(count)); - bs.setBrowseContainer(dso); + if (dso != null) + { + bs.setBrowseContainer(dso); + } for (SortOption so : SortOption.getSortOptions()) { if (so.getName().equals(source)) diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/configuration/JSPUISpringLoader.java b/dspace-jspui/src/main/java/org/dspace/app/webui/configuration/JSPUISpringLoader.java index d34580a657040d014090a22add4a0ac94d0ab99d..fc0bbcb0db76160388274ba40e470d512dd092f5 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/configuration/JSPUISpringLoader.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/configuration/JSPUISpringLoader.java @@ -14,9 +14,7 @@ import java.io.File; import java.net.MalformedURLException; /** - * User: kevin (kevin at atmire.com) - * Date: 3-aug-2011 - * Time: 11:45:41 + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class JSPUISpringLoader implements SpringLoader{ diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverUtility.java b/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverUtility.java index cbf7970740a02fcca29f4d6d92dd8c6af1ff2a1e..e598ac05030ce1b919c621b0e6bc27fa1d75ae1b 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverUtility.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverUtility.java @@ -541,7 +541,7 @@ public class DiscoverUtility // Create facet queries but limit then to 11 // (11 // == when we need to show a show more url) - for (int year = topYear - gap; year > oldestYear + for (int year = topYear; year > oldestYear && (facetQueries.size() < 11); year -= gap) { // Add a filter to remove the last year diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoveryJSONRequest.java b/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoveryJSONRequest.java index a1c69fa554fb87cd5a1f0da499905d618681b920..6bf937a5515841dc9c1aef1e63bc21b5c8175d65 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoveryJSONRequest.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoveryJSONRequest.java @@ -24,7 +24,12 @@ import org.dspace.discovery.DiscoverResult; import org.dspace.discovery.DiscoverResult.FacetResult; import org.dspace.discovery.SearchUtils; -import flexjson.JSONSerializer; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; public class DiscoveryJSONRequest extends JSONRequest { @@ -69,10 +74,25 @@ public class DiscoveryJSONRequest extends JSONRequest fResults = qResults .getFacetResult(autocompleteField); } - JSONSerializer serializer = new JSONSerializer(); - serializer.rootName("autocomplete"); - serializer.exclude("class","asFilterQuery"); - serializer.deepSerialize(fResults, resp.getWriter()); + Gson gson = new GsonBuilder().addSerializationExclusionStrategy(new ExclusionStrategy() { + + @Override + public boolean shouldSkipField(FieldAttributes f) { + + if(f.getName().equals("asFilterQuery"))return true; + return false; + } + + @Override + public boolean shouldSkipClass(Class<?> clazz) { + return false; + } + }).create(); + + JsonElement tree = gson.toJsonTree(fResults); + JsonObject jo = new JsonObject(); + jo.add("autocomplete", tree); + resp.getWriter().write(jo.toString()); } catch (Exception e) { diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverySearchRequestProcessor.java b/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverySearchRequestProcessor.java index e7a8c4deb24fed5fbed8f800e485370aaa4a2b6d..409b8dc9f25bb746eb7d937ebfceae16ddad6537 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverySearchRequestProcessor.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/discovery/DiscoverySearchRequestProcessor.java @@ -25,6 +25,7 @@ import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.dspace.app.bulkedit.DSpaceCSV; import org.dspace.app.bulkedit.MetadataExport; @@ -41,6 +42,7 @@ import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.ItemIterator; import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.I18nUtil; import org.dspace.core.LogManager; @@ -56,6 +58,8 @@ import org.w3c.dom.Document; public class DiscoverySearchRequestProcessor implements SearchRequestProcessor { + private static final int ITEMMAP_RESULT_PAGE_SIZE = 50; + private static String msgKey = "org.dspace.app.webui.servlet.FeedServlet"; /** log4j category */ @@ -64,12 +68,26 @@ public class DiscoverySearchRequestProcessor implements SearchRequestProcessor // locale-sensitive metadata labels private Map<String, Map<String, String>> localeLabels = null; + private List<String> searchIndices = null; + public synchronized void init() { if (localeLabels == null) { localeLabels = new HashMap<String, Map<String, String>>(); } + + if (searchIndices == null) + { + searchIndices = new ArrayList<String>(); + DiscoveryConfiguration discoveryConfiguration = SearchUtils + .getDiscoveryConfiguration(); + searchIndices.add("any"); + for (DiscoverySearchFilter sFilter : discoveryConfiguration.getSearchFilters()) + { + searchIndices.add(sFilter.getIndexFieldName()); + } + } } public void doOpenSearch(Context context, HttpServletRequest request, @@ -233,6 +251,8 @@ public class DiscoverySearchRequestProcessor implements SearchRequestProcessor DiscoverQuery queryArgs = DiscoverUtility.getDiscoverQuery(context, request, scope, true); + queryArgs.setSpellCheck(discoveryConfiguration.isSpellCheckEnabled()); + List<DiscoverySearchFilterFacet> availableFacet = discoveryConfiguration .getSidebarFacets(); @@ -321,6 +341,7 @@ public class DiscoverySearchRequestProcessor implements SearchRequestProcessor { qResults = SearchUtils.getSearchService().search(context, scope, queryArgs); + List<Community> resultsListComm = new ArrayList<Community>(); List<Collection> resultsListColl = new ArrayList<Collection>(); List<Item> resultsListItem = new ArrayList<Item>(); @@ -383,7 +404,8 @@ public class DiscoverySearchRequestProcessor implements SearchRequestProcessor request.setAttribute("pagecurrent", new Long(pageCurrent)); request.setAttribute("pagelast", new Long(pageLast)); request.setAttribute("pagefirst", new Long(pageFirst)); - + request.setAttribute("spellcheck", qResults.getSpellCheckQuery()); + request.setAttribute("queryresults", qResults); try @@ -480,4 +502,72 @@ public class DiscoverySearchRequestProcessor implements SearchRequestProcessor response.sendRedirect(request.getContextPath() + "/simple-search"); } + /** + * Method for searching authors in item map + * + * author: gam + */ + @Override + public void doItemMapSearch(Context context, HttpServletRequest request, + HttpServletResponse response) throws SearchProcessorException, ServletException, IOException + { + String queryString = (String) request.getParameter("query"); + Collection collection = (Collection) request.getAttribute("collection"); + int page = UIUtil.getIntParameter(request, "page")-1; + int offset = page > 0? page * ITEMMAP_RESULT_PAGE_SIZE:0; + String idx = (String) request.getParameter("index"); + if (StringUtils.isNotBlank(idx) && !idx.equalsIgnoreCase("any")) + { + queryString = idx + ":(" + queryString + ")"; + } + DiscoverQuery query = new DiscoverQuery(); + query.setQuery(queryString); + query.addFilterQueries("-location:l"+collection.getID()); + query.setMaxResults(ITEMMAP_RESULT_PAGE_SIZE); + query.setStart(offset); + + DiscoverResult results = null; + try + { + results = SearchUtils.getSearchService().search(context, query); + } + catch (SearchServiceException e) + { + throw new SearchProcessorException(e.getMessage(), e); + } + + Map<Integer, Item> items = new HashMap<Integer, Item>(); + + List<DSpaceObject> resultDSOs = results.getDspaceObjects(); + for (DSpaceObject dso : resultDSOs) + { + if (dso != null && dso.getType() == Constants.ITEM) + { + // no authorization check is required as discovery is right aware + Item item = (Item) dso; + items.put(Integer.valueOf(item.getID()), item); + } + } + + request.setAttribute("browsetext", queryString); + request.setAttribute("items", items); + request.setAttribute("more", results.getTotalSearchResults() > offset + ITEMMAP_RESULT_PAGE_SIZE); + request.setAttribute("browsetype", "Add"); + request.setAttribute("page", page > 0 ? page + 1 : 1); + + JSPManager.showJSP(request, response, "itemmap-browse.jsp"); + } + + @Override + public String getI18NKeyPrefix() + { + return "jsp.search.filter."; + } + + @Override + public List<String> getSearchIndices() + { + init(); + return searchIndices; + } } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/BrowseListTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/BrowseListTag.java index de3bcc9d519d75776eabf29bb1a479c240686711..3de8495938d3675aac94884caf5d74a9efce3f7b 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/BrowseListTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/BrowseListTag.java @@ -300,12 +300,12 @@ public class BrowseListTag extends TagSupport // If the table width has been specified, we can make this a fixed layout if (!StringUtils.isEmpty(tablewidth)) { - out.println("<table style=\"width: " + tablewidth + "; table-layout: fixed;\" align=\"center\" class=\"miscTable\" summary=\"This table browses all dspace content\">"); + out.println("<table style=\"width: " + tablewidth + "; table-layout: fixed;\" align=\"center\" class=\"table\" summary=\"This table browses all dspace content\">"); } else { // Otherwise, don't constrain the width - out.println("<table align=\"center\" class=\"miscTable\" summary=\"This table browses all dspace content\">"); + out.println("<table align=\"center\" class=\"table\" summary=\"This table browses all dspace content\">"); } // Output the known column widths @@ -332,11 +332,11 @@ public class BrowseListTag extends TagSupport } else if (!StringUtils.isEmpty(tablewidth)) { - out.println("<table width=\"" + tablewidth + "\" align=\"center\" class=\"miscTable\" summary=\"This table browses all dspace content\">"); + out.println("<table width=\"" + tablewidth + "\" align=\"center\" class=\"table\" summary=\"This table browses all dspace content\">"); } else { - out.println("<table align=\"center\" class=\"miscTable\" summary=\"This table browses all dspace content\">"); + out.println("<table align=\"center\" class=\"table\" summary=\"This table browses all dspace content\">"); } // Output the table headers @@ -482,7 +482,7 @@ public class BrowseListTag extends TagSupport DCDate dd = new DCDate(metadataArray[0].value); metadata = UIUtil.displayDate(dd, false, false, hrq); } - // format the title field correctly for withdrawn items (ie. don't link) + // format the title field correctly for withdrawn and private items (ie. don't link) else if (field.equals(titleField) && items[i].isWithdrawn()) { metadata = Utils.addEntities(metadataArray[0].value); @@ -570,7 +570,24 @@ public class BrowseListTag extends TagSupport metadata = "<em>" + sb.toString() + "</em>"; } } - + //In case title has no value, replace it with "undefined" so as the user has something to + //click in order to access the item page + else if (field.equals(titleField)){ + String undefined = LocaleSupport.getLocalizedMessage(pageContext, "itemlist.title.undefined"); + if (items[i].isWithdrawn()) + { + metadata = "<span style=\"font-style:italic\">("+undefined+")</span>"; + } + // format the title field correctly (as long as the item isn't withdrawn, link to it) + else + { + metadata = "<a href=\"" + hrq.getContextPath() + "/handle/" + + items[i].getHandle() + "\">" + + "<span style=\"font-style:italic\">("+undefined+")</span>" + + "</a>"; + } + } + // prepare extra special layout requirements for dates String extras = ""; if (isDate[colIdx]) diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/CollectionListTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/CollectionListTag.java index 3cdfc4c0aa6b06052f0393331fd54c902374732b..04e231351f0dd503ac8a89ee4b5b4c212a14d1de 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/CollectionListTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/CollectionListTag.java @@ -42,7 +42,7 @@ public class CollectionListTag extends TagSupport try { - out.println("<table align=\"center\" class=\"miscTable\" title=\"Collection List\">"); + out.println("<table align=\"center\" class=\"table\" title=\"Collection List\">"); // Write column headings out.print("<tr><th id=\"t4\" class=\"oddRowOddCol\">" diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/CommunityListTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/CommunityListTag.java index 2f7dc3238e08d2309a66e07211fe33c3c8d6562a..4a2bdd7eea0afea22c38e66e0160398ff9460363 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/CommunityListTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/CommunityListTag.java @@ -42,7 +42,7 @@ public class CommunityListTag extends TagSupport try { - out.println("<table align=\"center\" class=\"miscTable\" title=\"Community List\">"); + out.println("<table align=\"center\" class=\"table\" title=\"Community List\">"); // Write column headings out.print("<tr><th id=\"t5\" class=\"oddRowOddCol\">" diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemListTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemListTag.java index 2ea0f37de11b9c12d2ff54d8865795be211c1dca..8fa54b328afc16ee8377681fc7a0e22c8802ecc7 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemListTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemListTag.java @@ -267,12 +267,12 @@ public class ItemListTag extends TagSupport // If the table width has been specified, we can make this a fixed layout if (!StringUtils.isEmpty(tablewidth)) { - out.println("<table style=\"width: " + tablewidth + "; table-layout: fixed;\" align=\"center\" class=\"miscTable\" summary=\"This table browses all dspace content\">"); + out.println("<table style=\"width: " + tablewidth + "; table-layout: fixed;\" align=\"center\" class=\"table\" summary=\"This table browses all dspace content\">"); } else { // Otherwise, don't constrain the width - out.println("<table align=\"center\" class=\"miscTable\" summary=\"This table browses all dspace content\">"); + out.println("<table align=\"center\" class=\"table\" summary=\"This table browses all dspace content\">"); } // Output the known column widths @@ -299,11 +299,11 @@ public class ItemListTag extends TagSupport } else if (!StringUtils.isEmpty(tablewidth)) { - out.println("<table width=\"" + tablewidth + "\" align=\"center\" class=\"miscTable\" summary=\"This table browses all dspace content\">"); + out.println("<table width=\"" + tablewidth + "\" align=\"center\" class=\"table\" summary=\"This table browses all dspace content\">"); } else { - out.println("<table align=\"center\" class=\"miscTable\" summary=\"This table browses all dspace content\">"); + out.println("<table align=\"center\" class=\"table\" summary=\"This table browses all dspace content\">"); } // Output the table headers @@ -535,6 +535,23 @@ public class ItemListTag extends TagSupport metadata = "<em>" + sb.toString() + "</em>"; } } + //In case title has no value, replace it with "undefined" so as the user has something to + //click in order to access the item page + else if (field.equals(titleField)){ + String undefined = LocaleSupport.getLocalizedMessage(pageContext, "itemlist.title.undefined"); + if (items[i].isWithdrawn()) + { + metadata = "<span style=\"font-style:italic\">("+undefined+")</span>"; + } + // format the title field correctly (as long as the item isn't withdrawn, link to it) + else + { + metadata = "<a href=\"" + hrq.getContextPath() + "/handle/" + + items[i].getHandle() + "\">" + + "<span style=\"font-style:italic\">("+undefined+")</span>" + + "</a>"; + } + } // prepare extra special layout requirements for dates String extras = ""; diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemTag.java index 9e5e5490ccbd6e20eff3125abf86a9dcbdfb654e..080884a79ae9f89be9d30de10f1c8f690725bc8e 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/ItemTag.java @@ -34,6 +34,7 @@ import org.dspace.app.util.MetadataExposure; import org.dspace.app.util.Util; import org.dspace.app.webui.util.StyleSelection; import org.dspace.app.webui.util.UIUtil; +import org.dspace.authorize.AuthorizeManager; import org.dspace.browse.BrowseException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; @@ -391,7 +392,7 @@ public class ItemTag extends TagSupport configLine = defaultFields; } - out.println("<center><table class=\"itemDisplayTable\">"); + out.println("<table class=\"table itemDisplayTable\">"); /* * Break down the configuration into fields and display them @@ -472,7 +473,7 @@ public class ItemTag extends TagSupport try { label = I18nUtil.getMessage("metadata." - + (style != null ? style + "." : "") + field, + + ("default".equals(this.style) ? "" : this.style + ".") + field, context); } catch (MissingResourceException e) @@ -623,7 +624,7 @@ public class ItemTag extends TagSupport listCollections(); - out.println("</table></center><br/>"); + out.println("</table><br/>"); listBitstreams(); @@ -648,12 +649,12 @@ public class ItemTag extends TagSupport // Get all the metadata DCValue[] values = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); - out.println("<p align=\"center\">" + out.println("<div class=\"panel panel-info\"><div class=\"panel-heading\">" + LocaleSupport.getLocalizedMessage(pageContext, - "org.dspace.app.webui.jsptag.ItemTag.full") + "</p>"); + "org.dspace.app.webui.jsptag.ItemTag.full") + "</div>"); // Three column table - DC field, value, language - out.println("<center><table class=\"itemDisplayTable\">"); + out.println("<table class=\"panel-body table itemDisplayTable\">"); out.println("<tr><th id=\"s1\" class=\"standard\">" + LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.ItemTag.dcfield") @@ -697,7 +698,7 @@ public class ItemTag extends TagSupport listCollections(); - out.println("</table></center><br/>"); + out.println("</table></div><br/>"); listBitstreams(); @@ -731,7 +732,9 @@ public class ItemTag extends TagSupport out.print(LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.ItemTag.appears")); } - out.print("</td><td class=\"metadataFieldValue\">"); + out.print("</td><td class=\"metadataFieldValue\""+ + (style.equals("full")?"colspan=\"2\"":"") + +">"); for (int i = 0; i < collections.length; i++) { @@ -757,11 +760,11 @@ public class ItemTag extends TagSupport HttpServletRequest request = (HttpServletRequest) pageContext .getRequest(); - out.print("<table align=\"center\" class=\"miscTable\"><tr>"); - out.println("<td class=\"evenRowEvenCol\"><p><strong>" + out.print("<div class=\"panel panel-info\">"); + out.println("<div class=\"panel-heading\">" + LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.ItemTag.files") - + "</strong></p>"); + + "</div>"); try { @@ -781,10 +784,10 @@ public class ItemTag extends TagSupport // if user already has uploaded at least one file if (!filesExist) { - out.println("<p>" + out.println("<div class=\"panel-body\">" + LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.ItemTag.files.no") - + "</p>"); + + "</div>"); } else { @@ -824,7 +827,7 @@ public class ItemTag extends TagSupport } out - .println("<table cellpadding=\"6\"><tr><th id=\"t1\" class=\"standard\">" + .println("<table class=\"table panel-body\"><tr><th id=\"t1\" class=\"standard\">" + LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.ItemTag.file") + "</th>"); @@ -846,7 +849,7 @@ public class ItemTag extends TagSupport + "</th><th id=\"t4\" class=\"standard\">" + LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.ItemTag.fileformat") - + "</th></tr>"); + + "</th><th> </th></tr>"); // if primary bitstream is html, display a link for only that one to // HTMLServlet @@ -886,7 +889,7 @@ public class ItemTag extends TagSupport out.print("</td><td headers=\"t4\" class=\"standard\">"); out.print(primaryBitstream.getFormatDescription()); out - .print("</td><td class=\"standard\"><a target=\"_blank\" href=\""); + .print("</td><td class=\"standard\"><a class=\"btn btn-primary\" target=\"_blank\" href=\""); out.print(request.getContextPath()); out.print("/html/"); out.print(handle + "/"); @@ -900,6 +903,15 @@ public class ItemTag extends TagSupport } else { + Context context = UIUtil + .obtainContext(request); + boolean showRequestCopy = false; + if ("all".equalsIgnoreCase(ConfigurationManager.getProperty("request.item.type")) || + ("logged".equalsIgnoreCase(ConfigurationManager.getProperty("request.item.type")) && + context.getCurrentUser() != null)) + { + showRequestCopy = true; + } for (int i = 0; i < bundles.length; i++) { Bitstream[] bitstreams = bundles[i].getBitstreams(); @@ -913,7 +925,7 @@ public class ItemTag extends TagSupport // Work out what the bitstream link should be // (persistent // ID if item has Handle) - String bsLink = "<a target=\"_blank\" href=\"" + String bsLink = "target=\"_blank\" href=\"" + request.getContextPath(); if ((handle != null) @@ -936,7 +948,8 @@ public class ItemTag extends TagSupport out .print("<tr><td headers=\"t1\" class=\"standard\">"); - out.print(bsLink); + out.print("<a "); + out.print(bsLink); out.print(bitstreams[k].getName()); out.print("</a>"); @@ -977,6 +990,7 @@ public class ItemTag extends TagSupport .getName(), Constants.DEFAULT_ENCODING); + out.print("<a "); out.print(bsLink); out.print("<img src=\"" + myPath + "\" "); out.print("alt=\"" + tAltText @@ -984,13 +998,35 @@ public class ItemTag extends TagSupport } } + out.print("<a class=\"btn btn-primary\" "); out .print(bsLink + LocaleSupport .getLocalizedMessage( pageContext, "org.dspace.app.webui.jsptag.ItemTag.view") - + "</a></td></tr>"); + + "</a>"); + + try { + if (showRequestCopy && !AuthorizeManager + .authorizeActionBoolean(context, + bitstreams[k], + Constants.READ)) + out.print(" <a class=\"btn btn-success\" href=\"" + + request.getContextPath() + + "/request-item?handle=" + + handle + + "&bitstream-id=" + + bitstreams[k].getID() + + "\">" + + LocaleSupport + .getLocalizedMessage( + pageContext, + "org.dspace.app.webui.jsptag.ItemTag.restrict") + + "</a>"); + } catch (Exception e) { + } + out.print("</td></tr>"); } } } @@ -1004,7 +1040,7 @@ public class ItemTag extends TagSupport throw new IOException(sqle.getMessage(), sqle); } - out.println("</td></tr></table>"); + out.println("</div>"); } private void getThumbSettings() @@ -1032,7 +1068,7 @@ public class ItemTag extends TagSupport throw new IOException(sqle.getMessage(), sqle); } - out.println("<table align=\"center\" class=\"attentionTable\"><tr>"); + out.println("<table align=\"center\" class=\"table attentionTable\"><tr>"); out.println("<td class=\"attentionCell\"><p><strong>" + LocaleSupport.getLocalizedMessage(pageContext, @@ -1046,7 +1082,7 @@ public class ItemTag extends TagSupport for (int k = 0; k < bitstreams.length; k++) { out.print("<div align=\"center\" class=\"standard\">"); - out.print("<strong><a target=\"_blank\" href=\""); + out.print("<strong><a class=\"btn btn-primary\" target=\"_blank\" href=\""); out.print(request.getContextPath()); out.print("/retrieve/"); out.print(bitstreams[k].getID() + "/"); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/LayoutTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/LayoutTag.java index 0613acdaf1b97d68ee62a351ff80833d70359de1..f904b37baeae5d0e36ed42d7b6384f29aed7856c 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/LayoutTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/LayoutTag.java @@ -19,13 +19,14 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.JspException; import javax.servlet.jsp.jstl.fmt.LocaleSupport; -import javax.servlet.jsp.tagext.TagSupport; +import javax.servlet.jsp.tagext.BodyTagSupport; +import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.dspace.app.webui.servlet.FeedServlet; import org.dspace.content.Collection; import org.dspace.content.Community; import org.dspace.core.ConfigurationManager; -import org.dspace.app.webui.servlet.FeedServlet; /** * Tag for HTML page layout ("skin"). @@ -74,7 +75,7 @@ import org.dspace.app.webui.servlet.FeedServlet; * @author Robert Tansley * @version $Revision$ */ -public class LayoutTag extends TagSupport +public class LayoutTag extends BodyTagSupport { /** log4j logger */ private static Logger log = Logger.getLogger(LayoutTag.class); @@ -112,24 +113,27 @@ public class LayoutTag extends TagSupport /** Syndication feed "autodiscovery" link data */ private String feedData; + private String templatePath; + public LayoutTag() { super(); + String template = ConfigurationManager.getProperty("jspui.template.name"); + if (StringUtils.isNotBlank(template) + && !"default".equalsIgnoreCase(template)) + { + templatePath = "/layout/" + template + "/"; + } + else + { + templatePath = "/layout/"; + } } public int doStartTag() throws JspException { ServletRequest request = pageContext.getRequest(); - - // header file - String header = "/layout/header-default.jsp"; - - // Choose default style unless one is specified - if (style != null) - { - header = "/layout/header-" + style.toLowerCase() + ".jsp"; - } - + // Sort out location bar if (locbar == null) { @@ -246,7 +250,7 @@ public class LayoutTag extends TagSupport } else { - request.setAttribute("dspace.layout.navbar", "/layout/navbar-" + request.setAttribute("dspace.layout.navbar", templatePath + "navbar-" + navbar + ".jsp"); } @@ -323,12 +327,34 @@ public class LayoutTag extends TagSupport request.setAttribute("dspace.layout.feedref", "NONE" ); } + return EVAL_BODY_BUFFERED; + } + + public int doEndTag() throws JspException + { + // Context objects + ServletRequest request = pageContext.getRequest(); + HttpServletResponse response = (HttpServletResponse) pageContext + .getResponse(); + ServletConfig config = pageContext.getServletConfig(); + + // header file + String header = templatePath + "header-default.jsp"; + + // Choose default style unless one is specified + if (style != null) + { + header = templatePath + "header-" + style.toLowerCase() + ".jsp"; + } + + if (sidebar != null) + { + request.setAttribute("dspace.layout.sidebar", sidebar); + } + // Now include the header try { - HttpServletResponse response = (HttpServletResponse) pageContext - .getResponse(); - // Set headers to prevent browser caching, if appropriate if ((noCache != null) && noCache.equalsIgnoreCase("true")) { @@ -341,12 +367,13 @@ public class LayoutTag extends TagSupport // in the response. response.setContentType("text/html; charset=UTF-8"); - ServletConfig config = pageContext.getServletConfig(); - RequestDispatcher rd = config.getServletContext() .getRequestDispatcher(header); rd.include(request, response); + + //pageContext.getOut().write(getBodyContent().getString()); + getBodyContent().writeOut(pageContext.getOut()); } catch (IOException ioe) { @@ -357,19 +384,14 @@ public class LayoutTag extends TagSupport log.warn("Exception", se.getRootCause()); throw new JspException("Got ServletException: " + se); } - - return EVAL_BODY_INCLUDE; - } - - public int doEndTag() throws JspException - { + // Footer file to use - String footer = "/layout/footer-default.jsp"; + String footer = templatePath + "footer-default.jsp"; // Choose default flavour unless one is specified if (style != null) { - footer = "/layout/footer-" + style.toLowerCase() + ".jsp"; + footer = templatePath + "footer-" + style.toLowerCase() + ".jsp"; } try @@ -377,16 +399,6 @@ public class LayoutTag extends TagSupport // Ensure body is included before footer pageContext.getOut().flush(); - // Context objects - ServletRequest request = pageContext.getRequest(); - ServletResponse response = pageContext.getResponse(); - ServletConfig config = pageContext.getServletConfig(); - - if (sidebar != null) - { - request.setAttribute("dspace.layout.sidebar", sidebar); - } - RequestDispatcher rd = config.getServletContext() .getRequestDispatcher(footer); @@ -401,6 +413,15 @@ public class LayoutTag extends TagSupport throw new JspException("Got IOException: " + ioe); } + style = null; + title = null; + sidebar = null; + navbar = null; + locbar = null; + parentTitle = null; + parentLink = null; + noCache = null; + feedData = null; return EVAL_PAGE; } @@ -628,17 +649,4 @@ public class LayoutTag extends TagSupport { this.feedData = v; } - - public void release() - { - style = null; - title = null; - sidebar = null; - navbar = null; - locbar = null; - parentTitle = null; - parentLink = null; - noCache = null; - feedData = null; - } } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectEPersonTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectEPersonTag.java index c5c46089aee3ee5c03bdeb3b11dea13f492be852..144abfa5b589a3f2df884cc3014e8a31df697281 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectEPersonTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectEPersonTag.java @@ -108,7 +108,7 @@ public class SelectEPersonTag extends TagSupport HttpServletRequest req = (HttpServletRequest) pageContext .getRequest(); - out.print("<table><tr><td colspan=\"2\" align=\"center\"><select multiple=\"multiple\" name=\"eperson_id\" size=\""); + out.print("<select class=\"form-control\" multiple=\"multiple\" name=\"eperson_id\" size=\""); out.print(multiple ? "10" : "1"); out.println("\">"); // ensure that if no eperson is selected that a blank option is displayed - xhtml compliance @@ -129,37 +129,27 @@ public class SelectEPersonTag extends TagSupport } // add blank option value if no person selected to ensure that code is xhtml compliant //out.print("<option/>"); - out.print("</select></td>"); - - if (multiple) - { - out.print("</tr><tr><td width=\"50%\" align=\"center\">"); - } - else - { - out.print("<td>"); - } - + out.print("</select>"); + out.print("<br/><div class=\"row container\">"); String p = (multiple ? LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.SelectEPersonTag.selectPeople") : LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.SelectEPersonTag.selectPerson") ); - out.print("<input type=\"button\" value=\"" + p - + "\" onclick=\"javascript:popup_window('" - + req.getContextPath() + "/tools/eperson-list?multiple=" - + multiple + "', 'eperson_popup');\" />"); if (multiple) { - out.print("</td><td width=\"50%\" align=\"center\">"); - out.print("<input type=\"button\" value=\"" + out.print("<input class=\"btn btn-danger\" type=\"button\" value=\"" + LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.SelectEPersonTag.removeSelected") + "\" onclick=\"javascript:removeSelected(window.document.epersongroup.eperson_id);\"/>"); } - - out.println("</td></tr></table>"); + + out.print("<input class=\"btn btn-primary pull-right\" type=\"button\" value=\"" + p + + "\" onclick=\"javascript:popup_window('" + + req.getContextPath() + "/tools/eperson-list?multiple=" + + multiple + "', 'eperson_popup');\" />"); + out.print("</div>"); } catch (IOException ie) { diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectGroupTag.java b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectGroupTag.java index bbc695e58921efe535c73a4c3f38d17753137c85..cfa519c4137281b41216cb5e01502c2f7bb6b9f3 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectGroupTag.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/jsptag/SelectGroupTag.java @@ -104,7 +104,7 @@ public class SelectGroupTag extends TagSupport JspWriter out = pageContext.getOut(); HttpServletRequest req = (HttpServletRequest) pageContext.getRequest(); - out.print("<table><tr><td colspan=\"2\" align=\"center\"><select multiple=\"multiple\" name=\"group_ids\" size=\""); + out.print("<select class=\"form-control\" multiple=\"multiple\" name=\"group_ids\" size=\""); out.print(multiple ? "10" : "1"); out.println("\">"); @@ -124,37 +124,27 @@ public class SelectGroupTag extends TagSupport } } - out.print("</select></td>"); - - if (multiple) - { - out.print("</tr><tr><td width=\"50%\" align=\"center\">"); - } - else - { - out.print("<td>"); - } - + out.print("</select>"); + out.print("<br/><div class=\"row container\">"); String p = (multiple ? LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.SelectGroupTag.selectGroups") : LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.SelectGroupTag.selectGroup") ); - out.print("<input type=\"button\" value=\"" + p - + "\" onclick=\"javascript:popup_window('" - + req.getContextPath() + "/tools/group-select-list?multiple=" - + multiple + "', 'group_popup');\" />"); - - if (multiple) + + if (multiple) { - out.print("</td><td width=\"50%\" align=\"center\">"); - out.print("<input type=\"button\" value=\"" + out.print("<input class=\"btn btn-danger\" type=\"button\" value=\"" + LocaleSupport.getLocalizedMessage(pageContext, "org.dspace.app.webui.jsptag.SelectGroupTag.removeSelected") + "\" onclick=\"javascript:removeSelected(window.document.epersongroup.group_ids);\"/>"); } - - out.println("</td></tr></table>"); + + out.print("<input class=\"btn btn-primary pull-right\" type=\"button\" value=\"" + p + + "\" onclick=\"javascript:popup_window('" + + req.getContextPath() + "/tools/group-select-list?multiple=" + + multiple + "', 'group_popup');\" />"); + out.print("</div>"); } catch (IOException ie) { diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/search/LuceneSearchRequestProcessor.java b/dspace-jspui/src/main/java/org/dspace/app/webui/search/LuceneSearchRequestProcessor.java index d10329ac4184429e297fd82f52d670ccc93f8607..d7e6788b30de7fdbe4e8d2dccb898d658cbeac22 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/search/LuceneSearchRequestProcessor.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/search/LuceneSearchRequestProcessor.java @@ -38,6 +38,7 @@ import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.ItemIterator; +import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.I18nUtil; @@ -52,8 +53,19 @@ import org.dspace.usage.UsageSearchEvent; import org.dspace.utils.DSpace; import org.w3c.dom.Document; +/** +* @deprecated Since DSpace 4 the system use an abstraction layer named +* Discovery to provide access to different search provider. The +* legacy system build upon Apache Lucene is likely to be removed in +* a future version. If you are interested in use Lucene as backend +* for the DSpace search system please consider to build a Lucene +* implementation of the Discovery interfaces +*/ +@Deprecated public class LuceneSearchRequestProcessor implements SearchRequestProcessor { + private static final int ITEMMAP_RESULT_PAGE_SIZE = 50; + /** log4j category */ private static Logger log = Logger.getLogger(SimpleSearchServlet.class); @@ -62,12 +74,42 @@ public class LuceneSearchRequestProcessor implements SearchRequestProcessor private static String msgKey = "org.dspace.app.webui.servlet.FeedServlet"; + private List<String> searchIndices = null; + public synchronized void init() { if (localeLabels == null) { localeLabels = new HashMap<String, Map<String, String>>(); } + + if (searchIndices == null) + { + searchIndices = new ArrayList<String>(); + String definition; + + int idx = 1; + + while ( ((definition = ConfigurationManager.getProperty("jspui.search.index.display." + idx))) != null){ + String index = definition; + searchIndices.add(index); + idx++; + } + + // backward compatibility + if (searchIndices.size() == 0) + { + searchIndices.add("ANY"); + searchIndices.add("author"); + searchIndices.add("title"); + searchIndices.add("keyword"); + searchIndices.add("abstract"); + searchIndices.add("series"); + searchIndices.add("sponsor"); + searchIndices.add("identifier"); + searchIndices.add("language"); + } + } } /** @@ -667,6 +709,62 @@ public class LuceneSearchRequestProcessor implements SearchRequestProcessor } } + /** + * Method for searching authors in item map + * + * author: gam + */ + @Override + public void doItemMapSearch(Context context, HttpServletRequest request, + HttpServletResponse response) throws SearchProcessorException, ServletException, IOException + { + String query = (String) request.getParameter("query"); + int page = UIUtil.getIntParameter(request, "page")-1; + int offset = page > 0? page * ITEMMAP_RESULT_PAGE_SIZE:0; + Collection collection = (Collection) request.getAttribute("collection"); + String idx = (String) request.getParameter("index"); + if (StringUtils.isNotBlank(idx) && !idx.equalsIgnoreCase("any")) + { + query = idx + ":(" + query + ")"; + } + QueryArgs queryArgs = new QueryArgs(); + queryArgs.setQuery(query + " -location:l" + collection.getID()); + queryArgs.setPageSize(ITEMMAP_RESULT_PAGE_SIZE); + queryArgs.setStart(offset); + QueryResults results = DSQuery.doQuery(context, queryArgs); + + Map<Integer, Item> items = new HashMap<Integer, Item>(); + List<String> handles = results.getHitHandles(); + try + { + for (String handle : handles) + { + DSpaceObject resultDSO = HandleManager.resolveToObject(context, handle); + + if (resultDSO.getType() == Constants.ITEM) + { + Item item = (Item) resultDSO; + if (AuthorizeManager.authorizeActionBoolean(context, item, Constants.READ)) + { + items.put(Integer.valueOf(item.getID()), item); + } + } + } + } + catch (SQLException e) + { + throw new SearchProcessorException(e.getMessage(), e); + } + + request.setAttribute("browsetext", query); + request.setAttribute("items", items); + request.setAttribute("more", results.getHitCount() > offset + ITEMMAP_RESULT_PAGE_SIZE); + request.setAttribute("browsetype", "Add"); + request.setAttribute("page", page > 0 ? page + 1 : 1); + + JSPManager.showJSP(request, response, "itemmap-browse.jsp"); + } + /** * Export the search results as a csv file * @@ -731,4 +829,17 @@ public class LuceneSearchRequestProcessor implements SearchRequestProcessor } return labelMap; } + + @Override + public String getI18NKeyPrefix() + { + return "jsp.search.advanced.type."; + } + + @Override + public List<String> getSearchIndices() + { + init(); + return searchIndices; + } } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/search/SearchRequestProcessor.java b/dspace-jspui/src/main/java/org/dspace/app/webui/search/SearchRequestProcessor.java index aef54dc1ffe85221f3328f9e5c910822408b058c..c1614fe234e99a85c896567bdeb2580f87f157d5 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/search/SearchRequestProcessor.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/search/SearchRequestProcessor.java @@ -8,6 +8,7 @@ package org.dspace.app.webui.search; import java.io.IOException; +import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -29,4 +30,12 @@ public interface SearchRequestProcessor HttpServletResponse response) throws SearchProcessorException, IOException, ServletException; + public void doItemMapSearch(Context context, HttpServletRequest request, + HttpServletResponse response) throws SearchProcessorException, + IOException, ServletException; + + public List<String> getSearchIndices(); + + public String getI18NKeyPrefix(); + } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/AdvancedSearchServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/AdvancedSearchServlet.java index 6885f4e87d81f49c3269a787a62a8a3668d15992..0fc1bbba65fcfb0e60195c5f5bca34c1135136d7 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/AdvancedSearchServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/AdvancedSearchServlet.java @@ -15,6 +15,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; +import org.dspace.app.webui.discovery.DiscoverySearchRequestProcessor; import org.dspace.app.webui.search.LuceneSearchRequestProcessor; import org.dspace.app.webui.search.SearchProcessorException; import org.dspace.app.webui.search.SearchRequestProcessor; @@ -48,8 +49,8 @@ public class AdvancedSearchServlet extends DSpaceServlet e); } if (internalLogic == null) - { // backward compatibility - internalLogic = new LuceneSearchRequestProcessor(); + { // Discovery is the default search provider since DSpace 4.0 + internalLogic = new DiscoverySearchRequestProcessor(); } } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/CommunityListServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/CommunityListServlet.java index 939d23ba078a42604a01b36b7be609dc34373c1d..2789ed36f62a41361a20e1d3bcbd1b003e064217 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/CommunityListServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/CommunityListServlet.java @@ -11,6 +11,7 @@ import java.io.IOException; import java.sql.SQLException; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.locks.*; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -33,46 +34,71 @@ import org.dspace.core.LogManager; */ public class CommunityListServlet extends DSpaceServlet { + + // This will map community IDs to arrays of collections + private Map<Integer, Collection[]> colMap; + + // This will map communityIDs to arrays of sub-communities + private Map<Integer, Community[]> commMap; + private static final Object staticLock = new Object(); + /** log4j category */ private static Logger log = Logger.getLogger(CommunityListServlet.class); protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException - { - log.info(LogManager.getHeader(context, "view_community_list", "")); + { + synchronized (staticLock) + { + colMap = new HashMap<Integer, Collection[]>(); + commMap = new HashMap<Integer, Community[]>(); - // This will map community IDs to arrays of collections - Map<Integer, Collection[]> colMap = new HashMap<Integer, Collection[]>(); + log.info(LogManager.getHeader(context, "view_community_list", "")); - // This will map communityIDs to arrays of sub-communities - Map<Integer, Community[]> commMap = new HashMap<Integer, Community[]>(); + Community[] communities = Community.findAllTop(context); - Community[] communities = Community.findAllTop(context); + for (int com = 0; com < communities.length; com++) + { + build(communities[com]); + } - for (int com = 0; com < communities.length; com++) - { - Integer comID = Integer.valueOf(communities[com].getID()); + // can they admin communities? + if (AuthorizeManager.isAdmin(context)) + { + // set a variable to create an edit button + request.setAttribute("admin_button", Boolean.TRUE); + } - // Find collections in community - Collection[] colls = communities[com].getCollections(); - colMap.put(comID, colls); + request.setAttribute("communities", communities); + request.setAttribute("collections.map", colMap); + request.setAttribute("subcommunities.map", commMap); + JSPManager.showJSP(request, response, "/community-list.jsp"); + } + } + /* + * Get all subcommunities and collections from a community + */ + private void build(Community c) throws SQLException { - // Find subcommunties in community - Community[] comms = communities[com].getSubcommunities(); - commMap.put(comID, comms); - } + Integer comID = Integer.valueOf(c.getID()); + + // Find collections in community + Collection[] colls = c.getCollections(); + colMap.put(comID, colls); - // can they admin communities? - if (AuthorizeManager.isAdmin(context)) + // Find subcommunties in community + Community[] comms = c.getSubcommunities(); + + // Get all subcommunities for each communities if they have some + if (comms.length > 0) { - // set a variable to create an edit button - request.setAttribute("admin_button", Boolean.TRUE); + commMap.put(comID, comms); + + for (int sub = 0; sub < comms.length; sub++) { + + build(comms[sub]); + } } - - request.setAttribute("communities", communities); - request.setAttribute("collections.map", colMap); - request.setAttribute("subcommunities.map", commMap); - JSPManager.showJSP(request, response, "/community-list.jsp"); } } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/FeedbackServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/FeedbackServlet.java index b8328b94f3c09a4c0f918f0038b7a3cf78f82853..0f3c625242084417bde604da18df9a3a2b914f6d 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/FeedbackServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/FeedbackServlet.java @@ -109,7 +109,7 @@ public class FeedbackServlet extends DSpaceServlet // All data is there, send the email try { - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "feedback")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "feedback")); email.addRecipient(ConfigurationManager .getProperty("feedback.recipient")); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/LogoutServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/LogoutServlet.java index b98b9c0dbda32be626fac26e064a2cffa1de3d9c..8598730563e375fae32a6fe853d36b99170bc6a9 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/LogoutServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/LogoutServlet.java @@ -40,6 +40,14 @@ public class LogoutServlet extends DSpaceServlet Authenticate.loggedOut(context, request); + // if the user still logged in (i.e. it was a login as)? + if (context.getCurrentUser() != null) + { + // redirect to the admin home page + response.sendRedirect(request.getContextPath()+"/dspace-admin/"); + return; + } + // Display logged out message JSPManager.showJSP(request, response, "/login/logged-out.jsp"); } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/OpenSearchServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/OpenSearchServlet.java index 49634edbac071fd519f1c1c76e24f2c47d4359ef..bef2a05c0f6ae8db01cf1b9bf705e81310af16e8 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/OpenSearchServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/OpenSearchServlet.java @@ -15,6 +15,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; +import org.dspace.app.webui.discovery.DiscoverySearchRequestProcessor; import org.dspace.app.webui.search.LuceneSearchRequestProcessor; import org.dspace.app.webui.search.SearchProcessorException; import org.dspace.app.webui.search.SearchRequestProcessor; @@ -57,8 +58,8 @@ public class OpenSearchServlet extends DSpaceServlet e); } if (internalLogic == null) - { // backward compatibility - internalLogic = new LuceneSearchRequestProcessor(); + { // Discovery is the default search provider since DSpace 4.0 + internalLogic = new DiscoverySearchRequestProcessor(); } } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SimpleSearchServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SimpleSearchServlet.java index d366f06f5fdb65859f5b54ee7bfa2234f6b609ab..00155070b566b097f7306f9ab1e19ce2b2a5bacf 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SimpleSearchServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SimpleSearchServlet.java @@ -15,6 +15,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; +import org.dspace.app.webui.discovery.DiscoverySearchRequestProcessor; import org.dspace.app.webui.search.LuceneSearchRequestProcessor; import org.dspace.app.webui.search.SearchProcessorException; import org.dspace.app.webui.search.SearchRequestProcessor; @@ -48,8 +49,8 @@ public class SimpleSearchServlet extends DSpaceServlet e); } if (internalLogic == null) - { // backward compatibility - internalLogic = new LuceneSearchRequestProcessor(); + { // Discovery is the default search provider since DSpace 4.0 + internalLogic = new DiscoverySearchRequestProcessor(); } } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SubmissionController.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SubmissionController.java index b80ddc4b3b3bb9577bc87de64ee6537b2b42c7b6..f53a77cc9457553ec3448fcf67529125732e2bdf 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SubmissionController.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SubmissionController.java @@ -21,22 +21,25 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException; import org.apache.log4j.Logger; - import org.dspace.app.util.SubmissionInfo; import org.dspace.app.util.SubmissionStepConfig; import org.dspace.app.webui.submit.JSPStepManager; import org.dspace.app.webui.util.FileUploadRequest; +import org.dspace.app.webui.util.JSONUploadResponse; import org.dspace.app.webui.util.JSPManager; import org.dspace.app.webui.util.UIUtil; import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.WorkspaceItem; +import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.workflow.WorkflowItem; import org.dspace.submit.AbstractProcessingStep; +import com.google.gson.Gson; + /** * Submission Manager servlet for DSpace. Handles the initial submission of * items, as well as the editing of items further down the line. @@ -226,7 +229,22 @@ public class SubmissionController extends DSpaceServlet } catch (FileSizeLimitExceededException e) { log.warn("Upload exceeded upload.max"); - JSPManager.showFileSizeLimitExceededError(request, response, e.getMessage(), e.getActualSize(), e.getPermittedSize()); + if (ConfigurationManager.getBooleanProperty("webui.submit.upload.progressbar", true)) + { + Gson gson = new Gson(); + // old browser need to see this response as html to work + response.setContentType("text/html"); + JSONUploadResponse jsonResponse = new JSONUploadResponse(); + jsonResponse.addUploadFileSizeLimitExceeded( + e.getActualSize(), e.getPermittedSize()); + response.getWriter().print(gson.toJson(jsonResponse)); + response.flushBuffer(); + } + else + { + JSPManager.showFileSizeLimitExceededError(request, response, e.getMessage(), e.getActualSize(), e.getPermittedSize()); + } + return; } //also, upload any files and save their contents to Request (for later processing by UploadStep) @@ -513,7 +531,7 @@ public class SubmissionController extends DSpaceServlet if (!subInfo.isInWorkflow()) { - stepAndPageReached = Float.parseFloat(getStepReached(subInfo)+"."+JSPStepManager.getPageReached(subInfo)); + stepAndPageReached = Double.parseDouble(getStepReached(subInfo)+"."+JSPStepManager.getPageReached(subInfo)); } if (result != AbstractProcessingStep.STATUS_COMPLETE && currStepAndPage != stepAndPageReached) @@ -670,14 +688,13 @@ public class SubmissionController extends DSpaceServlet int currStep = currentStepConfig.getStepNumber(); int currPage = AbstractProcessingStep.getCurrentPage(request); - double currStepAndPage = Float - .parseFloat(currStep + "." + currPage); + double currStepAndPage = Double.parseDouble(currStep + "." + currPage); // default value if we are in workflow double stepAndPageReached = -1; if (!subInfo.isInWorkflow()) { - stepAndPageReached = Float.parseFloat(getStepReached(subInfo)+"."+JSPStepManager.getPageReached(subInfo)); + stepAndPageReached = Double.parseDouble(getStepReached(subInfo)+"."+JSPStepManager.getPageReached(subInfo)); } if (result != AbstractProcessingStep.STATUS_COMPLETE diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SubscribeServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SubscribeServlet.java index 2a36aae1d0b067d64f6cf6ec1f269a33dad33439..5370f75e2470eec3f998383420d09b802944b2c2 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SubscribeServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SubscribeServlet.java @@ -14,6 +14,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.dspace.app.util.CollectionDropDown; import org.dspace.app.webui.util.JSPManager; import org.dspace.app.webui.util.UIUtil; import org.dspace.authorize.AuthorizeException; @@ -60,6 +61,22 @@ public class SubscribeServlet extends DSpaceServlet context.complete(); } + else if (submit.equals("submit_subscribe")) + { + int collID = UIUtil.getIntParameter(request, "collection"); + Collection c = Collection.find(context, collID); + + // Sanity check - ignore duff values + if (c != null) + { + Subscribe.subscribe(context, e, c); + } + + // Show the list of subscriptions + showSubscriptions(context, request, response, true); + + context.complete(); + } else if (submit.equals("submit_unsubscribe")) { int collID = UIUtil.getIntParameter(request, "collection"); @@ -102,10 +119,14 @@ public class SubscribeServlet extends DSpaceServlet HttpServletResponse response, boolean updated) throws ServletException, IOException, SQLException { + // collections the currently logged in user can subscribe to + Collection[] avail = Subscribe.getAvailableSubscriptions(context); + // Subscribed collections Collection[] subs = Subscribe.getSubscriptions(context, context .getCurrentUser()); + request.setAttribute("availableSubscriptions", avail); request.setAttribute("subscriptions", subs); request.setAttribute("updated", Boolean.valueOf(updated)); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SuggestServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SuggestServlet.java index 1781919a295340fbf7c76ad7ffc9d210580ff3a1..3ae850b93fa23f4868e6d1b17add9cb89f7b9711 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SuggestServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/SuggestServlet.java @@ -77,7 +77,7 @@ public class SuggestServlet extends DSpaceServlet // Obtain information from request String handle = request.getParameter("handle"); - + // Lookup Item title & collection String title = null; String collName = null; @@ -85,7 +85,7 @@ public class SuggestServlet extends DSpaceServlet { Item item = (Item) HandleManager.resolveToObject(context, handle); if (item != null) - { + { DCValue[] titleDC = item.getDC("title", null, Item.ANY); if (titleDC != null && titleDC.length > 0) { @@ -111,18 +111,18 @@ public class SuggestServlet extends DSpaceServlet collName = ""; } request.setAttribute("suggest.title", title); - + // User email from context EPerson currentUser = context.getCurrentUser(); String authEmail = null; String userName = null; - + if (currentUser != null) { authEmail = currentUser.getEmail(); userName = currentUser.getFullName(); - } - + } + if (request.getParameter("submit") != null) { String recipAddr = request.getParameter("recip_email"); @@ -177,13 +177,13 @@ public class SuggestServlet extends DSpaceServlet } String itemUri = HandleManager.getCanonicalForm(handle); String itemUrl = HandleManager.resolveToURL(context,handle); - String message = request.getParameter("message"); + String message = request.getParameter("message"); String siteName = ConfigurationManager.getProperty("dspace.name"); // All data is there, send the email try { - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "suggest")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "suggest")); email.addRecipient(recipAddr); // recipient address email.addArgument(recipName); // 1st arg - recipient name email.addArgument(senderName); // 2nd arg - sender name @@ -192,14 +192,14 @@ public class SuggestServlet extends DSpaceServlet email.addArgument(itemUri); // 5th arg - item handle URI email.addArgument(itemUrl); // 6th arg - item local URL email.addArgument(collName); // 7th arg - collection name - email.addArgument(message); // 8th arg - user comments - + email.addArgument(message); // 8th arg - user comments + // Set sender's address as 'reply-to' address if supplied if ( senderAddr != null && ! "".equals(senderAddr)) { email.setReplyTo(senderAddr); } - + // Only actually send the email if feature is enabled if (ConfigurationManager.getBooleanProperty("webui.suggest.enable", false)) { @@ -226,7 +226,7 @@ public class SuggestServlet extends DSpaceServlet log.info(LogManager.getHeader(context, "show_suggest_form", "problem=false")); request.setAttribute("authenticated.email", authEmail); request.setAttribute("eperson.name", userName); - JSPManager.showJSP(request, response, "/suggest/suggest.jsp"); //asd + JSPManager.showJSP(request, response, "/suggest/suggest.jsp"); //asd } } @@ -236,5 +236,5 @@ public class SuggestServlet extends DSpaceServlet { // Treat as a GET doDSGet(context, request, response); - } + } } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EPersonAdminServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EPersonAdminServlet.java index ce9c168013c0dbc773f26c2eb37e8dbc89d12c5a..872981ad17aa1ead44439833bf248380472d3e1a 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EPersonAdminServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EPersonAdminServlet.java @@ -9,19 +9,31 @@ package org.dspace.app.webui.servlet.admin; import java.io.IOException; import java.sql.SQLException; +import java.util.Locale; +import javax.mail.MessagingException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import javax.servlet.jsp.jstl.core.Config; +import org.apache.log4j.Logger; import org.dspace.app.webui.servlet.DSpaceServlet; +import org.dspace.app.webui.util.Authenticate; import org.dspace.app.webui.util.JSPManager; import org.dspace.app.webui.util.UIUtil; +import org.dspace.authenticate.AuthenticationManager; import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; +import org.dspace.core.I18nUtil; +import org.dspace.core.LogManager; +import org.dspace.eperson.AccountManager; import org.dspace.eperson.EPerson; -import org.dspace.eperson.Group; import org.dspace.eperson.EPersonDeletionException; +import org.dspace.eperson.Group; /** * Servlet for editing and creating e-people @@ -31,6 +43,10 @@ import org.dspace.eperson.EPersonDeletionException; */ public class EPersonAdminServlet extends DSpaceServlet { + + /** Logger */ + private static Logger log = Logger.getLogger(EPersonAdminServlet.class); + protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException @@ -86,7 +102,7 @@ public class EPersonAdminServlet extends DSpaceServlet context.complete(); } } - else if (button.equals("submit_save")) + else if (button.equals("submit_save") || button.equals("submit_resetpassword")) { // Update the metadata for an e-person EPerson e = EPerson.find(context, UIUtil.getIntParameter(request, @@ -143,6 +159,20 @@ public class EPersonAdminServlet extends DSpaceServlet e.update(); + if (button.equals("submit_resetpassword")) + { + try + { + resetPassword(context, request, response, e); + } + catch (MessagingException e1) + { + JSPManager + .showJSP(request, response, + "/dspace-admin/eperson-resetpassword-error.jsp"); + return; + } + } showMain(context, request, response); context.complete(); } @@ -197,9 +227,27 @@ public class EPersonAdminServlet extends DSpaceServlet e.update(); + if (button.equals("submit_resetpassword")) + { + try + { + resetPassword(context, request, response, e); + } + catch (MessagingException e1) + { + JSPManager + .showJSP(request, response, + "/dspace-admin/eperson-resetpassword-error.jsp"); + return; + } + } + showMain(context, request, response); context.complete(); } + + + } else if (button.equals("submit_delete")) { @@ -242,6 +290,80 @@ public class EPersonAdminServlet extends DSpaceServlet showMain(context, request, response); context.complete(); } + else if (button.equals("submit_login_as")) + { + if (!ConfigurationManager.getBooleanProperty("webui.user.assumelogin", false)) + { + throw new AuthorizeException("Turn on webui.user.assumelogin to activate Login As feature"); + } + EPerson e = EPerson.find(context, UIUtil.getIntParameter(request, + "eperson_id")); + // Check the EPerson exists + if (e == null) + { + request.setAttribute("no_eperson_selected", new Boolean(true)); + showMain(context, request, response); + } + // Only super administrators can login as someone else. + else if (!AuthorizeManager.isAdmin(context)) + { + throw new AuthorizeException("Only site administrators may assume login as another user."); + } + else + { + + log.info(LogManager.getHeader(context, "login-as", + "current_eperson=" + + context.getCurrentUser().getFullName() + + ", id=" + context.getCurrentUser().getID() + + ", as_eperson=" + e.getFullName() + ", id=" + + e.getID())); + + // Just to be double be sure, make sure the administrator + // is the one who actually authenticated himself. + HttpSession session = request.getSession(false); + Integer authenticatedID = (Integer) session.getAttribute("dspace.current.user.id"); + if (context.getCurrentUser().getID() != authenticatedID) + { + throw new AuthorizeException("Only authenticated users who are administrators may assume the login as another user."); + } + + // You may not assume the login of another super administrator + Group administrators = Group.find(context,1); + if (administrators.isMember(e)) + { + JSPManager.showJSP(request, response, + "/dspace-admin/eperson-loginas-error.jsp"); + return; + } + + // store a reference to the authenticated admin + session.setAttribute("dspace.previous.user.id", authenticatedID); + + // Logged in OK. + Authenticate.loggedIn(context, request, e); + + // Set the Locale according to user preferences + Locale epersonLocale = I18nUtil.getEPersonLocale(context + .getCurrentUser()); + context.setCurrentLocale(epersonLocale); + Config.set(request.getSession(), Config.FMT_LOCALE, + epersonLocale); + + // Set any special groups - invoke the authentication mgr. + int[] groupIDs = AuthenticationManager.getSpecialGroups( + context, request); + + for (int i = 0; i < groupIDs.length; i++) + { + context.setSpecialGroup(groupIDs[i]); + log.debug("Adding Special Group id=" + + String.valueOf(groupIDs[i])); + } + + response.sendRedirect(request.getContextPath() + "/mydspace"); + } + } else { // Cancel etc. pressed - show list again @@ -249,6 +371,16 @@ public class EPersonAdminServlet extends DSpaceServlet } } + private void resetPassword(Context context, HttpServletRequest request, + HttpServletResponse response, EPerson e) throws SQLException, + IOException, AuthorizeException, ServletException, + MessagingException + { + // Note, this may throw an error is the email is bad. + AccountManager.sendForgotPasswordInfo(context, e.getEmail()); + request.setAttribute("reset_password", Boolean.TRUE); + } + private void showMain(Context c, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, SQLException, AuthorizeException diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditCommunitiesServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditCommunitiesServlet.java index 56b0b1ba0ff2591437d0604fad5aab4e25e561a4..1b59af8ecbcf0c3364d74926c1c01b3fb11ba6fc 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditCommunitiesServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditCommunitiesServlet.java @@ -315,7 +315,16 @@ public class EditCommunitiesServlet extends DSpaceServlet } catch (AuthorizeException authex) { request.setAttribute("policy_button", Boolean.FALSE); - } + } + if (AuthorizeManager.isAdmin(context, community)) + { + request.setAttribute("admin_community", Boolean.TRUE); + } + else + { + request.setAttribute("admin_community", Boolean.FALSE); + } + } /** @@ -561,6 +570,14 @@ public class EditCommunitiesServlet extends DSpaceServlet + "/tools/authorize?community_id=" + community.getID() + "&submit_community_select=1")); } + else if (button.equals("submit_curate_community")) + { + // Forward to policy edit page + response.sendRedirect(response.encodeRedirectURL(request + .getContextPath() + + "/tools/curate?community_id=" + + community.getID() + "&submit_community_select=1")); + } else if (button.equals("submit_admins_create")) { // Create new group @@ -796,6 +813,14 @@ public class EditCommunitiesServlet extends DSpaceServlet + "/tools/authorize?collection_id=" + collection.getID() + "&submit_collection_select=1")); } + else if (button.equals("submit_curate_collection")) + { + // Forward to policy edit page + response.sendRedirect(response.encodeRedirectURL(request + .getContextPath() + + "/tools/curate?collection_id=" + + collection.getID() + "&submit_collection_select=1")); + } else if (button.startsWith("submit_wf_edit_")) { int step = Integer.parseInt(button.substring(15)); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditItemServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditItemServlet.java index 9f568b0d8b902241eece82a1b6d9a1b38619a7fb..e0d483b9e5cd46820b711182dbc341e99a2f41b0 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditItemServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/EditItemServlet.java @@ -84,6 +84,15 @@ public class EditItemServlet extends DSpaceServlet /** User confirms the movement of the item */ public static final int CONFIRM_MOVE_ITEM = 8; + /** User starts withdrawal of item */ + public static final int START_PRIVATING = 9; + + /** User confirms withdrawal of item */ + public static final int CONFIRM_PRIVATING = 10; + + /** User confirms withdrawal of item */ + public static final int PUBLICIZE = 11; + /** Logger */ private static Logger log = Logger.getLogger(EditCommunitiesServlet.class); @@ -317,6 +326,32 @@ public class EditItemServlet extends DSpaceServlet } break; + + case START_PRIVATING: + + // Show "withdraw item" confirmation page + JSPManager.showJSP(request, response, + "/tools/confirm-privating-item.jsp"); + + break; + + case CONFIRM_PRIVATING: + + // Withdraw the item + item.setDiscoverable(false); + item.update(); + JSPManager.showJSP(request, response, "/tools/get-item-id.jsp"); + context.complete(); + + break; + + case PUBLICIZE: + item.setDiscoverable(true); + item.update(); + JSPManager.showJSP(request, response, "/tools/get-item-id.jsp"); + context.complete(); + + break; default: @@ -498,7 +533,17 @@ public class EditItemServlet extends DSpaceServlet request.setAttribute("reinstate_button", Boolean.FALSE); } } - + + if (item.isDiscoverable()) + { + request.setAttribute("privating_button", AuthorizeManager + .authorizeActionBoolean(context, item, Constants.WRITE)); + } + else + { + request.setAttribute("publicize_button", AuthorizeManager + .authorizeActionBoolean(context, item, Constants.WRITE)); + } request.setAttribute("item", item); request.setAttribute("handle", handle); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/ItemMapServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/ItemMapServlet.java index 8f646ea1adc50c55f6659e3f5e66f1b46fac2564..bf0ee1e9b0d718f12fd0baafdf3bcd39897d1bf9 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/ItemMapServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/ItemMapServlet.java @@ -8,6 +8,10 @@ package org.dspace.app.webui.servlet.admin; import org.apache.log4j.Logger; +import org.dspace.app.webui.discovery.DiscoverySearchRequestProcessor; +import org.dspace.app.webui.search.LuceneSearchRequestProcessor; +import org.dspace.app.webui.search.SearchProcessorException; +import org.dspace.app.webui.search.SearchRequestProcessor; import org.dspace.app.webui.servlet.DSpaceServlet; import org.dspace.app.webui.util.JSPManager; import org.dspace.app.webui.util.UIUtil; @@ -15,12 +19,15 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.authorize.AuthorizeManager; import org.dspace.browse.*; import org.dspace.content.Collection; +import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.content.ItemIterator; import org.dspace.core.ConfigurationManager; import org.dspace.core.Constants; import org.dspace.core.Context; -import org.dspace.sort.SortOption; +import org.dspace.handle.HandleManager; +import org.dspace.core.PluginConfigurationError; +import org.dspace.core.PluginManager; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -28,6 +35,7 @@ import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; +import java.util.List; import java.util.Map; /** @@ -37,9 +45,30 @@ import java.util.Map; */ public class ItemMapServlet extends DSpaceServlet { - /** Logger */ + private SearchRequestProcessor internalLogic; + + /** Logger */ private static Logger log = Logger.getLogger(ItemMapServlet.class); - + + public void init() + { + try + { + internalLogic = (SearchRequestProcessor) PluginManager + .getSinglePlugin(SearchRequestProcessor.class); + } + catch (PluginConfigurationError e) + { + log.warn( + "ItemMapServlet not properly configurated, please configure the SearchRequestProcessor plugin", + e); + } + if (internalLogic == null) + { // Discovery is the default search provider since DSpace 4.0 + internalLogic = new DiscoverySearchRequestProcessor(); + } + } + protected void doDSGet(Context context, HttpServletRequest request, HttpServletResponse response) throws java.sql.SQLException, javax.servlet.ServletException, java.io.IOException, @@ -162,6 +191,9 @@ public class ItemMapServlet extends DSpaceServlet .setAttribute("all_collections", Collection .findAll(context)); + request.setAttribute("searchIndices", + internalLogic.getSearchIndices()); + request.setAttribute("prefixKey", internalLogic.getI18NKeyPrefix()); // show this page when we're done jspPage = "itemmap-main.jsp"; @@ -268,79 +300,19 @@ public class ItemMapServlet extends DSpaceServlet // show the page JSPManager.showJSP(request, response, jspPage); } - else if (action.equals("Search Authors")) + else if (action.equals("search")) { - String name = (String) request.getParameter("namepart"); - String bidx = ConfigurationManager.getProperty("itemmap.author.index"); - if (bidx == null) - { - throw new ServletException("There is no configuration for itemmap.author.index"); - } - Map<Integer, Item> items = new HashMap<Integer, Item>(); - try - { - BrowserScope bs = new BrowserScope(context); - BrowseIndex bi = BrowseIndex.getBrowseIndex(bidx); - - // set up the browse scope - bs.setBrowseIndex(bi); - bs.setOrder(SortOption.ASCENDING); - bs.setFilterValue(name); - bs.setFilterValuePartial(true); - bs.setJumpToValue(null); - bs.setResultsPerPage(10000); // an arbitrary number (large) for the time being - bs.setBrowseLevel(1); - - BrowseEngine be = new BrowseEngine(context); - BrowseInfo results = be.browse(bs); - Item[] browseItems = results.getItemResults(context); - - // FIXME: oh god this is so annoying - what an API /Richard - // we need to deduplicate against existing items in this collection - ItemIterator itr = myCollection.getItems(); - try - { - ArrayList<Integer> idslist = new ArrayList<Integer>(); - while (itr.hasNext()) - { - idslist.add(Integer.valueOf(itr.nextID())); - } - - for (int i = 0; i < browseItems.length; i++) - { - // only if it isn't already in this collection - if (!idslist.contains(Integer.valueOf(browseItems[i].getID()))) - { - // only put on list if you can read item - if (AuthorizeManager.authorizeActionBoolean(context, browseItems[i], Constants.READ)) - { - items.put(Integer.valueOf(browseItems[i].getID()), browseItems[i]); - } - } - } - } - finally - { - if (itr != null) - { - itr.close(); - } - } + request.setAttribute("collection", myCollection); + try + { + internalLogic.doItemMapSearch(context, request, response); } - catch (BrowseException e) - { - log.error("caught exception: ", e); - throw new ServletException(e); - } - - request.setAttribute("collection", myCollection); - request.setAttribute("browsetext", name); - request.setAttribute("items", items); - request.setAttribute("browsetype", "Add"); - - jspPage = "itemmap-browse.jsp"; - JSPManager.showJSP(request, response, jspPage); - } + catch (SearchProcessorException e) + { + log.error(e.getMessage(), e); + throw new ServletException(e.getMessage(), e); + } + } else if (action.equals("browse")) { // target collection to browse diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/LicenseEditServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/LicenseEditServlet.java index 3feaae990cec5ce4f87214211651c93a8138bf74..a8cb206818e53c54726118ff45db36e6c700842f 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/LicenseEditServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/LicenseEditServlet.java @@ -20,18 +20,19 @@ import org.dspace.app.webui.util.UIUtil; import org.dspace.authorize.AuthorizeException; import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; -import org.dspace.core.I18nUtil; +import org.dspace.core.I18nUtil; +import org.dspace.core.LicenseManager; /** * Servlet for editing the default license - * + * * @author Stuart Lewis */ public class LicenseEditServlet extends DSpaceServlet { /** * Handle GET requests. This does nothing but forwards - * the request on to the POST handler. + * the request on to the POST handler. */ protected void doDSGet(Context c, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException, @@ -59,7 +60,7 @@ public class LicenseEditServlet extends DSpaceServlet else if (!button.equals("submit_save")) { // Get the existing text from the ConfigurationManager - String license = ConfigurationManager.getLicenseText(I18nUtil.getDefaultLicense(c)); + String license = LicenseManager.getLicenseText(I18nUtil.getDefaultLicense(c)); // Pass the existing license back to the JSP request.setAttribute("license", license); @@ -76,11 +77,11 @@ public class LicenseEditServlet extends DSpaceServlet if (license.trim().equals("")) { // Get the existing text from the ConfigurationManager - license = ConfigurationManager.getLicenseText(I18nUtil.getDefaultLicense(c)); + license = LicenseManager.getLicenseText(I18nUtil.getDefaultLicense(c)); // Pass the existing license back to the JSP request.setAttribute("license", license); - + // Pass the 'empty' message back request.setAttribute("empty", "true"); @@ -90,14 +91,14 @@ public class LicenseEditServlet extends DSpaceServlet else { // Write the string out to file - ConfigurationManager.writeLicenseFile(I18nUtil.getDefaultLicense(c), license); - + LicenseManager.writeLicenseFile(I18nUtil.getDefaultLicense(c), license); + // Pass the existing license back to the JSP request.setAttribute("license", license); - + // Pass the 'edited' message back request.setAttribute("edited", "true"); - + // Show edit page JSPManager.showJSP(request, response, "/dspace-admin/license-edit.jsp"); } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/NewsEditServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/NewsEditServlet.java index e2f3fb32a61754ee1a70b1e2600da1e1f613158a..513cc845297cba2e92475bea58f349e6f0938bfd 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/NewsEditServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/NewsEditServlet.java @@ -20,10 +20,11 @@ import org.dspace.app.webui.util.UIUtil; import org.dspace.authorize.AuthorizeException; import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; +import org.dspace.core.NewsManager; /** * Servlet for editing the front page news - * + * * @author gcarpent */ public class NewsEditServlet extends DSpaceServlet @@ -47,11 +48,11 @@ public class NewsEditServlet extends DSpaceServlet //Are we editing the top news or the sidebar news? String position = request.getParameter("position"); - + if (button.equals("submit_edit")) { //get the existing text from the file - news = ConfigurationManager.readNewsFile(position); + news = NewsManager.readNewsFile(position); //pass the position back to the JSP request.setAttribute("position", position); @@ -69,7 +70,7 @@ public class NewsEditServlet extends DSpaceServlet news = (String) request.getParameter("news"); //write the string out to file - ConfigurationManager.writeNewsFile(position, news); + NewsManager.writeNewsFile(position, news); JSPManager .showJSP(request, response, "/dspace-admin/news-main.jsp"); diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/SuperviseServlet.java b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/SuperviseServlet.java index add8914fc88d20a521bd3ee7c836a81c46de676b..1b003af817501fd8ca13d53938390e6cd04aac96 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/SuperviseServlet.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/servlet/admin/SuperviseServlet.java @@ -141,9 +141,20 @@ public class SuperviseServlet extends org.dspace.app.webui.servlet.DSpaceServlet // set the attributes for the JSP request.setAttribute("groups",groups); request.setAttribute("wsItems",wsItems); - - JSPManager.showJSP(request, response, "/dspace-admin/supervise-link.jsp" ); - + + // set error message key when there is no workspace item + if (wsItems.length == 0) + { + request.setAttribute("errorKey", + "jsp.dspace-admin.supervise-no-workspaceitem.no-wsitems"); + JSPManager.showJSP(request, response, + "/dspace-admin/supervise-no-workspaceitem.jsp"); + + } + else + { + JSPManager.showJSP(request, response, "/dspace-admin/supervise-link.jsp" ); + } } /** @@ -269,6 +280,16 @@ public class SuperviseServlet extends org.dspace.app.webui.servlet.DSpaceServlet int groupID = UIUtil.getIntParameter(request,"TargetGroup"); int wsItemID = UIUtil.getIntParameter(request,"TargetWSItem"); + // set error message key when no workspace item is selected + if (wsItemID == -1) + { + request.setAttribute("errorKey", + "jsp.dspace-admin.supervise-no-workspaceitem.unselected"); + JSPManager.showJSP(request, response, + "/dspace-admin/supervise-no-workspaceitem.jsp" ); + return false; + } + boolean invalid = Supervisor.isOrder(context, wsItemID, groupID); if (invalid) diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/JSPStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/JSPStep.java index 73daa3b7d737652a5bd573c4337910a5cce2f682..456eaac293938482e08df48146d49d6713896edf 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/JSPStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/JSPStep.java @@ -36,9 +36,9 @@ import org.dspace.core.Context; * <li>If showJSP() was specified from doPreProcessing(), then the JSP * specified will be displayed</li> * <li>If showJSP() was not specified from doPreProcessing(), then the - * doProcessing() method is called an the step completes immediately</li> - * <li>Call doProcessing() method on appropriate AbstractProcessingStep after the user returns from the JSP, in order - * to process the user input</li> + * doProcessing() method is called and the step completes immediately</li> + * <li>Call doProcessing() method on appropriate AbstractProcessingStep after + * the user returns from the JSP, in order to process the user input</li> * <li>Call doPostProcessing() method to determine if more user interaction is * required, and if further JSPs need to be called.</li> * <li>If there are more "pages" in this step then, the process begins again diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPCCLicenseStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPCCLicenseStep.java index 93ad9e6c4745e3d6b2dd470779449a69318e5892..276099fac6d0c188a9ba4bf745dcdbdae331802d 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPCCLicenseStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPCCLicenseStep.java @@ -42,9 +42,9 @@ import java.sql.SQLException; * <li>If showJSP() was specified from doPreProcessing(), then the JSP * specified will be displayed</li> * <li>If showJSP() was not specified from doPreProcessing(), then the - * doProcessing() method is called an the step completes immediately</li> - * <li>Call doProcessing() method on appropriate AbstractProcessingStep after the user returns from the JSP, in order - * to process the user input</li> + * doProcessing() method is called and the step completes immediately</li> + * <li>Call doProcessing() method on appropriate AbstractProcessingStep after + * the user returns from the JSP, in order to process the user input</li> * <li>Call doPostProcessing() method to determine if more user interaction is * required, and if further JSPs need to be called.</li> * <li>If there are more "pages" in this step then, the process begins again diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPDescribeStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPDescribeStep.java index 86b14fe80ad3ee6289815073b90038357d968bc0..f367852eb218ebcbbb663cfa9ab6fadc007993e7 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPDescribeStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPDescribeStep.java @@ -45,9 +45,9 @@ import org.dspace.submit.step.DescribeStep; * <li>If showJSP() was specified from doPreProcessing(), then the JSP * specified will be displayed</li> * <li>If showJSP() was not specified from doPreProcessing(), then the - * doProcessing() method is called an the step completes immediately</li> - * <li>Call doProcessing() method on appropriate AbstractProcessingStep after the user returns from the JSP, in order - * to process the user input</li> + * doProcessing() method is called and the step completes immediately</li> + * <li>Call doProcessing() method on appropriate AbstractProcessingStep after + * the user returns from the JSP, in order to process the user input</li> * <li>Call doPostProcessing() method to determine if more user interaction is * required, and if further JSPs need to be called.</li> * <li>If there are more "pages" in this step then, the process begins again diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPInitialQuestionsStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPInitialQuestionsStep.java index 64f39a302e6fb5263f9458443f427f5f20395d09..7a775366b4cba118ee534aad6fafe8d6e54286da 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPInitialQuestionsStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPInitialQuestionsStep.java @@ -39,9 +39,9 @@ import org.dspace.submit.step.InitialQuestionsStep; * <li>If showJSP() was specified from doPreProcessing(), then the JSP * specified will be displayed</li> * <li>If showJSP() was not specified from doPreProcessing(), then the - * doProcessing() method is called an the step completes immediately</li> - * <li>Call doProcessing() method on appropriate AbstractProcessingStep after the user returns from the JSP, in order - * to process the user input</li> + * doProcessing() method is called and the step completes immediately</li> + * <li>Call doProcessing() method on appropriate AbstractProcessingStep after + * the user returns from the JSP, in order to process the user input</li> * <li>Call doPostProcessing() method to determine if more user interaction is * required, and if further JSPs need to be called.</li> * <li>If there are more "pages" in this step then, the process begins again diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPLicenseStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPLicenseStep.java index 536c232513dc081e69277205ca5d5cd91b2b6ea9..0c022921f08de72a228a61586beb0e586c26ed12 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPLicenseStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPLicenseStep.java @@ -44,9 +44,9 @@ import org.dspace.submit.step.LicenseStep; * <li>If showJSP() was specified from doPreProcessing(), then the JSP * specified will be displayed</li> * <li>If showJSP() was not specified from doPreProcessing(), then the - * doProcessing() method is called an the step completes immediately</li> - * <li>Call doProcessing() method on appropriate AbstractProcessingStep after the user returns from the JSP, in order - * to process the user input</li> + * doProcessing() method is called and the step completes immediately</li> + * <li>Call doProcessing() method on appropriate AbstractProcessingStep after + * the user returns from the JSP, in order to process the user input</li> * <li>Call doPostProcessing() method to determine if more user interaction is * required, and if further JSPs need to be called.</li> * <li>If there are more "pages" in this step then, the process begins again diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPSampleStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPSampleStep.java index 4ba4c4a7b29ddfe642108af3b3751ee22ff0f636..3f66c2a15e7672cc94a8ff3d8207e2dd9b074275 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPSampleStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPSampleStep.java @@ -50,9 +50,9 @@ import org.dspace.submit.step.SampleStep; * <li>If showJSP() was specified from doPreProcessing(), then the JSP * specified will be displayed</li> * <li>If showJSP() was not specified from doPreProcessing(), then the - * doProcessing() method is called an the step completes immediately</li> - * <li>Call doProcessing() method on appropriate AbstractProcessingStep after the user returns from the JSP, in order - * to process the user input</li> + * doProcessing() method is called and the step completes immediately</li> + * <li>Call doProcessing() method on appropriate AbstractProcessingStep after + * the user returns from the JSP, in order to process the user input</li> * <li>Call doPostProcessing() method to determine if more user interaction is * required, and if further JSPs need to be called.</li> * <li>If there are more "pages" in this step then, the process begins again diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPSelectCollectionStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPSelectCollectionStep.java index ced0d9bce4b0506dd95357d019ff71227e470b4e..91c5b9c265d40f0da5af4c87a752b6ddcaa5dd25 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPSelectCollectionStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPSelectCollectionStep.java @@ -41,9 +41,9 @@ import org.dspace.submit.step.SelectCollectionStep; * <li>If showJSP() was specified from doPreProcessing(), then the JSP * specified will be displayed</li> * <li>If showJSP() was not specified from doPreProcessing(), then the - * doProcessing() method is called an the step completes immediately</li> - * <li>Call doProcessing() method on appropriate AbstractProcessingStep after the user returns from the JSP, in order - * to process the user input</li> + * doProcessing() method is called and the step completes immediately</li> + * <li>Call doProcessing() method on appropriate AbstractProcessingStep after + * the user returns from the JSP, in order to process the user input</li> * <li>Call doPostProcessing() method to determine if more user interaction is * required, and if further JSPs need to be called.</li> * <li>If there are more "pages" in this step then, the process begins again diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadStep.java index 604b5dc3f0852e73c2ce2d60dedb06ae6427e9a6..685bcab2d5323cb46222e977eb75768f76828f16 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPUploadStep.java @@ -9,17 +9,22 @@ package org.dspace.app.webui.submit.step; import java.io.IOException; import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; +import org.dspace.app.sherpa.submit.SHERPASubmitService; import org.dspace.app.util.DCInputsReader; import org.dspace.app.util.DCInputsReaderException; import org.dspace.app.util.SubmissionInfo; +import org.dspace.app.webui.servlet.SubmissionController; import org.dspace.app.webui.submit.JSPStep; import org.dspace.app.webui.submit.JSPStepManager; +import org.dspace.app.webui.util.JSONUploadResponse; import org.dspace.app.webui.util.JSPManager; import org.dspace.app.webui.util.UIUtil; import org.dspace.authorize.AuthorizeException; @@ -32,6 +37,11 @@ import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.dspace.submit.step.UploadStep; +import org.dspace.utils.DSpace; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; /** * Upload step for DSpace JSP-UI. Handles the pages that revolve around uploading files @@ -46,9 +56,9 @@ import org.dspace.submit.step.UploadStep; * <li>If showJSP() was specified from doPreProcessing(), then the JSP * specified will be displayed</li> * <li>If showJSP() was not specified from doPreProcessing(), then the - * doProcessing() method is called an the step completes immediately</li> - * <li>Call doProcessing() method on appropriate AbstractProcessingStep after the user returns from the JSP, in order - * to process the user input</li> + * doProcessing() method is called and the step completes immediately</li> + * <li>Call doProcessing() method on appropriate AbstractProcessingStep after + * the user returns from the JSP, in order to process the user input</li> * <li>Call doPostProcessing() method to determine if more user interaction is * required, and if further JSPs need to be called.</li> * <li>If there are more "pages" in this step then, the process begins again @@ -82,13 +92,13 @@ public class JSPUploadStep extends JSPStep private static final String FILE_FORMAT_JSP = "/submit/get-file-format.jsp"; /** JSP to show any upload errors * */ - private static final String UPLOAD_ERROR_JSP = "/submit/upload-error.jsp"; + protected static final String UPLOAD_ERROR_JSP = "/submit/upload-error.jsp"; /** JSP to show any upload errors * */ - private static final String VIRUS_CHECKER_ERROR_JSP = "/submit/virus-checker-error.jsp"; + protected static final String VIRUS_CHECKER_ERROR_JSP = "/submit/virus-checker-error.jsp"; /** JSP to show any upload errors * */ - private static final String VIRUS_ERROR_JSP = "/submit/virus-error.jsp"; + protected static final String VIRUS_ERROR_JSP = "/submit/virus-error.jsp"; /** JSP to review uploaded files * */ private static final String REVIEW_JSP = "/submit/review-upload.jsp"; @@ -181,6 +191,34 @@ public class JSPUploadStep extends JSPStep // Do we need to skip the upload entirely? boolean fileRequired = ConfigurationManager.getBooleanProperty("webui.submit.upload.required", true); + + if (UIUtil.getBoolParameter(request, "ajaxUpload")) + { + Gson gson = new Gson(); + // old browser need to see this response as html to work + response.setContentType("text/html"); + JSONUploadResponse jsonResponse = new JSONUploadResponse(); + String bitstreamName = null; + int bitstreamID = -1; + long size = 0; + String url = null; + if (subInfo.getBitstream() != null) + { + Bitstream bitstream = subInfo.getBitstream(); + bitstreamName = bitstream.getName(); + bitstreamID = bitstream.getID(); + size = bitstream.getSize(); + url = request.getContextPath() + "/retrieve/" + bitstreamID + + "/" + UIUtil.encodeBitstreamName(bitstreamName); + } + jsonResponse.addUploadFileStatus(bitstreamName, bitstreamID, size, + url, status); + response.getWriter().print(gson.toJson(jsonResponse)); + response.flushBuffer(); + return; + } + + if (buttonPressed.equalsIgnoreCase(UploadStep.SUBMIT_SKIP_BUTTON) || (buttonPressed.equalsIgnoreCase(UploadStep.SUBMIT_UPLOAD_BUTTON) && !fileRequired)) { @@ -424,7 +462,7 @@ public class JSPUploadStep extends JSPStep * @param justUploaded * true, if the user just finished uploading a file */ - private void showUploadPage(Context context, HttpServletRequest request, + protected void showUploadPage(Context context, HttpServletRequest request, HttpServletResponse response, SubmissionInfo subInfo, boolean justUploaded) throws SQLException, ServletException, IOException @@ -472,15 +510,28 @@ public class JSPUploadStep extends JSPStep * @param subInfo * the SubmissionInfo object */ - private void showChooseFile(Context context, HttpServletRequest request, + protected void showChooseFile(Context context, HttpServletRequest request, HttpServletResponse response, SubmissionInfo subInfo) throws SQLException, ServletException, IOException { + if (ConfigurationManager.getBooleanProperty( + "webui.submission.sherparomeo-policy-enabled", true)) + { + SHERPASubmitService sherpaSubmitService = new DSpace() + .getSingletonService(SHERPASubmitService.class); + request.setAttribute("sherpa", sherpaSubmitService + .hasISSNs(context, subInfo.getSubmissionItem() + .getItem())); + } // set to null the bitstream in subInfo, we need to process a new file // we don't need any info about previous files... subInfo.setBitstream(null); - + + // set a flag whether the current step is UploadWithEmbargoStep + boolean withEmbargo = SubmissionController.getCurrentStepConfig(request, subInfo).getProcessingClassName().equals("org.dspace.submit.step.UploadWithEmbargoStep") ? true : false; + request.setAttribute("with_embargo", Boolean.valueOf(withEmbargo)); + // load JSP which allows the user to select a file to upload JSPStepManager.showJSP(request, response, subInfo, CHOOSE_FILE_JSP); } @@ -501,7 +552,7 @@ public class JSPUploadStep extends JSPStep * @param showChecksums * pass in true if checksums should be displayed */ - private void showUploadFileList(Context context, + protected void showUploadFileList(Context context, HttpServletRequest request, HttpServletResponse response, SubmissionInfo subInfo, boolean justUploaded, boolean showChecksums) throws SQLException, ServletException, IOException @@ -510,6 +561,10 @@ public class JSPUploadStep extends JSPStep request.setAttribute("just.uploaded", Boolean.valueOf(justUploaded)); request.setAttribute("show.checksums", Boolean.valueOf(showChecksums)); + // set a flag whether the current step is UploadWithEmbargoStep + boolean withEmbargo = SubmissionController.getCurrentStepConfig(request, subInfo).getProcessingClassName().equals("org.dspace.submit.step.UploadWithEmbargoStep") ? true : false; + request.setAttribute("with_embargo", Boolean.valueOf(withEmbargo)); + // Always go to advanced view in workflow mode if (subInfo.isInWorkflow() || subInfo.getSubmissionItem().hasMultipleFiles()) @@ -537,7 +592,7 @@ public class JSPUploadStep extends JSPStep * @param subInfo * the SubmissionInfo object */ - private void showGetFileFormat(Context context, HttpServletRequest request, + protected void showGetFileFormat(Context context, HttpServletRequest request, HttpServletResponse response, SubmissionInfo subInfo) throws SQLException, ServletException, IOException { @@ -577,7 +632,7 @@ public class JSPUploadStep extends JSPStep * @param subInfo * the SubmissionInfo object */ - private void showFileDescription(Context context, + protected void showFileDescription(Context context, HttpServletRequest request, HttpServletResponse response, SubmissionInfo subInfo) throws SQLException, ServletException, IOException diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPVerifyStep.java b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPVerifyStep.java index 22329a32ee936bcae7e2f425a4c4775427a65137..275c4495bf44c369527743b213d1ad9709b2835e 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPVerifyStep.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/submit/step/JSPVerifyStep.java @@ -44,9 +44,9 @@ import org.dspace.core.LogManager; * <li>If showJSP() was specified from doPreProcessing(), then the JSP * specified will be displayed</li> * <li>If showJSP() was not specified from doPreProcessing(), then the - * doProcessing() method is called an the step completes immediately</li> - * <li>Call doProcessing() method after the user returns from the JSP, in order - * to process the user input</li> + * doProcessing() method is called and the step completes immediately</li> + * <li>Call doProcessing() method on appropriate AbstractProcessingStep after + * the user returns from the JSP, in order to process the user input</li> * <li>Call doPostProcessing() method to determine if more user interaction is * required, and if further JSPs need to be called.</li> * <li>If there are more "pages" in this step then, the process begins again diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/util/Authenticate.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/Authenticate.java index 7f6d16515c20f4d02feb80aa09a2cc30c75bd507..6a1727ad71fc251efbb35fb7c9a6af67313623c2 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/util/Authenticate.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/Authenticate.java @@ -308,8 +308,9 @@ public class Authenticate * DSpace context * @param request * HTTP request + * @throws SQLException */ - public static void loggedOut(Context context, HttpServletRequest request) + public static void loggedOut(Context context, HttpServletRequest request) throws SQLException { HttpSession session = request.getSession(); @@ -318,20 +319,29 @@ public class Authenticate request.removeAttribute("dspace.current.user"); session.removeAttribute("dspace.current.user.id"); + Integer previousUserID = (Integer) session.getAttribute("dspace.previous.user.id"); + // Keep the user's locale setting if set Locale sessionLocale = UIUtil.getSessionLocale(request); - // Invalidate session unless dspace.cfg says not to - if(ConfigurationManager.getBooleanProperty("webui.session.invalidate", true)) + // Invalidate session unless dspace.cfg says not to (or it is a loggedOut from a loginAs) + if(ConfigurationManager.getBooleanProperty("webui.session.invalidate", true) + && previousUserID != null) { session.invalidate(); } - // Restore the session locale if (sessionLocale != null) { Config.set(request.getSession(), Config.FMT_LOCALE, sessionLocale); } + + if (previousUserID != null) + { + session.removeAttribute("dspace.previous.user.id"); + EPerson ePerson = EPerson.find(context, previousUserID); + loggedIn(context, request, ePerson); + } } } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/util/FileUploadRequest.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/FileUploadRequest.java index 16a818f9fe3671c47705e4a15d48f68203961b24..75a48e7ca06f38ffc9aa1a5c44dfda3a1028aad8 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/util/FileUploadRequest.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/FileUploadRequest.java @@ -13,6 +13,7 @@ import java.util.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; +import javax.servlet.http.HttpSession; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException; @@ -31,6 +32,8 @@ import org.dspace.core.ConfigurationManager; */ public class FileUploadRequest extends HttpServletRequestWrapper { + public static final String FILE_UPLOAD_LISTNER = "file-upload-listner"; + private Map<String, String> parameters = new HashMap<String, String>(); private Map<String, FileItem> fileitems = new HashMap<String, FileItem>(); @@ -54,7 +57,8 @@ public class FileUploadRequest extends HttpServletRequestWrapper original = req; - tempDir = ConfigurationManager.getProperty("upload.temp.dir"); + tempDir = (ConfigurationManager.getProperty("upload.temp.dir") != null) + ? ConfigurationManager.getProperty("upload.temp.dir") : System.getProperty("java.io.tmpdir"); long maxSize = ConfigurationManager.getLongProperty("upload.max"); // Create a factory for disk-based file items @@ -63,6 +67,19 @@ public class FileUploadRequest extends HttpServletRequestWrapper // Create a new file upload handler ServletFileUpload upload = new ServletFileUpload(factory); + + HttpSession session = req.getSession(); + + if (ConfigurationManager.getBooleanProperty("webui.submit.upload.progressbar", true)) + { + // set file upload progress listener + FileUploadListener listener = new FileUploadListener(); + + session.setAttribute(FILE_UPLOAD_LISTNER, listener); + + // upload servlet allows to set upload listener + upload.setProgressListener(listener); + } try { @@ -103,6 +120,13 @@ public class FileUploadRequest extends HttpServletRequestWrapper } throw new IOException(e.getMessage(), e); } + finally + { + if (ConfigurationManager.getBooleanProperty("webui.submit.upload.progressbar", true)) + { + session.removeAttribute(FILE_UPLOAD_LISTNER); + } + } } // Methods to replace HSR methods @@ -194,4 +218,4 @@ public class FileUploadRequest extends HttpServletRequestWrapper } return filename; } -} \ No newline at end of file +} diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/util/UIUtil.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/UIUtil.java index dbd518f44767350a32fc196f32987157dc0d3f40..a83cb46cfccfaf302f7b71d3f5911c81ca54a993 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/util/UIUtil.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/UIUtil.java @@ -40,7 +40,7 @@ import org.dspace.eperson.EPerson; /** * Miscellaneous UI utility methods - * + * * @author Robert Tansley * @version $Revision$ */ @@ -51,7 +51,7 @@ public class UIUtil extends Util /** log4j category */ public static final Logger log = Logger.getLogger(UIUtil.class); - + /** * Pattern used to get file.ext from filename (which can be a path) */ @@ -62,20 +62,20 @@ public class UIUtil extends Util * for this HTTP request, it is re-used, otherwise it is created. If a user * has authenticated with the system, the current user of the context is set * appropriately. - * + * * @param request * the HTTP request - * + * * @return a context object */ public static Context obtainContext(HttpServletRequest request) throws SQLException { - + //Set encoding to UTF-8, if not set yet //This avoids problems of using the HttpServletRequest - //in the getSpecialGroups() for an AuthenticationMethod, - //which causes the HttpServletRequest to default to + //in the getSpecialGroups() for an AuthenticationMethod, + //which causes the HttpServletRequest to default to //non-UTF-8 encoding. try { @@ -88,9 +88,9 @@ public class UIUtil extends Util { log.error("Unable to set encoding to UTF-8.", e); } - + Context c = (Context) request.getAttribute("dspace.context"); - + if (c == null) { @@ -149,7 +149,7 @@ public class UIUtil extends Util // Store the context in the request request.setAttribute("dspace.context", c); } - + // Set the locale to be used Locale sessionLocale = getSessionLocale(request); Config.set(request.getSession(), Config.FMT_LOCALE, sessionLocale); @@ -162,10 +162,10 @@ public class UIUtil extends Util * Get the current community location, that is, where the user "is". This * returns <code>null</code> if there is no location, i.e. "all of DSpace" * is the location. - * + * * @param request * current HTTP request - * + * * @return the current community location, or null */ public static Community getCommunityLocation(HttpServletRequest request) @@ -177,10 +177,10 @@ public class UIUtil extends Util * Get the current collection location, that is, where the user "is". This * returns null if there is no collection location, i.e. the location is * "all of DSpace" or a community. - * + * * @param request * current HTTP request - * + * * @return the current collection location, or null */ public static Collection getCollectionLocation(HttpServletRequest request) @@ -193,7 +193,7 @@ public class UIUtil extends Util * later use. This is necessary because forwarding a request removes this * information. The attribute is only written if it hasn't been before; thus * it can be called after a forward safely. - * + * * @param request * the HTTP request */ @@ -216,10 +216,10 @@ public class UIUtil extends Util /** * Get the original request URL. - * + * * @param request * the HTTP request - * + * * @return the original request URL */ public static String getOriginalURL(HttpServletRequest request) @@ -232,7 +232,7 @@ public class UIUtil extends Util /** * Write a human-readable version of a DCDate. - * + * * @param d * the date * @param time @@ -240,8 +240,8 @@ public class UIUtil extends Util * @param localTime * if true, adjust for local timezone, otherwise GMT * @param request - * the servlet request - * + * the servlet request + * * @return the date in a human-readable form. */ public static String displayDate(DCDate d, boolean time, boolean localTime, HttpServletRequest request) @@ -252,7 +252,7 @@ public class UIUtil extends Util /** * Return a string for logging, containing useful information about the * current request - the URL, the method and parameters. - * + * * @param request * the request object. * @return a multi-line string containing information about the request. @@ -288,15 +288,15 @@ public class UIUtil extends Util return report.toString(); } - - + + /** * Get the Locale for a session according to the user's language selection or language preferences. * Order of selection * - language selected via UI * - language as set by application * - language browser default - * + * * @param request * the request Object * @return supportedLocale @@ -314,8 +314,8 @@ public class UIUtil extends Util /* get session locale according to user selection */ sessionLocale = new Locale(paramLocale); } - - + + if (sessionLocale == null) { /* get session locale set by application */ @@ -331,17 +331,17 @@ public class UIUtil extends Util { sessionLocale = request.getLocale(); } - + if (sessionLocale == null) { sessionLocale = I18nUtil.DEFAULTLOCALE; } supportedLocale = I18nUtil.getSupportedLocale(sessionLocale); - + return supportedLocale; - } + } + - /** * Send an alert to the designated "alert recipient" - that is, when a * database error or internal error occurs, this person is sent an e-mail @@ -354,7 +354,7 @@ public class UIUtil extends Util * This method "swallows" any exception that might occur - it will just be * logged. This is because this method will usually be invoked as part of an * error handling routine anyway. - * + * * @param request * the HTTP request leading to the error * @param exception @@ -372,9 +372,9 @@ public class UIUtil extends Util String recipient = ConfigurationManager .getProperty("alert.recipient"); - if (recipient != null) + if (StringUtils.isNotBlank(recipient)) { - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(locale, "internal_error")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(locale, "internal_error")); email.addRecipient(recipient); email.addArgument(ConfigurationManager .getProperty("dspace.url")); @@ -406,7 +406,7 @@ public class UIUtil extends Util { log.warn("No context, the database might be down or the connection pool exhausted."); } - + if (user != null) { email.addArgument(user.getFullName() + " (" + user.getEmail() + ")"); @@ -425,10 +425,10 @@ public class UIUtil extends Util log.warn("Unable to send email alert", e); } } - + /** * Evaluate filename and client and encode appropriate disposition - * + * * @param filename * @param request * @param response @@ -437,31 +437,31 @@ public class UIUtil extends Util public static void setBitstreamDisposition(String filename, HttpServletRequest request, HttpServletResponse response) { - + String name = filename; - + Matcher m = p.matcher(name); - + if (m.find() && !m.group().equals("")) { name = m.group(); } - try + try { String agent = request.getHeader("USER-AGENT"); - if (null != agent && -1 != agent.indexOf("MSIE")) + if (null != agent && -1 != agent.indexOf("MSIE")) { name = URLEncoder.encode(name, "UTF8"); - } - else if (null != agent && -1 != agent.indexOf("Mozilla")) + } + else if (null != agent && -1 != agent.indexOf("Mozilla")) { name = MimeUtility.encodeText(name, "UTF8", "B"); - } + } - } - catch (UnsupportedEncodingException e) + } + catch (UnsupportedEncodingException e) { log.error(e.getMessage(),e); } diff --git a/dspace-jspui/src/main/java/org/dspace/app/webui/util/XMLUtil.java b/dspace-jspui/src/main/java/org/dspace/app/webui/util/XMLUtil.java index 0d885fc4636cc05367264c3e60af73d8c8fc2e36..2a453a6abc5fcf227aad00cd6388de7237885c55 100644 --- a/dspace-jspui/src/main/java/org/dspace/app/webui/util/XMLUtil.java +++ b/dspace-jspui/src/main/java/org/dspace/app/webui/util/XMLUtil.java @@ -100,7 +100,7 @@ public class XMLUtil } - // Create an empy DOMResult object for the output. + // Create an empty DOMResult object for the output. DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); dFactory.setNamespaceAware(true); DocumentBuilder dBuilder = dFactory.newDocumentBuilder(); diff --git a/dspace-jspui/src/main/webapp/WEB-INF/dspace-tags.tld b/dspace-jspui/src/main/webapp/WEB-INF/dspace-tags.tld index ecbd1abda7c9c4397c0743912e74f486bdbe8a4f..a300a3b8606e07cf2de16db44b138d839c11b62d 100644 --- a/dspace-jspui/src/main/webapp/WEB-INF/dspace-tags.tld +++ b/dspace-jspui/src/main/webapp/WEB-INF/dspace-tags.tld @@ -19,7 +19,7 @@ <taglib> <tlibversion>1.0</tlibversion> - <jspversion>1.1</jspversion> + <jspversion>2.0</jspversion> <shortname>dspace</shortname> <uri>http://www.dspace.org/dspace-tags.tld</uri> <info>DSpace JSP tags</info> @@ -446,5 +446,79 @@ </attribute> </tag> + <tag> + <name>access-setting</name> + <tagclass>org.dspace.app.webui.jsptag.AccessSettingTag</tagclass> + <bodycontent>empty</bodycontent> + <info> + Tag for display access setting elements. The "subInfo" is the SubmissionInfo + to get an array of group that can be set as a target of the resource policy. + The "dso" is the DSpaceObject that the access settings target to. The "rp" is + the resource policy. If the target is a specific resource policy, you must set + "rp", othewise you must set "dso". The resource policy setting fields are are + not display if "embargo" is true. The embargo date and reason are set as hidden + fields if "hidden" is true. The "confirm and add policy" button is dislay + if "addpolicy" is true; + </info> + + <attribute> + <name>subInfo</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>dso</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>rp</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + + <attribute> + <name>embargo</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>hidden</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>addpolicy</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + </tag> + + <tag> + <name>policieslist</name> + <tagclass>org.dspace.app.webui.jsptag.PoliciesListTag</tagclass> + <bodycontent>empty</bodycontent> + <info> + Tag for display policies list. The "policies" is an list of policies. + </info> + + <attribute> + <name>policies</name> + <required>true</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + <attribute> + <name>showButton</name> + <required>false</required> + <rtexprvalue>true</rtexprvalue> + </attribute> + + </tag> </taglib> diff --git a/dspace-jspui/src/main/webapp/WEB-INF/web.xml b/dspace-jspui/src/main/webapp/WEB-INF/web.xml index 9791717b155a5ba06e2dd083dbac5ffcceb5c765..b7000e20e6a642023ab7812f933590bf8396bfc3 100644 --- a/dspace-jspui/src/main/webapp/WEB-INF/web.xml +++ b/dspace-jspui/src/main/webapp/WEB-INF/web.xml @@ -229,6 +229,11 @@ <servlet-class>org.dspace.app.webui.servlet.admin.GroupListServlet</servlet-class> </servlet> + <servlet> + <servlet-name>curate</servlet-name> + <servlet-class>org.dspace.app.webui.servlet.admin.CurateServlet</servlet-class> + </servlet> + <servlet> <servlet-name>feed</servlet-name> <servlet-class>org.dspace.app.webui.servlet.FeedServlet</servlet-class> @@ -292,6 +297,11 @@ <servlet-class>org.dspace.app.webui.servlet.MetadataImportServlet</servlet-class> </servlet> + <servlet> + <servlet-name>batchmetadataimport</servlet-name> + <servlet-class>org.dspace.app.webui.servlet.BatchMetadataImportServlet</servlet-class> + </servlet> + <servlet> <servlet-name>metadata-field-registry</servlet-name> <servlet-class>org.dspace.app.webui.servlet.admin.MetadataFieldRegistryServlet</servlet-class> @@ -425,6 +435,11 @@ <servlet-class>org.dspace.app.webui.servlet.AuthorityChooseServlet</servlet-class> </servlet> + <servlet> + <servlet-name>sherpapolicy</servlet-name> + <servlet-class>org.dspace.app.webui.servlet.SHERPAPublisherPolicyServlet</servlet-class> + </servlet> + <servlet> <servlet-name>SearchResultLogServlet</servlet-name> <servlet-class>org.dspace.app.webui.servlet.SearchResultLogServlet</servlet-class> @@ -440,13 +455,32 @@ <servlet-name>json</servlet-name> <servlet-class>org.dspace.app.webui.servlet.JSONServlet</servlet-class> </servlet> - + + <servlet> + <servlet-name>privateitems</servlet-name> + <servlet-class>org.dspace.app.webui.servlet.admin.PrivateItemsServlet</servlet-class> + </servlet> + + <servlet> + <servlet-name>version-item</servlet-name> + <servlet-class>org.dspace.app.webui.servlet.VersionItemServlet</servlet-class> + </servlet> + + <servlet> + <servlet-name>version-history</servlet-name> + <servlet-class>org.dspace.app.webui.servlet.VersionHistoryServlet</servlet-class> + </servlet> + + <servlet> + <servlet-name>request-item</servlet-name> + <servlet-class>org.dspace.app.webui.servlet.RequestItemServlet</servlet-class> + </servlet> + <servlet-mapping> <servlet-name>shibboleth-login</servlet-name> <url-pattern>/shibboleth-login</url-pattern> </servlet-mapping> - <!-- Servlet Mappings --> <servlet-mapping> @@ -529,6 +563,16 @@ <url-pattern>/tools/group-select-list</url-pattern> </servlet-mapping> + <servlet-mapping> + <servlet-name>curate</servlet-name> + <url-pattern>/dspace-admin/curate</url-pattern> + </servlet-mapping> + + <servlet-mapping> + <servlet-name>curate</servlet-name> + <url-pattern>/tools/curate</url-pattern> + </servlet-mapping> + <servlet-mapping> <servlet-name>itemmap</servlet-name> <url-pattern>/tools/itemmap</url-pattern> @@ -594,6 +638,11 @@ <url-pattern>/dspace-admin/metadataimport</url-pattern> </servlet-mapping> + <servlet-mapping> + <servlet-name>batchmetadataimport</servlet-name> + <url-pattern>/dspace-admin/batchmetadataimport</url-pattern> + </servlet-mapping> + <servlet-mapping> <servlet-name>metadata-field-registry</servlet-name> <url-pattern>/dspace-admin/metadata-field-registry</url-pattern> @@ -718,7 +767,12 @@ <servlet-name>AuthorityChooseServlet</servlet-name> <url-pattern>/choices/*</url-pattern> </servlet-mapping> - + + <servlet-mapping> + <servlet-name>sherpapolicy</servlet-name> + <url-pattern>/tools/sherpaPolicy</url-pattern> + </servlet-mapping> + <servlet-mapping> <servlet-name>json</servlet-name> <url-pattern>/json/*</url-pattern> @@ -729,6 +783,26 @@ <url-pattern>/dso-display</url-pattern> </servlet-mapping> + <servlet-mapping> + <servlet-name>privateitems</servlet-name> + <url-pattern>/dspace-admin/privateitems</url-pattern> + </servlet-mapping> + + <servlet-mapping> + <servlet-name>version-item</servlet-name> + <url-pattern>/tools/version</url-pattern> + </servlet-mapping> + + <servlet-mapping> + <servlet-name>version-history</servlet-name> + <url-pattern>/tools/history</url-pattern> + </servlet-mapping> + + <servlet-mapping> + <servlet-name>request-item</servlet-name> + <url-pattern>/request-item</url-pattern> + </servlet-mapping> + <!-- Icon MIME type --> <mime-mapping> <extension>ico</extension> diff --git a/dspace-jspui/src/main/webapp/browse/full.jsp b/dspace-jspui/src/main/webapp/browse/full.jsp index 5567cf3e5fd92a29ede46227d3c1a1ee71578ede..788c57b4b499285d2f9fcc0174a7c964627717dd 100644 --- a/dspace-jspui/src/main/webapp/browse/full.jsp +++ b/dspace-jspui/src/main/webapp/browse/full.jsp @@ -33,12 +33,19 @@ String urlFragment = "browse"; String layoutNavbar = "default"; boolean withdrawn = false; + boolean privateitems = false; if (request.getAttribute("browseWithdrawn") != null) { layoutNavbar = "admin"; urlFragment = "dspace-admin/withdrawn"; withdrawn = true; } + else if (request.getAttribute("browsePrivate") != null) + { + layoutNavbar = "admin"; + urlFragment = "dspace-admin/privateitems"; + privateitems = true; + } // First, get the browse info object BrowseInfo bi = (BrowseInfo) request.getAttribute("browse.info"); @@ -103,18 +110,18 @@ String valueString = ""; if (value!=null) { - valueString = "&" + argument + "=" + URLEncoder.encode(value); + valueString = "&" + argument + "=" + URLEncoder.encode(value, "UTF-8"); } String sharedLink = linkBase + urlFragment + "?"; if (bix.getName() != null) - sharedLink += "type=" + URLEncoder.encode(bix.getName()); + sharedLink += "type=" + URLEncoder.encode(bix.getName(), "UTF-8"); - sharedLink += "&sort_by=" + URLEncoder.encode(Integer.toString(so.getNumber())) + - "&order=" + URLEncoder.encode(direction) + - "&rpp=" + URLEncoder.encode(Integer.toString(bi.getResultsPerPage())) + - "&etal=" + URLEncoder.encode(Integer.toString(bi.getEtAl())) + + sharedLink += "&sort_by=" + URLEncoder.encode(Integer.toString(so.getNumber()), "UTF-8") + + "&order=" + URLEncoder.encode(direction, "UTF-8") + + "&rpp=" + URLEncoder.encode(Integer.toString(bi.getResultsPerPage()), "UTF-8") + + "&etal=" + URLEncoder.encode(Integer.toString(bi.getEtAl()), "UTF-8") + valueString; String next = sharedLink; @@ -175,7 +182,7 @@ <%-- Include the main navigation for all the browse pages --%> <%-- This first part is where we render the standard bits required by both possibly navigations --%> - <div align="center" id="browse_navigation"> + <div id="browse_navigation" class="well text-center"> <form method="get" action="<%= formaction %>"> <input type="hidden" name="type" value="<%= bix.getName() %>"/> <input type="hidden" name="sort_by" value="<%= so.getNumber() %>"/> @@ -198,58 +205,40 @@ if (so.isDate() || (bix.isDate() && so.isDefault())) { %> - <table align="center" border="0" bgcolor="#CCCCCC" cellpadding="0" summary="Browsing by date"> - <tr> - <td> - <table border="0" bgcolor="#EEEEEE" cellpadding="2"> - <tr> - <td class="browseBar"> - <span class="browseBarLabel"><fmt:message key="browse.nav.date.jump"/> </span> - <select name="year"> - <option selected="selected" value="-1"><fmt:message key="browse.nav.year"/></option> + <span><fmt:message key="browse.nav.date.jump"/></span> + <select name="year"> + <option selected="selected" value="-1"><fmt:message key="browse.nav.year"/></option> <% int thisYear = DCDate.getCurrent().getYear(); for (int i = thisYear; i >= 1990; i--) { %> - <option><%= i %></option> + <option><%= i %></option> <% } %> - <option>1985</option> - <option>1980</option> - <option>1975</option> - <option>1970</option> - <option>1960</option> - <option>1950</option> - </select> - <select name="month"> - <option selected="selected" value="-1"><fmt:message key="browse.nav.month"/></option> + <option>1985</option> + <option>1980</option> + <option>1975</option> + <option>1970</option> + <option>1960</option> + <option>1950</option> + </select> + <select name="month"> + <option selected="selected" value="-1"><fmt:message key="browse.nav.month"/></option> <% for (int i = 1; i <= 12; i++) { %> - <option value="<%= i %>"><%= DCDate.getMonthName(i, UIUtil.getSessionLocale(request)) %></option> + <option value="<%= i %>"><%= DCDate.getMonthName(i, UIUtil.getSessionLocale(request)) %></option> <% } %> - </select> - </td> - <td class="browseBar" rowspan="2"> - <input type="submit" value="<fmt:message key="browse.nav.go"/>" /> - </td> - </tr> - <tr> - <%-- HACK: Shouldn't use align here --%> - <td class="browseBar" align="center"> - <span class="browseBarLabel"><fmt:message key="browse.nav.type-year"/></span> - <input type="text" name="starts_with" size="4" maxlength="4"/> - </td> - </tr> - </table> - </td> - </tr> - </table> + </select> + <input type="submit" class="btn btn-default" value="<fmt:message key="browse.nav.go"/>" /> + <br/> + <label for="starts_with"><fmt:message key="browse.nav.type-year"/></label> + <input type="text" name="starts_with" size="4" maxlength="4"/> <% } @@ -257,34 +246,18 @@ else { %> - <table align="center" border="0" bgcolor="#CCCCCC" cellpadding="0" summary="Browse the respository"> - <tr> - <td> - <table border="0" bgcolor="#EEEEEE" cellpadding="2"> - <tr> - <td class="browseBar"> - <span class="browseBarLabel"><fmt:message key="browse.nav.jump"/></span> - <a href="<%= sharedLink %>&starts_with=0">0-9</a> + <span><fmt:message key="browse.nav.jump"/></span> + <a class="label label-default" href="<%= sharedLink %>&starts_with=0">0-9</a> <% for (char c = 'A'; c <= 'Z'; c++) { %> - <a href="<%= sharedLink %>&starts_with=<%= c %>"><%= c %></a> + <a class="label label-default" href="<%= sharedLink %>&starts_with=<%= c %>"><%= c %></a> <% } -%> - </td> - </tr> - <tr> - <td class="browseBar" align="center"> - <span class="browseBarLabel"><fmt:message key="browse.nav.enter"/> </span> - <input type="text" name="starts_with"/> <input type="submit" value="<fmt:message key="browse.nav.go"/>" /> - </td> - </tr> - </table> - </td> - </tr> - </table> +%><br/> + <span><fmt:message key="browse.nav.enter"/></span> + <input type="text" name="starts_with"/> <input type="submit" class="btn btn-default" value="<fmt:message key="browse.nav.go"/>" /> <% } %> @@ -293,7 +266,7 @@ <%-- End of Navigation Headers --%> <%-- Include a component for modifying sort by, order, results per page, and et-al limit --%> - <div align="center" id="browse_controls"> + <div id="browse_controls" class="well text-center"> <form method="get" action="<%= formaction %>"> <input type="hidden" name="type" value="<%= bix.getName() %>"/> <% @@ -326,7 +299,7 @@ if (sortOptions.size() > 1) // && bi.getBrowseLevel() > 0 { %> - <fmt:message key="browse.full.sort-by"/> + <label for="sort_by"><fmt:message key="browse.full.sort-by"/></label> <select name="sort_by"> <% for (SortOption sortBy : sortOptions) @@ -343,14 +316,13 @@ <% } %> - - <fmt:message key="browse.full.order"/> + <label for="order"><fmt:message key="browse.full.order"/></label> <select name="order"> <option value="ASC" <%= ascSelected %>><fmt:message key="browse.order.asc" /></option> <option value="DESC" <%= descSelected %>><fmt:message key="browse.order.desc" /></option> </select> - - <fmt:message key="browse.full.rpp"/> + + <label for="rpp"><fmt:message key="browse.full.rpp"/></label> <select name="rpp"> <% for (int i = 5; i <= 100 ; i += 5) @@ -362,8 +334,8 @@ } %> </select> - - <fmt:message key="browse.full.etal" /> + + <label for="etal"><fmt:message key="browse.full.etal" /></label> <select name="etal"> <% String unlimitedSelect = ""; @@ -415,35 +387,33 @@ } %> </select> - - <input type="submit" name="submit_browse" value="<fmt:message key="jsp.general.update"/>"/> + + <input type="submit" class="btn btn-default" name="submit_browse" value="<fmt:message key="jsp.general.update"/>"/> <% - if (admin_button && !withdrawn) + if (admin_button && !withdrawn && !privateitems) { - %><input type="submit" name="submit_export_metadata" value="<fmt:message key="jsp.general.metadataexport.button"/>" /><% + %><input type="submit" class="btn btn-default" name="submit_export_metadata" value="<fmt:message key="jsp.general.metadataexport.button"/>" /><% } %> </form> </div> - +<div class="panel panel-primary"> <%-- give us the top report on what we are looking at --%> - <div align="center" class="browse_range"> + <div class="panel-heading text-center"> <fmt:message key="browse.full.range"> <fmt:param value="<%= Integer.toString(bi.getStart()) %>"/> <fmt:param value="<%= Integer.toString(bi.getFinish()) %>"/> <fmt:param value="<%= Integer.toString(bi.getTotal()) %>"/> </fmt:message> - </div> <%-- do the top previous and next page links --%> - <div align="center"> <% if (bi.hasPrevPage()) { %> - <a href="<%= prev %>"><fmt:message key="browse.full.prev"/></a> + <a class="pull-left" href="<%= prev %>"><fmt:message key="browse.full.prev"/></a> <% } %> @@ -452,7 +422,7 @@ if (bi.hasNextPage()) { %> - <a href="<%= next %>"><fmt:message key="browse.full.next"/></a> + <a class="pull-right" href="<%= next %>"><fmt:message key="browse.full.next"/></a> <% } %> @@ -466,7 +436,7 @@ <dspace:browselist browseInfo="<%= bi %>" emphcolumn="<%= bix.getMetadata() %>" /> <% } - else if (request.getAttribute("browseWithdrawn") != null) + else if (withdrawn || privateitems) { %> <dspace:browselist browseInfo="<%= bi %>" emphcolumn="<%= bix.getSortOption().getMetadata() %>" linkToEdit="true" disableCrossLinks="true" /> @@ -480,21 +450,19 @@ } %> <%-- give us the bottom report on what we are looking at --%> - <div align="center" class="browse_range"> + <div class="panel-footer text-center"> <fmt:message key="browse.full.range"> <fmt:param value="<%= Integer.toString(bi.getStart()) %>"/> <fmt:param value="<%= Integer.toString(bi.getFinish()) %>"/> <fmt:param value="<%= Integer.toString(bi.getTotal()) %>"/> </fmt:message> - </div> <%-- do the bottom previous and next page links --%> - <div align="center"> <% if (bi.hasPrevPage()) { %> - <a href="<%= prev %>"><fmt:message key="browse.full.prev"/></a> + <a class="pull-left" href="<%= prev %>"><fmt:message key="browse.full.prev"/></a> <% } %> @@ -503,44 +471,15 @@ if (bi.hasNextPage()) { %> - <a href="<%= next %>"><fmt:message key="browse.full.next"/></a> + <a class="pull-right" href="<%= next %>"><fmt:message key="browse.full.next"/></a> <% } %> </div> - +</div> <%-- dump the results for debug (uncomment to enable) --%> <%-- <!-- <%= bi.toString() %> --> --%> -</dspace:layout> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +</dspace:layout> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/browse/no-results.jsp b/dspace-jspui/src/main/webapp/browse/no-results.jsp index 9099326ec457f883376541f162b1946f7f5bfc94..9d25c41bb98309c8a1e8d6b5a02bfa5ec193b440 100644 --- a/dspace-jspui/src/main/webapp/browse/no-results.jsp +++ b/dspace-jspui/src/main/webapp/browse/no-results.jsp @@ -31,7 +31,7 @@ request.setAttribute("LanguageSwitch", "hide"); String layoutNavbar = "default"; - if (request.getAttribute("browseWithdrawn") != null) + if (request.getAttribute("browseWithdrawn") != null || request.getAttribute("browsePrivate") != null) { layoutNavbar = "admin"; } diff --git a/dspace-jspui/src/main/webapp/browse/single.jsp b/dspace-jspui/src/main/webapp/browse/single.jsp index 296c4001cc8e96887cc14d273649967f85d1baf8..45187ef2e2b29173e4621d31e61c9e82d91cca61 100644 --- a/dspace-jspui/src/main/webapp/browse/single.jsp +++ b/dspace-jspui/src/main/webapp/browse/single.jsp @@ -78,9 +78,9 @@ } String direction = (bi.isAscending() ? "ASC" : "DESC"); - String sharedLink = linkBase + "browse?type=" + URLEncoder.encode(bix.getName()) + - "&order=" + URLEncoder.encode(direction) + - "&rpp=" + URLEncoder.encode(Integer.toString(bi.getResultsPerPage())); + String sharedLink = linkBase + "browse?type=" + URLEncoder.encode(bix.getName(), "UTF-8") + + "&order=" + URLEncoder.encode(direction, "UTF-8") + + "&rpp=" + URLEncoder.encode(Integer.toString(bi.getResultsPerPage()), "UTF-8"); // prepare the next and previous links String next = sharedLink; @@ -125,7 +125,7 @@ <%-- Include the main navigation for all the browse pages --%> <%-- This first part is where we render the standard bits required by both possibly navigations --%> - <div align="center" id="browse_navigation"> + <div id="browse_navigation" class="well text-center"> <form method="get" action="<%= formaction %>"> <input type="hidden" name="type" value="<%= bix.getName() %>"/> <input type="hidden" name="order" value="<%= direction %>"/> @@ -136,58 +136,40 @@ if (bix.isDate()) { %> - <table align="center" border="0" bgcolor="#CCCCCC" cellpadding="0" summary="Browsing by date"> - <tr> - <td> - <table border="0" bgcolor="#EEEEEE" cellpadding="2"> - <tr> - <td class="browseBar"> - <span class="browseBarLabel"><fmt:message key="browse.nav.date.jump"/> </span> - <select name="year"> - <option selected="selected" value="-1"><fmt:message key="browse.nav.year"/></option> + <span><fmt:message key="browse.nav.date.jump"/> </span> + <select name="year"> + <option selected="selected" value="-1"><fmt:message key="browse.nav.year"/></option> <% int thisYear = DCDate.getCurrent().getYear(); for (int i = thisYear; i >= 1990; i--) { %> - <option><%= i %></option> + <option><%= i %></option> <% } %> - <option>1985</option> - <option>1980</option> - <option>1975</option> - <option>1970</option> - <option>1960</option> - <option>1950</option> - </select> - <select name="month"> - <option selected="selected" value="-1"><fmt:message key="browse.nav.month"/></option> + <option>1985</option> + <option>1980</option> + <option>1975</option> + <option>1970</option> + <option>1960</option> + <option>1950</option> + </select> + <select name="month"> + <option selected="selected" value="-1"><fmt:message key="browse.nav.month"/></option> <% for (int i = 1; i <= 12; i++) { %> - <option value="<%= i %>"><%= DCDate.getMonthName(i, UIUtil.getSessionLocale(request)) %></option> + <option value="<%= i %>"><%= DCDate.getMonthName(i, UIUtil.getSessionLocale(request)) %></option> <% } %> - </select> - </td> - <td class="browseBar" rowspan="2"> - <input type="submit" value="<fmt:message key="browse.nav.go"/>" /> - </td> - </tr> - <tr> - <%-- HACK: Shouldn't use align here --%> - <td class="browseBar" align="center"> - <span class="browseBarLabel"><fmt:message key="browse.nav.type-year"/></span> - <input type="text" name="starts_with" size="4" maxlength="4"/> - </td> - </tr> - </table> - </td> - </tr> - </table> + </select> + <input type="submit" class="btn btn-default" value="<fmt:message key="browse.nav.go"/>" /> + <br/> + <label for="starts_with"><fmt:message key="browse.nav.type-year"/></label> + <input type="text" name="starts_with" size="4" maxlength="4"/> <% } @@ -195,34 +177,20 @@ else { %> - <table align="center" border="0" bgcolor="#CCCCCC" cellpadding="0" summary="Browse the respository"> - <tr> - <td> - <table border="0" bgcolor="#EEEEEE" cellpadding="2"> - <tr> - <td class="browseBar"> - <span class="browseBarLabel"><fmt:message key="browse.nav.jump"/></span> - <a href="<%= sharedLink %>&starts_with=0">0-9</a> + <span><fmt:message key="browse.nav.jump"/></span> + <a class="label label-default" href="<%= sharedLink %>&starts_with=0">0-9</a> <% for (char c = 'A'; c <= 'Z'; c++) { %> - <a href="<%= sharedLink %>&starts_with=<%= c %>"><%= c %></a> + <a href="<%= sharedLink %>&starts_with=<%= c %>"><%= c %></a> <% } %> - </td> - </tr> - <tr> - <td class="browseBar" align="center"> - <span class="browseBarLabel"><fmt:message key="browse.nav.enter"/> </span> - <input type="text" name="starts_with"/> <input type="submit" value="<fmt:message key="browse.nav.go"/>" /> - </td> - </tr> - </table> - </td> - </tr> - </table> + <br/> + <label for="starts_with"><fmt:message key="browse.nav.enter"/></label> + <input type="text" name="starts_with"/> + <input type="submit" class="btn btn-default" value="<fmt:message key="browse.nav.go"/>" /> <% } %> @@ -231,7 +199,7 @@ <%-- End of Navigation Headers --%> <%-- Include a component for modifying sort by, order and results per page --%> - <div align="center" id="browse_controls"> + <div id="browse_controls" class="well text-center"> <form method="get" action="<%= formaction %>"> <input type="hidden" name="type" value="<%= bix.getName() %>"/> @@ -243,13 +211,13 @@ %><input type="hidden" name="vfocus" value="<%= bi.getFocus() %>"/><% } --%> - <fmt:message key="browse.single.order"/> + <label for="order"><fmt:message key="browse.single.order"/></label> <select name="order"> <option value="ASC" <%= ascSelected %>><fmt:message key="browse.order.asc" /></option> <option value="DESC" <%= descSelected %>><fmt:message key="browse.order.desc" /></option> </select> - <fmt:message key="browse.single.rpp"/> + <label for="rpp"><fmt:message key="browse.single.rpp"/></label> <select name="rpp"> <% for (int i = 5; i <= 100 ; i += 5) @@ -261,26 +229,26 @@ } %> </select> - <input type="submit" name="submit_browse" value="<fmt:message key="jsp.general.update"/>"/> + <input type="submit" class="btn btn-default" name="submit_browse" value="<fmt:message key="jsp.general.update"/>"/> </form> </div> +<div class="row col-md-offset-3 col-md-6"> <%-- give us the top report on what we are looking at --%> - <div align="center" class="browse_range"> + <div class="panel panel-primary"> + <div class="panel-heading text-center"> <fmt:message key="browse.single.range"> <fmt:param value="<%= Integer.toString(bi.getStart()) %>"/> <fmt:param value="<%= Integer.toString(bi.getFinish()) %>"/> <fmt:param value="<%= Integer.toString(bi.getTotal()) %>"/> </fmt:message> - </div> - + <%-- do the top previous and next page links --%> - <div align="center"> <% if (bi.hasPrevPage()) { %> - <a href="<%= prev %>"><fmt:message key="browse.single.prev"/></a> + <a class="pull-left" href="<%= prev %>"><fmt:message key="browse.single.prev"/></a> <% } %> @@ -289,51 +257,41 @@ if (bi.hasNextPage()) { %> - <a href="<%= next %>"><fmt:message key="browse.single.next"/></a> + <a class="pull-right" href="<%= next %>"><fmt:message key="browse.single.next"/></a> <% } %> </div> - - <%-- THE RESULTS --%> - <table align="center" class="miscTable" summary="This table displays a list of results"> +<ul class="list-group"> <% - // Row: toggles between Odd and Even - String row = "odd"; String[][] results = bi.getStringResults(); for (int i = 0; i < results.length; i++) { %> - <tr> - <td class="<%= row %>RowOddCol"> + <li class="list-group-item"> <a href="<%= sharedLink %><% if (results[i][1] != null) { %>&authority=<%= URLEncoder.encode(results[i][1], "UTF-8") %>" class="authority <%= bix.getName() %>"><%= Utils.addEntities(results[i][0]) %></a> <% } else { %>&value=<%= URLEncoder.encode(results[i][0], "UTF-8") %>"><%= Utils.addEntities(results[i][0]) %></a> <% } %> - <%= StringUtils.isNotBlank(results[i][2])?" ["+results[i][2]+"]":""%> - </td> - </tr> + <%= StringUtils.isNotBlank(results[i][2])?" <span class=\"badge\">"+results[i][2]+"</span>":""%> + </li> <% - row = ( row.equals( "odd" ) ? "even" : "odd" ); } %> - </table> - + </ul> <%-- give us the bottom report on what we are looking at --%> - <div align="center" class="browse_range"> + <div class="panel-footer text-center"> <fmt:message key="browse.single.range"> <fmt:param value="<%= Integer.toString(bi.getStart()) %>"/> <fmt:param value="<%= Integer.toString(bi.getFinish()) %>"/> <fmt:param value="<%= Integer.toString(bi.getTotal()) %>"/> </fmt:message> - </div> <%-- do the bottom previous and next page links --%> - <div align="center"> <% if (bi.hasPrevPage()) { %> - <a href="<%= prev %>"><fmt:message key="browse.single.prev"/></a> + <a class="pull-left" href="<%= prev %>"><fmt:message key="browse.single.prev"/></a> <% } %> @@ -342,12 +300,13 @@ if (bi.hasNextPage()) { %> - <a href="<%= next %>"><fmt:message key="browse.single.next"/></a> + <a class="pull-right" href="<%= next %>"><fmt:message key="browse.single.next"/></a> <% } %> </div> - +</div> +</div> <%-- dump the results for debug (uncomment to enable) --%> <%-- <!-- <%= bi.toString() %> --> diff --git a/dspace-jspui/src/main/webapp/collection-home.jsp b/dspace-jspui/src/main/webapp/collection-home.jsp index 39b983e9edd312008c1bea0ea1a0d1c59cbf542e..0da3a403db737ab6d2fddc33fbfeadd048d2f684 100644 --- a/dspace-jspui/src/main/webapp/collection-home.jsp +++ b/dspace-jspui/src/main/webapp/collection-home.jsp @@ -19,6 +19,8 @@ - subscribed - Boolean, true if user is subscribed to this collection - admin_button - Boolean, show admin 'edit' button - editor_button - Boolean, show collection editor (edit submitters, item mapping) buttons + - show.items - Boolean, show item list + - browse.info - BrowseInfo, item list --%> <%@ page contentType="text/html;charset=UTF-8" %> @@ -31,11 +33,14 @@ <%@ page import="org.dspace.app.webui.servlet.admin.EditCommunitiesServlet" %> <%@ page import="org.dspace.app.webui.util.UIUtil" %> <%@ page import="org.dspace.browse.BrowseIndex" %> +<%@ page import="org.dspace.browse.BrowseInfo" %> <%@ page import="org.dspace.browse.ItemCounter"%> <%@ page import="org.dspace.content.*"%> <%@ page import="org.dspace.core.ConfigurationManager"%> +<%@ page import="org.dspace.core.Context" %> <%@ page import="org.dspace.eperson.Group" %> <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="java.net.URLEncoder" %> <% @@ -93,15 +98,15 @@ } ItemCounter ic = new ItemCounter(UIUtil.obtainContext(request)); + + Boolean showItems = (Boolean)request.getAttribute("show.items"); + boolean show_items = showItems != null ? showItems.booleanValue() : false; %> <%@page import="org.dspace.app.webui.servlet.MyDSpaceServlet"%> <dspace:layout locbar="commLink" title="<%= name %>" feedData="<%= feedData %>"> - - <table border="0" cellpadding="5" width="100%"> - <tr> - <td width="100%"> - <h1><%= name %> + <div class="well"> + <div class="row"><div class="col-md-8"><h2><%= name %> <% if(ConfigurationManager.getBooleanProperty("webui.strengths.show")) { @@ -110,204 +115,256 @@ <% } %> - </h1> - <h3><fmt:message key="jsp.collection-home.heading1"/></h3> - </td> - <td valign="top"> + <small><fmt:message key="jsp.collection-home.heading1"/></small> + <a class="statisticsLink btn btn-info" href="<%= request.getContextPath() %>/handle/<%= collection.getHandle() %>/statistics"><fmt:message key="jsp.collection-home.display-statistics"/></a> + </h2></div> <% if (logo != null) { %> - <img alt="Logo" src="<%= request.getContextPath() %>/retrieve/<%= logo.getID() %>" /> -<% } %></td> - </tr> - </table> - - <%-- Search/Browse --%> - <table class="miscTable" align="center" summary="This table allows you to search through all collections in the repository"> - <tr> - <td class="evenRowEvenCol" colspan="2"> - <form method="get" action=""> - <table> - <tr> - <td class="standard" align="center"> - <label for="tlocation"><small><strong><fmt:message key="jsp.general.location"/></strong></small></label> - <select name="location" id="tlocation"> - <option value="/"><fmt:message key="jsp.general.genericScope"/></option> - <option selected="selected" value="<%= community.getHandle() %>"><%= communityName %></option> - <option selected="selected" value="<%= collection.getHandle() %>"><%= name %></option> - </select> - </td> - </tr> - <tr> - <td class="standard" align="center"> - <label for="tquery"><small><fmt:message key="jsp.general.searchfor"/> </small></label><input type="text" name="query" id="tquery"/> - <input type="submit" name="submit_search" value="<fmt:message key="jsp.general.go"/>" /> - </td> - </tr> - </table> - </form> - </td> - </tr> - <tr> - <td align="center" class="standard" valign="middle"> - <small><fmt:message key="jsp.general.orbrowse"/> </small> - <%-- Insert the dynamic list of browse options --%> + <div class="col-md-4"> + <img class="img-responsive pull-right" alt="Logo" src="<%= request.getContextPath() %>/retrieve/<%= logo.getID() %>" /> + </div> +<% } %> + </div> +<% + if (StringUtils.isNotBlank(intro)) { %> + <%= intro %> +<% } %> + </div> + <p class="copyrightText"><%= copyright %></p> + + <%-- Browse --%> + <div class="panel panel-primary"> + <div class="panel-heading"> + <fmt:message key="jsp.general.browse"/> + </div> + <div class="panel-body"> + <%-- Insert the dynamic list of browse options --%> <% for (int i = 0; i < bis.length; i++) { String key = "browse.menu." + bis[i].getName(); %> - <div class="browse_buttons"> - <form method="get" action="<%= request.getContextPath() %>/handle/<%= collection.getHandle() %>/browse"> + <form method="get" class="btn-group" action="<%= request.getContextPath() %>/handle/<%= collection.getHandle() %>/browse"> <input type="hidden" name="type" value="<%= bis[i].getName() %>"/> <%-- <input type="hidden" name="collection" value="<%= collection.getHandle() %>" /> --%> - <input type="submit" name="submit_browse" value="<fmt:message key="<%= key %>"/>"/> + <input type="submit" class="btn btn-default" name="submit_browse" value="<fmt:message key="<%= key %>"/>"/> </form> - </div> <% } -%> - </td> - </tr> - </table> - - <table width="100%" align="center" cellspacing="10"> - <tr> - <td> -<%-- HACK: <center> used for Netscape 4.x, which doesn't accept align="center" - for a paragraph with a button in it --%> +%> </div> +</div> <% if (submit_button) { %> - <center> - <form action="<%= request.getContextPath() %>/submit" method="post"> + <form class="form-group" action="<%= request.getContextPath() %>/submit" method="post"> <input type="hidden" name="collection" value="<%= collection.getID() %>" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.collection-home.submit.button"/>" /> + <input class="btn btn-success col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.collection-home.submit.button"/>" /> </form> - </center> <% } %> - </td> - <td class="oddRowEvenCol"> - <form method="get" action=""> - <table> - <tr> - <td class="standard"> + <form class="well" method="get" action=""> <% if (loggedIn && subscribed) { %> <small><fmt:message key="jsp.collection-home.subscribed"/> <a href="<%= request.getContextPath() %>/subscribe"><fmt:message key="jsp.collection-home.info"/></a></small> - </td> - <td class="standard"> - <input type="submit" name="submit_unsubscribe" value="<fmt:message key="jsp.collection-home.unsub"/>" /> + <input class="btn btn-sm btn-warning" type="submit" name="submit_unsubscribe" value="<fmt:message key="jsp.collection-home.unsub"/>" /> <% } else { %> <small> <fmt:message key="jsp.collection-home.subscribe.msg"/> </small> - </td> - <td class="standard"> - <input type="submit" name="submit_subscribe" value="<fmt:message key="jsp.collection-home.subscribe"/>" /> -<% } %> - </td> - </tr> - </table> + <input class="btn btn-sm btn-info" type="submit" name="submit_subscribe" value="<fmt:message key="jsp.collection-home.subscribe"/>" /> +<% } + if(feedEnabled) + { %> + <span class="pull-right"> + <% + String[] fmts = feedData.substring(5).split(","); + String icon = null; + int width = 0; + for (int j = 0; j < fmts.length; j++) + { + if ("rss_1.0".equals(fmts[j])) + { + icon = "rss1.gif"; + width = 80; + } + else if ("rss_2.0".equals(fmts[j])) + { + icon = "rss2.gif"; + width = 80; + } + else + { + icon = "rss.gif"; + width = 36; + } +%> + <a href="<%= request.getContextPath() %>/feed/<%= fmts[j] %>/<%= collection.getHandle() %>"><img src="<%= request.getContextPath() %>/image/<%= icon %>" alt="RSS Feed" width="<%= width %>" height="15" vspace="3" border="0" /></a> +<% + } %> + </span><% + } +%> </form> - </td> - </tr> - </table> - <div align="center"> - <a class="statisticsLink" href="<%= request.getContextPath() %>/handle/<%= collection.getHandle() %>/statistics"><fmt:message key="jsp.collection-home.display-statistics"/></a> - </div> - <%= intro %> +<% if (show_items) + { + BrowseInfo bi = (BrowseInfo) request.getAttribute("browse.info"); + BrowseIndex bix = bi.getBrowseIndex(); - <p class="copyrightText"><%= copyright %></p> + // prepare the next and previous links + String linkBase = request.getContextPath() + "/handle/" + collection.getHandle(); + + String next = linkBase; + String prev = linkBase; + + if (bi.hasNextPage()) + { + next = next + "?offset=" + bi.getNextOffset(); + } + + if (bi.hasPrevPage()) + { + prev = prev + "?offset=" + bi.getPrevOffset(); + } + + String bi_name_key = "browse.menu." + bi.getSortOption().getName(); + String so_name_key = "browse.order." + (bi.isAscending() ? "asc" : "desc"); +%> + <%-- give us the top report on what we are looking at --%> + <fmt:message var="bi_name" key="<%= bi_name_key %>"/> + <fmt:message var="so_name" key="<%= so_name_key %>"/> + <div align="center" class="browse_range"> + <fmt:message key="jsp.collection-home.content.range"> + <fmt:param value="${bi_name}"/> + <fmt:param value="${so_name}"/> + <fmt:param value="<%= Integer.toString(bi.getStart()) %>"/> + <fmt:param value="<%= Integer.toString(bi.getFinish()) %>"/> + <fmt:param value="<%= Integer.toString(bi.getTotal()) %>"/> + </fmt:message> + </div> + + <%-- do the top previous and next page links --%> + <div align="center"> +<% + if (bi.hasPrevPage()) + { +%> + <a href="<%= prev %>"><fmt:message key="browse.full.prev"/></a> +<% + } + + if (bi.hasNextPage()) + { +%> + <a href="<%= next %>"><fmt:message key="browse.full.next"/></a> +<% + } +%> + </div> + +<%-- output the results using the browselist tag --%> +<% + if (bix.isMetadataIndex()) + { +%> + <dspace:browselist browseInfo="<%= bi %>" emphcolumn="<%= bix.getMetadata() %>" /> +<% + } + else + { +%> + <dspace:browselist browseInfo="<%= bi %>" emphcolumn="<%= bix.getSortOption().getMetadata() %>" /> +<% + } +%> + + <%-- give us the bottom report on what we are looking at --%> + <div align="center" class="browse_range"> + <fmt:message key="jsp.collection-home.content.range"> + <fmt:param value="${bi_name}"/> + <fmt:param value="${so_name}"/> + <fmt:param value="<%= Integer.toString(bi.getStart()) %>"/> + <fmt:param value="<%= Integer.toString(bi.getFinish()) %>"/> + <fmt:param value="<%= Integer.toString(bi.getTotal()) %>"/> + </fmt:message> + </div> + + <%-- do the bottom previous and next page links --%> + <div align="center"> +<% + if (bi.hasPrevPage()) + { +%> + <a href="<%= prev %>"><fmt:message key="browse.full.prev"/></a> +<% + } + + if (bi.hasNextPage()) + { +%> + <a href="<%= next %>"><fmt:message key="browse.full.next"/></a> +<% + } +%> + </div> + +<% + } // end of if (show_title) +%> <dspace:sidebar> <% if(admin_button || editor_button ) { %> - <table class="miscTable" align="center"> - <tr> - <td class="evenRowEvenCol" colspan="2"> - <table> - <tr> - <th id="t1" class="standard"> - <strong><fmt:message key="jsp.admintools"/></strong> - </th> - </tr> - + <div class="panel panel-warning"> + <div class="panel-heading"><fmt:message key="jsp.admintools"/> + <span class="pull-right"><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.collection-admin\")%>"><fmt:message key="jsp.adminhelp"/></dspace:popup></span> + </div> + <div class="panel-body"> <% if( editor_button ) { %> - <tr> - <td headers="t1" class="standard" align="center"> <form method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> <input type="hidden" name="collection_id" value="<%= collection.getID() %>" /> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="action" value="<%= EditCommunitiesServlet.START_EDIT_COLLECTION %>" /> - <input type="submit" value="<fmt:message key="jsp.general.edit.button"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.general.edit.button"/>" /> </form> - </td> - </tr> <% } %> <% if( admin_button ) { %> - <tr> - <td headers="t1" class="standard" align="center"> <form method="post" action="<%=request.getContextPath()%>/tools/itemmap"> <input type="hidden" name="cid" value="<%= collection.getID() %>" /> - <input type="submit" value="<fmt:message key="jsp.collection-home.item.button"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.collection-home.item.button"/>" /> </form> - </td> - </tr> <% if(submitters != null) { %> - <tr> - <td headers="t1" class="standard" align="center"> <form method="get" action="<%=request.getContextPath()%>/tools/group-edit"> <input type="hidden" name="group_id" value="<%=submitters.getID()%>" /> - <input type="submit" name="submit_edit" value="<fmt:message key="jsp.collection-home.editsub.button"/>" /> + <input class="btn btn-default col-md-12" type="submit" name="submit_edit" value="<fmt:message key="jsp.collection-home.editsub.button"/>" /> </form> - </td> - </tr> <% } %> <% if( editor_button || admin_button) { %> - <tr> - <td headers="t1" class="standard" align="center"> <form method="post" action="<%=request.getContextPath()%>/mydspace"> <input type="hidden" name="collection_id" value="<%= collection.getID() %>" /> <input type="hidden" name="step" value="<%= MyDSpaceServlet.REQUEST_EXPORT_ARCHIVE %>" /> - <input type="submit" value="<fmt:message key="jsp.mydspace.request.export.collection"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.mydspace.request.export.collection"/>" /> </form> - </td> - </tr> - <tr> - <td headers="t1" class="standard" align="center"> <form method="post" action="<%=request.getContextPath()%>/mydspace"> <input type="hidden" name="collection_id" value="<%= collection.getID() %>" /> <input type="hidden" name="step" value="<%= MyDSpaceServlet.REQUEST_MIGRATE_ARCHIVE %>" /> - <input type="submit" value="<fmt:message key="jsp.mydspace.request.export.migratecollection"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.mydspace.request.export.migratecollection"/>" /> </form> - </td> - </tr> - <tr> - <td headers="t1" class="standard" align="center"> <form method="post" action="<%=request.getContextPath()%>/dspace-admin/metadataexport"> <input type="hidden" name="handle" value="<%= collection.getHandle() %>" /> - <input type="submit" value="<fmt:message key="jsp.general.metadataexport.button"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.general.metadataexport.button"/>" /> </form> - </td> - </tr> + </div> + </div> <% } %> - <tr> - <td headers="t1" class="standard" align="center"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.collection-admin\")%>"><fmt:message key="jsp.adminhelp"/></dspace:popup> - </td> - </tr> + <% } %> - </table> - </td> - </tr> - </table> <% } %> - - <h3><fmt:message key="jsp.collection-home.recentsub"/></h3> <% if (rs != null) { +%> + <h3><fmt:message key="jsp.collection-home.recentsub"/></h3> +<% Item[] items = rs.getRecentSubmissions(); for (int i = 0; i < items.length; i++) { @@ -322,47 +379,15 @@ } %><p class="recentItem"><a href="<%= request.getContextPath() %>/handle/<%= items[i].getHandle() %>"><%= displayTitle %></a></p><% } - } %> <p> </p> -<% - if(feedEnabled) - { -%> - <center> - <h4><fmt:message key="jsp.collection-home.feeds"/></h4> -<% - String[] fmts = feedData.substring(5).split(","); - String icon = null; - int width = 0; - for (int j = 0; j < fmts.length; j++) - { - if ("rss_1.0".equals(fmts[j])) - { - icon = "rss1.gif"; - width = 80; - } - else if ("rss_2.0".equals(fmts[j])) - { - icon = "rss2.gif"; - width = 80; - } - else - { - icon = "rss.gif"; - width = 36; - } -%> - <a href="<%= request.getContextPath() %>/feed/<%= fmts[j] %>/<%= collection.getHandle() %>"><img src="<%= request.getContextPath() %>/image/<%= icon %>" alt="RSS Feed" width="<%= width %>" height="15" vspace="3" border="0" /></a> -<% - } -%> - </center> -<% - } -%> +<% } %> + <%= sidebar %> - + <% + int discovery_panel_cols = 12; + int discovery_facet_cols = 12; + %> <%@ include file="discovery/static-sidebar-facet.jsp" %> </dspace:sidebar> diff --git a/dspace-jspui/src/main/webapp/community-home.jsp b/dspace-jspui/src/main/webapp/community-home.jsp index e6a928b10c5c6629f727b0e7ef2327a86bc4d941..5c8cce0481b65aa806ec247993f49699fff5c69a 100644 --- a/dspace-jspui/src/main/webapp/community-home.jsp +++ b/dspace-jspui/src/main/webapp/community-home.jsp @@ -74,11 +74,10 @@ <%@page import="org.dspace.app.webui.servlet.MyDSpaceServlet"%> <dspace:layout locbar="commLink" title="<%= name %>" feedData="<%= feedData %>"> - - <table border="0" cellpadding="5" width="100%"> - <tr> - <td width="100%"> - <h1><%= name %> +<div class="well"> +<div class="row"> + <div class="col-md-8"> + <h2><%= name %> <% if(ConfigurationManager.getBooleanProperty("webui.strengths.show")) { @@ -87,329 +86,319 @@ <% } %> - </h1> - <h3><fmt:message key="jsp.community-home.heading1"/></h3> - </td> - <td valign="top"> + <small><fmt:message key="jsp.community-home.heading1"/></small> + <a class="statisticsLink btn btn-info" href="<%= request.getContextPath() %>/handle/<%= community.getHandle() %>/statistics"><fmt:message key="jsp.community-home.display-statistics"/></a> + </h2> + </div> <% if (logo != null) { %> - <img alt="Logo" src="<%= request.getContextPath() %>/retrieve/<%= logo.getID() %>" /> -<% } %></td> - </tr> - </table> - + <div class="col-md-4"> + <img class="img-responsive" alt="Logo" src="<%= request.getContextPath() %>/retrieve/<%= logo.getID() %>" /> + </div> +<% } %> + </div> - <%-- Search/Browse --%> - - <table class="miscTable" align="center" summary="This table allows you to search through all communities held in the repository"> - <tr> - <td class="evenRowEvenCol" colspan="2"> - <form method="get" action=""> - <table> - <tr> - <td class="standard" align="center"> - <small><label for="tlocation"><strong><fmt:message key="jsp.general.location"/></strong></label></small> <select name="location" id="tlocation"> - <option value="/"><fmt:message key="jsp.general.genericScope"/></option> - <option selected="selected" value="<%= community.getHandle() %>"><%= name %></option> +<% if (StringUtils.isNotBlank(intro)) { %> + <%= intro %> +<% } %> +</div> +<p class="copyrightText"><%= copyright %></p> + <div class="row"> +<% + if (rs != null) + { %> + <div class="col-md-8"> + <div class="panel panel-primary"> + <div id="recent-submissions-carousel" class="panel-heading carousel slide"> + <%-- Recently Submitted items --%> + <h3><fmt:message key="jsp.community-home.recentsub"/> <% - for (int i = 0; i < collections.length; i++) + if(feedEnabled) { -%> - <option value="<%= collections[i].getHandle() %>"><%= collections[i].getMetadata("name") %></option> + String[] fmts = feedData.substring(5).split(","); + String icon = null; + int width = 0; + for (int j = 0; j < fmts.length; j++) + { + if ("rss_1.0".equals(fmts[j])) + { + icon = "rss1.gif"; + width = 80; + } + else if ("rss_2.0".equals(fmts[j])) + { + icon = "rss2.gif"; + width = 80; + } + else + { + icon = "rss.gif"; + width = 36; + } +%> + <a href="<%= request.getContextPath() %>/feed/<%= fmts[j] %>/<%= community.getHandle() %>"><img src="<%= request.getContextPath() %>/image/<%= icon %>" alt="RSS Feed" width="<%= width %>" height="15" vspace="3" border="0" /></a> <% + } } %> + </h3> + + <% + Item[] items = rs.getRecentSubmissions(); + boolean first = true; + if(items!=null && items.length>0) + { + %> + <!-- Wrapper for slides --> + <div class="carousel-inner"> + <% for (int i = 0; i < items.length; i++) + { + DCValue[] dcv = items[i].getMetadata("dc", "title", null, Item.ANY); + String displayTitle = "Untitled"; + if (dcv != null) + { + if (dcv.length > 0) + { + displayTitle = dcv[0].value; + } + } + %> + <div style="padding-bottom: 50px; min-height: 200px;" class="item <%= first?"active":""%>"> + <div style="padding-left: 80px; padding-right: 80px; display: inline-block;"><%= StringUtils.abbreviate(displayTitle, 400) %> + <a href="<%= request.getContextPath() %>/handle/<%=items[i].getHandle() %>"> + <button class="btn btn-success" type="button">See</button> + </a> + </div> + </div> <% - for (int j = 0; j < subcommunities.length; j++) - { -%> - <option value="<%= subcommunities[j].getHandle() %>"><%= subcommunities[j].getMetadata("name") %></option> + first = false; + } + %> + </div> + + <!-- Controls --> + <a class="left carousel-control" href="#recent-submissions-carousel" data-slide="prev"> + <span class="icon-prev"></span> + </a> + <a class="right carousel-control" href="#recent-submissions-carousel" data-slide="next"> + <span class="icon-next"></span> + </a> + + <ol class="carousel-indicators"> + <li data-target="#recent-submissions-carousel" data-slide-to="0" class="active"></li> + <% for (int i = 1; i < rs.count(); i++){ %> + <li data-target="#recent-submissions-carousel" data-slide-to="<%= i %>"></li> + <% } %> + </ol> + + <% + } + %> + + </div></div></div> <% - } + } %> - </select> - </td> - </tr> - <tr> - <td class="standard" align="center"> - <small><label for="tquery"><strong><fmt:message key="jsp.general.searchfor"/> </strong></label></small><input type="text" name="query" id="tquery" /> <input type="submit" name="submit_search" value="<fmt:message key="jsp.general.go"/>" /> - </td> - </tr> - </table> - </form> - </td> - </tr> - <tr> - <td align="center" class="standard" valign="middle"> - <small><fmt:message key="jsp.general.orbrowse"/> </small> + <div class="col-md-4"> + <%= sidebar %> + </div> +</div> + +<%-- Browse --%> +<div class="panel panel-primary"> + <div class="panel-heading"><fmt:message key="jsp.general.browse"/></div> + <div class="panel-body"> <%-- Insert the dynamic list of browse options --%> <% for (int i = 0; i < bis.length; i++) { String key = "browse.menu." + bis[i].getName(); %> - <div class="browse_buttons"> <form method="get" action="<%= request.getContextPath() %>/handle/<%= community.getHandle() %>/browse"> <input type="hidden" name="type" value="<%= bis[i].getName() %>"/> <%-- <input type="hidden" name="community" value="<%= community.getHandle() %>" /> --%> - <input type="submit" name="submit_browse" value="<fmt:message key="<%= key %>"/>"/> + <input class="btn btn-default col-md-3" type="submit" name="submit_browse" value="<fmt:message key="<%= key %>"/>"/> </form> - </div> <% } %> - </td> - </tr> - </table> - - <%= intro %> + + </div> +</div> + +<div class="row"> + <% + int discovery_panel_cols = 12; + int discovery_facet_cols = 4; + %> + <%@ include file="discovery/static-sidebar-facet.jsp" %> +</div> +<div class="row"> <% - if (collections.length != 0) + boolean showLogos = ConfigurationManager.getBooleanProperty("jspui.community-home.logos", true); + if (subcommunities.length != 0) { %> + <div class="col-md-6"> - <%-- <h2>Collections in this community</h2> --%> - <h2><fmt:message key="jsp.community-home.heading2"/></h2> - <ul class="collectionListItem"> + <h3><fmt:message key="jsp.community-home.heading3"/></h3> + + <div class="list-group"> <% - for (int i = 0; i < collections.length; i++) + for (int j = 0; j < subcommunities.length; j++) { %> - <li> - <table> - <tr> - <td> - <a href="<%= request.getContextPath() %>/handle/<%= collections[i].getHandle() %>"> - <%= collections[i].getMetadata("name") %></a> + <div class="list-group-item row"> +<% + Bitstream logoCom = subcommunities[j].getLogo(); + if (showLogos && logoCom != null) { %> + <div class="col-md-3"> + <img alt="Logo" class="img-responsive" src="<%= request.getContextPath() %>/retrieve/<%= logoCom.getID() %>" /> + </div> + <div class="col-md-9"> +<% } else { %> + <div class="col-md-12"> +<% } %> + + <h4 class="list-group-item-heading"><a href="<%= request.getContextPath() %>/handle/<%= subcommunities[j].getHandle() %>"> + <%= subcommunities[j].getMetadata("name") %></a> <% - if(ConfigurationManager.getBooleanProperty("webui.strengths.show")) - { + if (ConfigurationManager.getBooleanProperty("webui.strengths.show")) + { %> - [<%= ic.getCount(collections[i]) %>] + [<%= ic.getCount(subcommunities[j]) %>] <% - } + } %> - </td> - <% if (remove_button) { %> - <td> - <form method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> - <input type="hidden" name="parent_community_id" value="<%= community.getID() %>" /> - <input type="hidden" name="community_id" value="<%= community.getID() %>" /> - <input type="hidden" name="collection_id" value="<%= collections[i].getID() %>" /> - <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_DELETE_COLLECTION%>" /> - <input type="image" src="<%= request.getContextPath() %>/image/remove.gif" /> - </form> - </td> - <% } %> - </tr> - </table> - <p class="collectionDescription"><%= collections[i].getMetadata("short_description") %></p> - </li> + <% if (remove_button) { %> + <form class="btn-group" method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> + <input type="hidden" name="parent_community_id" value="<%= community.getID() %>" /> + <input type="hidden" name="community_id" value="<%= subcommunities[j].getID() %>" /> + <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_DELETE_COMMUNITY%>" /> + <button type="submit" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span></button> + </form> + <% } %> + </h4> + <p class="collectionDescription"><%= subcommunities[j].getMetadata("short_description") %></p> + </div> + </div> <% } %> - </ul> + </div> +</div> <% } %> <% - if (subcommunities.length != 0) + if (collections.length != 0) { %> - <%--<h2>Sub-communities within this community</h2>--%> - <h2><fmt:message key="jsp.community-home.heading3"/></h2> - - <ul class="collectionListItem"> + <div class="col-md-6"> + + <%-- <h2>Collections in this community</h2> --%> + <h3><fmt:message key="jsp.community-home.heading2"/></h3> + <div class="list-group"> <% - for (int j = 0; j < subcommunities.length; j++) + for (int i = 0; i < collections.length; i++) { %> - <li> - <table> - <tr> - <td> - <a href="<%= request.getContextPath() %>/handle/<%= subcommunities[j].getHandle() %>"> - <%= subcommunities[j].getMetadata("name") %></a> + <div class="list-group-item row"> +<% + Bitstream logoCol = collections[i].getLogo(); + if (showLogos && logoCol != null) { %> + <div class="col-md-3"> + <img alt="Logo" class="img-responsive" src="<%= request.getContextPath() %>/retrieve/<%= logoCol.getID() %>" /> + </div> + <div class="col-md-9"> +<% } else { %> + <div class="col-md-12"> +<% } %> + + <h4 class="list-group-item-heading"><a href="<%= request.getContextPath() %>/handle/<%= collections[i].getHandle() %>"> + <%= collections[i].getMetadata("name") %></a> <% - if (ConfigurationManager.getBooleanProperty("webui.strengths.show")) - { + if(ConfigurationManager.getBooleanProperty("webui.strengths.show")) + { %> - [<%= ic.getCount(subcommunities[j]) %>] + [<%= ic.getCount(collections[i]) %>] <% - } + } %> - </td> - <% if (remove_button) { %> - <td> - <form method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> - <input type="hidden" name="parent_community_id" value="<%= community.getID() %>" /> - <input type="hidden" name="community_id" value="<%= subcommunities[j].getID() %>" /> - <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_DELETE_COMMUNITY%>" /> - <input type="image" src="<%= request.getContextPath() %>/image/remove.gif" /> - </form> - </td> - <% } %> - </tr> - </table> - <p class="collectionDescription"><%= subcommunities[j].getMetadata("short_description") %></p> - </li> + <% if (remove_button) { %> + <form class="btn-group" method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> + <input type="hidden" name="parent_community_id" value="<%= community.getID() %>" /> + <input type="hidden" name="community_id" value="<%= community.getID() %>" /> + <input type="hidden" name="collection_id" value="<%= collections[i].getID() %>" /> + <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_DELETE_COLLECTION%>" /> + <button type="submit" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span></button> + </form> + <% } %> + </h4> + <p class="collectionDescription"><%= collections[i].getMetadata("short_description") %></p> + </div> + </div> <% } %> - </ul> + </div> +</div> <% } %> - - <p class="copyrightText"><%= copyright %></p> - - <dspace:sidebar> +</div> <% if(editor_button || add_button) // edit button(s) { %> - <table class="miscTable" align="center"> - <tr> - <td class="evenRowEvenCol" colspan="2"> - <table> - <tr> - <th id="t1" class="standard"> - <%--<strong>Admin Tools</strong>--%> - <strong><fmt:message key="jsp.admintools"/></strong> - </th> - </tr> - <tr> - <td headers="t1" class="standard" align="center"> + <dspace:sidebar> + <div class="panel panel-warning"> + <div class="panel-heading"> + <fmt:message key="jsp.admintools"/> + <span class="pull-right"> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\")%>"><fmt:message key="jsp.adminhelp"/></dspace:popup> + </span> + </div> + <div class="panel-body"> <% if(editor_button) { %> <form method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_EDIT_COMMUNITY%>" /> <%--<input type="submit" value="Edit..." />--%> - <input type="submit" value="<fmt:message key="jsp.general.edit.button"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.general.edit.button"/>" /> </form> <% } %> <% if(add_button) { %> <form method="post" action="<%=request.getContextPath()%>/tools/collection-wizard"> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> - <input type="submit" value="<fmt:message key="jsp.community-home.create1.button"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.community-home.create1.button"/>" /> </form> <form method="post" action="<%=request.getContextPath()%>/tools/edit-communities"> <input type="hidden" name="action" value="<%= EditCommunitiesServlet.START_CREATE_COMMUNITY%>" /> <input type="hidden" name="parent_community_id" value="<%= community.getID() %>" /> <%--<input type="submit" name="submit" value="Create Sub-community" />--%> - <input type="submit" name="submit" value="<fmt:message key="jsp.community-home.create2.button"/>" /> + <input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.community-home.create2.button"/>" /> </form> <% } %> - </td> - </tr> <% if( editor_button ) { %> - <tr> - <td headers="t1" class="standard" align="center"> <form method="post" action="<%=request.getContextPath()%>/mydspace"> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="step" value="<%= MyDSpaceServlet.REQUEST_EXPORT_ARCHIVE %>" /> - <input type="submit" value="<fmt:message key="jsp.mydspace.request.export.community"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.mydspace.request.export.community"/>" /> </form> - </td> - </tr> - <tr> - <td headers="t1" class="standard" align="center"> <form method="post" action="<%=request.getContextPath()%>/mydspace"> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="step" value="<%= MyDSpaceServlet.REQUEST_MIGRATE_ARCHIVE %>" /> - <input type="submit" value="<fmt:message key="jsp.mydspace.request.export.migratecommunity"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.mydspace.request.export.migratecommunity"/>" /> </form> - </td> - </tr> - <tr> - <td headers="t1" class="standard" align="center"> <form method="post" action="<%=request.getContextPath()%>/dspace-admin/metadataexport"> <input type="hidden" name="handle" value="<%= community.getHandle() %>" /> - <input type="submit" value="<fmt:message key="jsp.general.metadataexport.button"/>" /> + <input class="btn btn-default col-md-12" type="submit" value="<fmt:message key="jsp.general.metadataexport.button"/>" /> </form> - </td> - </tr> <% } %> - <tr> - <td headers="t1" class="standard" align="center"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\")%>"><fmt:message key="jsp.adminhelp"/></dspace:popup> - </td> - </tr> - </table> - </td> - </tr> - </table> - - <% } %> - - <%-- Recently Submitted items --%> - <h3><fmt:message key="jsp.community-home.recentsub"/></h3> -<% - if (rs != null) - { - Item[] items = rs.getRecentSubmissions(); - for (int i = 0; i < items.length; i++) - { - DCValue[] dcv = items[i].getMetadata("dc", "title", null, Item.ANY); - String displayTitle = "Untitled"; - if (dcv != null) - { - if (dcv.length > 0) - { - displayTitle = dcv[0].value; - } - } - %><p class="recentItem"><a href="<%= request.getContextPath() %>/handle/<%= items[i].getHandle() %>"><%= displayTitle %></a></p><% - } - } -%> - <p> </p> -<% - if(feedEnabled) - { -%> - <center> - <h4><fmt:message key="jsp.community-home.feeds"/></h4> -<% - String[] fmts = feedData.substring(5).split(","); - String icon = null; - int width = 0; - for (int j = 0; j < fmts.length; j++) - { - if ("rss_1.0".equals(fmts[j])) - { - icon = "rss1.gif"; - width = 80; - } - else if ("rss_2.0".equals(fmts[j])) - { - icon = "rss2.gif"; - width = 80; - } - else - { - icon = "rss.gif"; - width = 36; - } -%> - <a href="<%= request.getContextPath() %>/feed/<%= fmts[j] %>/<%= community.getHandle() %>"><img src="<%= request.getContextPath() %>/image/<%= icon %>" alt="RSS Feed" width="<%= width %>" height="15" vspace="3" border="0" /></a> -<% - } -%> - </center> -<% - } -%> - - <%= sidebar %> - <%@ include file="discovery/static-sidebar-facet.jsp" %> + </div> + </div> </dspace:sidebar> - - <div align="center"> - <a class="statisticsLink" href="<%= request.getContextPath() %>/handle/<%= community.getHandle() %>/statistics"><fmt:message key="jsp.community-home.display-statistics"/></a> - </div> - - -</dspace:layout> - + <% } %> +</dspace:layout> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/community-list.jsp b/dspace-jspui/src/main/webapp/community-list.jsp index baf353254decbd240ee06940f9a74d9d22b64340..336a7ca1145c72ed7f396af3c954768bd53019b2 100644 --- a/dspace-jspui/src/main/webapp/community-list.jsp +++ b/dspace-jspui/src/main/webapp/community-list.jsp @@ -20,6 +20,8 @@ - admin_button - Boolean, show admin 'Create Top-Level Community' button --%> +<%@page import="org.dspace.content.Bitstream"%> +<%@page import="org.apache.commons.lang.StringUtils"%> <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> @@ -44,61 +46,78 @@ Map subcommunityMap = (Map) request.getAttribute("subcommunities.map"); Boolean admin_b = (Boolean)request.getAttribute("admin_button"); boolean admin_button = (admin_b == null ? false : admin_b.booleanValue()); - boolean showAll = true; ItemCounter ic = new ItemCounter(UIUtil.obtainContext(request)); %> <%! - JspWriter out = null; - HttpServletRequest request = null; - - void setContext(JspWriter out, HttpServletRequest request) - { - this.out = out; - this.request = request; - } - - void showCommunity(Community c) throws ItemCountException, IOException, SQLException + void showCommunity(Community c, JspWriter out, HttpServletRequest request, ItemCounter ic, + Map collectionMap, Map subcommunityMap) throws ItemCountException, IOException, SQLException { - ItemCounter ic = new ItemCounter(UIUtil.obtainContext(request)); - out.println( "<li class=\"communityLink\">" ); - out.println( "<strong><a href=\"" + request.getContextPath() + "/handle/" + c.getHandle() + "\">" + c.getMetadata("name") + "</a></strong>"); + boolean showLogos = ConfigurationManager.getBooleanProperty("jspui.community-list.logos", true); + out.println( "<li class=\"media well\">" ); + Bitstream logo = c.getLogo(); + if (showLogos && logo != null) + { + out.println("<a class=\"pull-left col-md-2\" href=\"" + request.getContextPath() + "/handle/" + + c.getHandle() + "\"><img class=\"media-object img-responsive\" src=\"" + + request.getContextPath() + "/retrieve/" + logo.getID() + "\" alt=\"community logo\"></a>"); + } + out.println( "<div class=\"media-body\"><h4 class=\"media-heading\"><a href=\"" + request.getContextPath() + "/handle/" + + c.getHandle() + "\">" + c.getMetadata("name") + "</a>"); if(ConfigurationManager.getBooleanProperty("webui.strengths.show")) { - out.println(" <span class=\"communityStrength\">[" + ic.getCount(c) + "]</span>"); + out.println(" <span class=\"badge\">" + ic.getCount(c) + "</span>"); } - + out.println("</h4>"); + if (StringUtils.isNotBlank(c.getMetadata("short_description"))) + { + out.println(c.getMetadata("short_description")); + } + out.println("<br>"); // Get the collections in this community - Collection[] cols = c.getCollections(); - if (cols.length > 0) + Collection[] cols = (Collection[]) collectionMap.get(c.getID()); + if (cols != null && cols.length > 0) { - out.println("<ul>"); + out.println("<ul class=\"media-list\">"); for (int j = 0; j < cols.length; j++) { - out.println("<li class=\"collectionListItem\">"); - out.println("<a href=\"" + request.getContextPath() + "/handle/" + cols[j].getHandle() + "\">" + cols[j].getMetadata("name") +"</a>"); + out.println("<li class=\"media well\">"); + + Bitstream logoCol = cols[j].getLogo(); + if (showLogos && logoCol != null) + { + out.println("<a class=\"pull-left col-md-2\" href=\"" + request.getContextPath() + "/handle/" + + cols[j].getHandle() + "\"><img class=\"media-object img-responsive\" src=\"" + + request.getContextPath() + "/retrieve/" + logoCol.getID() + "\" alt=\"collection logo\"></a>"); + } + out.println("<div class=\"media-body\"><h4 class=\"media-heading\"><a href=\"" + request.getContextPath() + "/handle/" + cols[j].getHandle() + "\">" + cols[j].getMetadata("name") +"</a>"); if(ConfigurationManager.getBooleanProperty("webui.strengths.show")) { out.println(" [" + ic.getCount(cols[j]) + "]"); } - + out.println("</h4>"); + if (StringUtils.isNotBlank(cols[j].getMetadata("short_description"))) + { + out.println(cols[j].getMetadata("short_description")); + } + out.println("</div>"); out.println("</li>"); } out.println("</ul>"); } // Get the sub-communities in this community - Community[] comms = c.getSubcommunities(); - if (comms.length > 0) + Community[] comms = (Community[]) subcommunityMap.get(c.getID()); + if (comms != null && comms.length > 0) { - out.println("<ul>"); + out.println("<ul class=\"media-list\">"); for (int k = 0; k < comms.length; k++) { - showCommunity(comms[k]); + showCommunity(comms[k], out, request, ic, collectionMap, subcommunityMap); } out.println("</ul>"); } - out.println("<br />"); + out.println("</div>"); out.println("</li>"); } %> @@ -109,130 +128,36 @@ if (admin_button) { %> - -<table class="miscTableNoColor" align="center"> - <tr> - <td> - <h1><fmt:message key="jsp.community-list.title"/></h1> - <p><fmt:message key="jsp.community-list.text1"/></p> - </td> - <td> - <table class="miscTable" align="center"> - <tr> - <td class="evenRowEvenCol" colspan="2"> - <table> - <tr> - <th class="standard" id="t1"> - <strong><fmt:message key="jsp.admintools"/></strong> - </th> - </tr> - <tr> - <td headers="t1" class="standard" align="center"> - <form method="post" action="<%=request.getContextPath()%>/dspace-admin/edit-communities"> - <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_CREATE_COMMUNITY%>" /> - <%--<input type="submit" name="submit" value="Create Top-Level Community...">--%> - <input type="submit" name="submit" value="<fmt:message key="jsp.community-list.create.button"/>" /> - </form> - </td> - </tr> - <tr> - <td headers="t1" class="standard" align="center"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\")%>"><fmt:message key="jsp.adminhelp"/></dspace:popup> - </td> - </tr> - </table> - </td> - </tr> - </table> - </td> - </tr> - </table> - +<dspace:sidebar> + <div class="panel panel-warning"> + <div class="panel-heading"> + <fmt:message key="jsp.admintools"/> + <span class="pull-right"> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\")%>"><fmt:message key="jsp.adminhelp"/></dspace:popup> + </span> + </div> + <div class="panel-body"> + <form method="post" action="<%=request.getContextPath()%>/dspace-admin/edit-communities"> + <input type="hidden" name="action" value="<%=EditCommunitiesServlet.START_CREATE_COMMUNITY%>" /> + <input class="btn btn-default" type="submit" name="submit" value="<fmt:message key="jsp.community-list.create.button"/>" /> + </form> + </div> +</dspace:sidebar> <% } - else - { %> <h1><fmt:message key="jsp.community-list.title"/></h1> <p><fmt:message key="jsp.community-list.text1"/></p> -<% - } -%> + <% if (communities.length != 0) { %> - <ul> + <ul class="media-list"> <% - if (showAll) - { - setContext(out, request); for (int i = 0; i < communities.length; i++) { - showCommunity(communities[i]); + showCommunity(communities[i], out, request, ic, collectionMap, subcommunityMap); } - } - else - { - for (int i = 0; i < communities.length; i++) - { -%> - <li class="communityLink"> - <%-- HACK: <strong> tags here for broken Netscape 4.x CSS support --%> - <strong><a href="<%= request.getContextPath() %>/handle/<%= communities[i].getHandle() %>"><%= communities[i].getMetadata("name") %></a></strong> - <ul> -<% - // Get the collections in this community from the map - Collection[] cols = (Collection[]) collectionMap.get( - new Integer(communities[i].getID())); - - for (int j = 0; j < cols.length; j++) - { -%> - <li class="collectionListItem"> - <a href="<%= request.getContextPath() %>/handle/<%= cols[j].getHandle() %>"><%= cols[j].getMetadata("name") %></a> -<% - if (ConfigurationManager.getBooleanProperty("webui.strengths.show")) - { -%> - [<%= ic.getCount(cols[j]) %>] -<% - } -%> - - </li> -<% - } -%> - </ul> - <ul> -<% - // Get the sub-communities in this community from the map - Community[] comms = (Community[]) subcommunityMap.get( - new Integer(communities[i].getID())); - - for (int k = 0; k < comms.length; k++) - { -%> - <li class="communityLink"> - <a href="<%= request.getContextPath() %>/handle/<%= comms[k].getHandle() %>"><%= comms[k].getMetadata("name") %></a> -<% - if (ConfigurationManager.getBooleanProperty("webui.strengths.show")) - { -%> - [<%= ic.getCount(comms[k]) %>] -<% - } -%> - </li> -<% - } -%> - </ul> - <br /> - </li> -<% - } - } %> </ul> diff --git a/dspace-jspui/src/main/webapp/components/login-form.jsp b/dspace-jspui/src/main/webapp/components/login-form.jsp index fe9f8f3ddc643a30923602f01f777b9bd67825b5..e603c24bb3061a2065f6dd9dfdebdd8ab158baf7 100644 --- a/dspace-jspui/src/main/webapp/components/login-form.jsp +++ b/dspace-jspui/src/main/webapp/components/login-form.jsp @@ -13,34 +13,30 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> - -<table class="miscTable" align="center" width="70%"> - <tr> - <td class="evenRowEvenCol"> - <form name="loginform" id="loginform" method="post" action="<%= request.getContextPath() %>/password-login"> + <div class="panel-body"> + <form name="loginform" class="form-horizontal" id="loginform" method="post" action="<%= request.getContextPath() %>/password-login"> <p><strong><a href="<%= request.getContextPath() %>/register"><fmt:message key="jsp.components.login-form.newuser"/></a></strong></p> <p><fmt:message key="jsp.components.login-form.enter"/></p> - - <table border="0" cellpadding="5" align="center"> - <tr> - <td class="standard" align="right"><label for="tlogin_email"><strong><fmt:message key="jsp.components.login-form.email"/></strong></label></td> - <td><input type="text" name="login_email" id="tlogin_email" tabindex="1" /></td> - </tr> - <tr> - <td class="standard" align="right"><label for="tlogin_password"><strong><fmt:message key="jsp.components.login-form.password"/></strong></label></td> - <td><input type="password" name="login_password" id="tlogin_password" tabindex="2" /></td> - </tr> - <tr> - <td align="center" colspan="2"> - <input type="submit" name="login_submit" value="<fmt:message key="jsp.components.login-form.login"/>" tabindex="3" /> - </td> - </tr> - </table> - + <div class="form-group"> + <label class="col-md-offset-3 col-md-2 control-label" for="tlogin_email"><fmt:message key="jsp.components.login-form.email"/></label> + <div class="col-md-3"> + <input class="form-control" type="text" name="login_email" id="tlogin_email" tabindex="1" /> + </div> + </div> + <div class="form-group"> + <label class="col-md-offset-3 col-md-2 control-label" for="tlogin_password"><fmt:message key="jsp.components.login-form.password"/></label> + <div class="col-md-3"> + <input class="form-control" type="password" name="login_password" id="tlogin_password" tabindex="2" /> + </div> + </div> + <div class="row"> + <div class="col-md-6"> + <input type="submit" class="btn btn-success pull-right" name="login_submit" value="<fmt:message key="jsp.components.login-form.login"/>" tabindex="3" /> + </div> + </div> + <p><a href="<%= request.getContextPath() %>/forgot"><fmt:message key="jsp.components.login-form.forgot"/></a></p> </form> <script type="text/javascript"> document.loginform.login_email.focus(); </script> - <p><a href="<%= request.getContextPath() %>/forgot"><fmt:message key="jsp.components.login-form.forgot"/></a></p></td> - </tr> -</table> + </div> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/controlledvocabulary/results.jsp b/dspace-jspui/src/main/webapp/controlledvocabulary/results.jsp index 44af6d501575f400f25ca966e7af21adf21ada50..332ae51ddbbd661339c7997334365b52c1b6977c 100644 --- a/dspace-jspui/src/main/webapp/controlledvocabulary/results.jsp +++ b/dspace-jspui/src/main/webapp/controlledvocabulary/results.jsp @@ -133,7 +133,7 @@ else String prevURL = request.getContextPath() + searchScope + "/simple-search?query=" - + URLEncoder.encode(query) + + URLEncoder.encode(query, "UTF-8") + "&start="; String nextURL = prevURL; @@ -157,7 +157,7 @@ for( int q = pageFirst; q <= pageLast; q++ ) + request.getContextPath() + searchScope + "/simple-search?query=" - + URLEncoder.encode(query) + + URLEncoder.encode(query, "UTF-8") + "&start="; diff --git a/dspace-jspui/src/main/webapp/discovery/static-sidebar-facet.jsp b/dspace-jspui/src/main/webapp/discovery/static-sidebar-facet.jsp index 170c1db4428687dd5c36df921b2e9b56b23d0ab0..5d3e55e62a0806187416d104bb3970752372d23e 100644 --- a/dspace-jspui/src/main/webapp/discovery/static-sidebar-facet.jsp +++ b/dspace-jspui/src/main/webapp/discovery/static-sidebar-facet.jsp @@ -60,8 +60,9 @@ } if (brefine) { %> +<div class="col-md-<%= discovery_panel_cols %>"> <h3 class="facets"><fmt:message key="jsp.search.facet.refine" /></h3> -<div id="facets" class="facetsBox"> +<div id="facets" class="facetsBox row panel"> <% for (DiscoverySearchFilterFacet facetConf : facetsConf) { @@ -77,47 +78,50 @@ } String fkey = "jsp.search.facet.refine."+f; int limit = facetConf.getFacetLimit()+1; - %><div id="facet_<%= f %>" class="facet"> + %><div id="facet_<%= f %>" class="facet col-md-<%= discovery_facet_cols %>"> <span class="facetName"><fmt:message key="<%= fkey %>" /></span> - <ul><% + <ul class="list-group"><% int idx = 1; int currFp = UIUtil.getIntParameter(request, f+"_page"); if (currFp < 0) { currFp = 0; } - if (currFp > 0) - { - %><li class="facet-previous"><a href="<%= request.getContextPath() - + searchScope - + "?"+f+"_page="+(currFp-1) %>"><fmt:message key="jsp.search.facet.refine.previous" /></a></li> - <% - } if (facet != null) { for (FacetResult fvalue : facet) { - if (idx == limit) - { - %><li class="facet-next"><a href="<%= request.getContextPath() - + searchScope - + "?"+f+"_page="+(currFp+1) %>"><fmt:message key="jsp.search.facet.refine.next" /></a></li> - <% - } - else + if (idx != limit) { - %><li><a href="<%= request.getContextPath() + %><li class="list-group-item"><span class="badge"><%= fvalue.getCount() %></span> <a href="<%= request.getContextPath() + searchScope + "/simple-search?filterquery="+URLEncoder.encode(fvalue.getAsFilterQuery(),"UTF-8") + "&filtername="+URLEncoder.encode(f,"UTF-8") + "&filtertype="+URLEncoder.encode(fvalue.getFilterType(),"UTF-8") %>" title="<fmt:message key="jsp.search.facet.narrow"><fmt:param><%=fvalue.getDisplayedValue() %></fmt:param></fmt:message>"> - <%= StringUtils.abbreviate(fvalue.getDisplayedValue(),32) + " (" + fvalue.getCount()+")" %></a></li><% + <%= StringUtils.abbreviate(fvalue.getDisplayedValue(),36) %></a></li><% } idx++; } + if (currFp > 0 || idx > limit) + { + %><li class="list-group-item"><span style="visibility: hidden;">.</span> + <% if (currFp > 0) { %> + <a class="pull-left" href="<%= request.getContextPath() + + searchScope + + "?"+f+"_page="+(currFp-1) %>"><fmt:message key="jsp.search.facet.refine.previous" /></a> + <% } %> + <% if (idx > limit) { %> + <a href="<%= request.getContextPath() + + searchScope + + "?"+f+"_page="+(currFp+1) %>"><span class="pull-right"><fmt:message key="jsp.search.facet.refine.next" /></span></a> + <% + } + %></li><% + } } %></ul></div><% } +%></div></div><% } %> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/display-item.jsp b/dspace-jspui/src/main/webapp/display-item.jsp index 50a4fc561b76da16e8c7d69f6f004df95d701bb3..3e9e7f65ca4813c849dd707911409763a7a697f3 100644 --- a/dspace-jspui/src/main/webapp/display-item.jsp +++ b/dspace-jspui/src/main/webapp/display-item.jsp @@ -23,7 +23,6 @@ - display any collections. - admin_button - Boolean, show admin 'edit' button --%> - <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> @@ -36,7 +35,17 @@ <%@ page import="org.dspace.core.ConfigurationManager" %> <%@ page import="org.dspace.handle.HandleManager" %> <%@ page import="org.dspace.license.CreativeCommons" %> - +<%@page import="javax.servlet.jsp.jstl.fmt.LocaleSupport"%> +<%@page import="org.dspace.versioning.Version"%> +<%@page import="org.dspace.core.Context"%> +<%@page import="org.dspace.app.webui.util.VersionUtil"%> +<%@page import="org.dspace.app.webui.util.UIUtil"%> +<%@page import="org.dspace.authorize.AuthorizeManager"%> +<%@page import="java.util.List"%> +<%@page import="org.dspace.core.Constants"%> +<%@page import="org.dspace.eperson.EPerson"%> +<%@page import="org.dspace.versioning.VersionHistory"%> +<%@page import="org.elasticsearch.common.trove.strategy.HashingStrategy"%> <% // Attributes Boolean displayAllBoolean = (Boolean) request.getAttribute("display.all"); @@ -47,7 +56,7 @@ Collection[] collections = (Collection[]) request.getAttribute("collections"); Boolean admin_b = (Boolean)request.getAttribute("admin_button"); boolean admin_button = (admin_b == null ? false : admin_b.booleanValue()); - + // get the workspace id if one has been passed Integer workspace_id = (Integer) request.getAttribute("workspace_id"); @@ -76,55 +85,104 @@ title = "Item " + handle; } } + + Boolean versioningEnabledBool = (Boolean)request.getAttribute("versioning.enabled"); + boolean versioningEnabled = (versioningEnabledBool!=null && versioningEnabledBool.booleanValue()); + Boolean hasVersionButtonBool = (Boolean)request.getAttribute("versioning.hasversionbutton"); + Boolean hasVersionHistoryBool = (Boolean)request.getAttribute("versioning.hasversionhistory"); + boolean hasVersionButton = (hasVersionButtonBool!=null && hasVersionButtonBool.booleanValue()); + boolean hasVersionHistory = (hasVersionHistoryBool!=null && hasVersionHistoryBool.booleanValue()); + + Boolean newversionavailableBool = (Boolean)request.getAttribute("versioning.newversionavailable"); + boolean newVersionAvailable = (newversionavailableBool!=null && newversionavailableBool.booleanValue()); + Boolean showVersionWorkflowAvailableBool = (Boolean)request.getAttribute("versioning.showversionwfavailable"); + boolean showVersionWorkflowAvailable = (showVersionWorkflowAvailableBool!=null && showVersionWorkflowAvailableBool.booleanValue()); + + String latestVersionHandle = (String)request.getAttribute("versioning.latestversionhandle"); + String latestVersionURL = (String)request.getAttribute("versioning.latestversionurl"); + + VersionHistory history = (VersionHistory)request.getAttribute("versioning.history"); + List<Version> historyVersions = (List<Version>)request.getAttribute("versioning.historyversions"); %> <%@page import="org.dspace.app.webui.servlet.MyDSpaceServlet"%> <dspace:layout title="<%= title %>"> - <% if (handle != null) { %> - <table align="center" class="miscTable"> - <tr> - <td class="evenRowEvenCol" align="center"> + <% + if (newVersionAvailable) + { + %> + <div class="alert alert-warning"><b><fmt:message key="jsp.version.notice.new_version_head"/></b> + <fmt:message key="jsp.version.notice.new_version_help"/><a href="<%=latestVersionURL %>"><%= latestVersionHandle %></a> + </div> + <% + } + %> + + <% + if (showVersionWorkflowAvailable) + { + %> + <div class="alert alert-warning"><b><fmt:message key="jsp.version.notice.workflow_version_head"/></b> + <fmt:message key="jsp.version.notice.workflow_version_help"/> + </div> + <% + } + %> + + <%-- <strong>Please use this identifier to cite or link to this item: <code><%= HandleManager.getCanonicalForm(handle) %></code></strong>--%> - <strong><fmt:message key="jsp.display-item.identifier"/> - <code><%= HandleManager.getCanonicalForm(handle) %></code></strong> - </td> + <div class="well"><fmt:message key="jsp.display-item.identifier"/> + <code><%= HandleManager.getCanonicalForm(handle) %></code></div> <% if (admin_button) // admin edit button { %> - <td class="evenRowEvenCol" align="center"> + <dspace:sidebar> + <div class="panel panel-warning"> + <div class="panel-heading"><fmt:message key="jsp.admintools"/></div> + <div class="panel-body"> + <form method="get" action="<%= request.getContextPath() %>/tools/edit-item"> + <input type="hidden" name="item_id" value="<%= item.getID() %>" /> + <%--<input type="submit" name="submit" value="Edit...">--%> + <input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.general.edit.button"/>" /> + </form> <form method="post" action="<%= request.getContextPath() %>/mydspace"> <input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="step" value="<%= MyDSpaceServlet.REQUEST_EXPORT_ARCHIVE %>" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.mydspace.request.export.item"/>" /> + <input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.mydspace.request.export.item"/>" /> </form> <form method="post" action="<%= request.getContextPath() %>/mydspace"> <input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="step" value="<%= MyDSpaceServlet.REQUEST_MIGRATE_ARCHIVE %>" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.mydspace.request.export.migrateitem"/>" /> + <input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.mydspace.request.export.migrateitem"/>" /> </form> <form method="post" action="<%= request.getContextPath() %>/dspace-admin/metadataexport"> <input type="hidden" name="handle" value="<%= item.getHandle() %>" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.general.metadataexport.button"/>" /> - </form> - - </td> - <td class="evenRowEvenCol" align="center"> - <form method="get" action="<%= request.getContextPath() %>/tools/edit-item"> - <input type="hidden" name="item_id" value="<%= item.getID() %>" /> - <%--<input type="submit" name="submit" value="Edit...">--%> - <input type="submit" name="submit" value="<fmt:message key="jsp.general.edit.button"/>" /> + <input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.general.metadataexport.button"/>" /> </form> - </td> + <% if(hasVersionButton) { %> + <form method="get" action="<%= request.getContextPath() %>/tools/version"> + <input type="hidden" name="itemID" value="<%= item.getID() %>" /> + <input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.general.version.button"/>" /> + </form> + <% } %> + <% if(hasVersionHistory) { %> + <form method="get" action="<%= request.getContextPath() %>/tools/history"> + <input type="hidden" name="itemID" value="<%= item.getID() %>" /> + <input type="hidden" name="versionID" value="<%= history.getVersion(item)!=null?history.getVersion(item).getVersionId():null %>" /> + <input class="btn btn-info col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.general.version.history.button"/>" /> + </form> + <% } %> + </div> + </div> + </dspace:sidebar> <% } %> - </tr> - </table> - <br /> + <% } @@ -132,91 +190,77 @@ %> <dspace:item-preview item="<%= item %>" /> <dspace:item item="<%= item %>" collections="<%= collections %>" style="<%= displayStyle %>" /> - +<div class="container row"> <% String locationLink = request.getContextPath() + "/handle/" + handle; if (displayAll) { %> - - <div align="center"> <% if (workspace_id != null) { %> - <form method="post" action="<%= request.getContextPath() %>/view-workspaceitem"> + <form class="col-md-2" method="post" action="<%= request.getContextPath() %>/view-workspaceitem"> <input type="hidden" name="workspace_id" value="<%= workspace_id.intValue() %>" /> - <input type="submit" name="submit_simple" value="<fmt:message key="jsp.display-item.text1"/>" /> + <input class="btn btn-default" type="submit" name="submit_simple" value="<fmt:message key="jsp.display-item.text1"/>" /> </form> <% } else { %> - <form method="get" action="<%=locationLink %>"> - <input type="hidden" name="mode" value="simple"/> - <input type="submit" name="submit_simple" value="<fmt:message key="jsp.display-item.text1"/>" /> - </form> + <a class="btn btn-default" href="<%=locationLink %>?mode=simple"> + <fmt:message key="jsp.display-item.text1"/> + </a> <% } %> - </div> <% } else { %> - <div align="center"> <% if (workspace_id != null) { %> - <form method="post" action="<%= request.getContextPath() %>/view-workspaceitem"> + <form class="col-md-2" method="post" action="<%= request.getContextPath() %>/view-workspaceitem"> <input type="hidden" name="workspace_id" value="<%= workspace_id.intValue() %>" /> - <input type="submit" name="submit_full" value="<fmt:message key="jsp.display-item.text2"/>" /> + <input class="btn btn-default" type="submit" name="submit_full" value="<fmt:message key="jsp.display-item.text2"/>" /> </form> <% } else { %> - <form method="get" action="<%=locationLink %>"> - <input type="hidden" name="mode" value="full"/> - <input type="submit" name="submit_simple" value="<fmt:message key="jsp.display-item.text2"/>" /> - </form> + <a class="btn btn-default" href="<%=locationLink %>?mode=full"> + <fmt:message key="jsp.display-item.text2"/> + </a> <% } - if (suggestLink) - { -%> - <a href="<%= request.getContextPath() %>/suggest?handle=<%= handle %>" target="new_window"> - <fmt:message key="jsp.display-item.suggest"/></a> -<% - } -%> - </div> -<% } -%> - -<div align="center"> - <a class="statisticsLink" href="<%= request.getContextPath() %>/handle/<%= handle %>/statistics"><fmt:message key="jsp.display-item.display-statistics"/></a> -</div> -<% if (workspace_id != null) { %> -<div align="center"> - <form method="post" action="<%= request.getContextPath() %>/workspace"> + <form class="col-md-2" method="post" action="<%= request.getContextPath() %>/workspace"> <input type="hidden" name="workspace_id" value="<%= workspace_id.intValue() %>"/> - <input type="submit" name="submit_open" value="<fmt:message key="jsp.display-item.back_to_workspace"/>"/> + <input class="btn btn-primary" type="submit" name="submit_open" value="<fmt:message key="jsp.display-item.back_to_workspace"/>"/> </form> -</div> <% - } + } else { + + if (suggestLink) + { +%> + <a class="btn btn-success" href="<%= request.getContextPath() %>/suggest?handle=<%= handle %>" target="new_window"> + <fmt:message key="jsp.display-item.suggest"/></a> +<% + } %> + <a class="statisticsLink btn btn-primary" href="<%= request.getContextPath() %>/handle/<%= handle %>/statistics"><fmt:message key="jsp.display-item.display-statistics"/></a> + <%-- SFX Link --%> <% if (ConfigurationManager.getProperty("sfx.server.url") != null) @@ -227,25 +271,76 @@ sfximage = request.getContextPath() + "/image/sfx-link.gif"; } %> - <p align="center"> - <a href="<dspace:sfxlink item="<%= item %>"/>" /><img src="<%= sfximage %>" border="0" alt="SFX Query" /></a> - </p> + <a class="btn btn-default" href="<dspace:sfxlink item="<%= item %>"/>" /><img src="<%= sfximage %>" border="0" alt="SFX Query" /></a> +<% + } + } +%> +</div> +<br/> + <%-- Versioning table --%> <% + if (versioningEnabled && hasVersionHistory) + { + boolean item_history_view_admin = ConfigurationManager + .getBooleanProperty("versioning", "item.history.view.admin"); + if(!item_history_view_admin || admin_button) { +%> + <div id="versionHistory" class="panel panel-info"> + <div class="panel-heading"><fmt:message key="jsp.version.history.head2" /></div> + + <table class="table panel-body"> + <tr> + <th id="tt1" class="oddRowEvenCol"><fmt:message key="jsp.version.history.column1"/></th> + <th + id="tt2" class="oddRowOddCol"><fmt:message key="jsp.version.history.column2"/></th> + <th + id="tt3" class="oddRowEvenCol"><fmt:message key="jsp.version.history.column3"/></th> + <th + + id="tt4" class="oddRowOddCol"><fmt:message key="jsp.version.history.column4"/></th> + <th + id="tt5" class="oddRowEvenCol"><fmt:message key="jsp.version.history.column5"/> </th> + </tr> + + <% for(Version versRow : historyVersions) { + + EPerson versRowPerson = versRow.getEperson(); + String[] identifierPath = VersionUtil.addItemIdentifier(item, versRow); + %> + <tr> + <td headers="tt1" class="oddRowEvenCol"><%= versRow.getVersionNumber() %></td> + <td headers="tt2" class="oddRowOddCol"><a href="<%= request.getContextPath() + identifierPath[0] %>"><%= identifierPath[1] %></a><%= item.getID()==versRow.getItemID()?"<span class=\"glyphicon glyphicon-asterisk\"></span>":""%></td> + <td headers="tt3" class="oddRowEvenCol"><% if(admin_button) { %><a + href="mailto:<%= versRowPerson.getEmail() %>"><%=versRowPerson.getFullName() %></a><% } else { %><%=versRowPerson.getFullName() %><% } %></td> + <td headers="tt4" class="oddRowOddCol"><%= versRow.getVersionDate() %></td> + <td headers="tt5" class="oddRowEvenCol"><%= versRow.getSummary() %></td> + </tr> + <% } %> + </table> + <div class="panel-footer"><fmt:message key="jsp.version.history.legend"/></div> + </div> +<% + } } %> +<br/> <%-- Create Commons Link --%> <% if (cc_url != null) { %> - <p class="submitFormHelp"><fmt:message key="jsp.display-item.text3"/> <a href="<%= cc_url %>"><fmt:message key="jsp.display-item.license"/></a><br/> - <a href="<%= cc_url %>"><img src="<%= request.getContextPath() %>/image/cc-somerights.gif" border="0" alt="Creative Commons" /></a> + <p class="submitFormHelp alert alert-info"><fmt:message key="jsp.display-item.text3"/> <a href="<%= cc_url %>"><fmt:message key="jsp.display-item.license"/></a> + <a href="<%= cc_url %>"><img src="<%= request.getContextPath() %>/image/cc-somerights.gif" border="0" alt="Creative Commons" style="margin-top: -5px;" class="pull-right"/></a> </p> <!-- <%= cc_rdf %> --> <% - } + } else { %> - <p class="submitFormHelp"><fmt:message key="jsp.display-item.copyright"/></p> + <p class="submitFormHelp alert alert-info"><fmt:message key="jsp.display-item.copyright"/></p> +<% + } +%> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/authorize-advanced.jsp b/dspace-jspui/src/main/webapp/dspace-admin/authorize-advanced.jsp index af7f1d048ed5899b1564081de0b54f0aa79e2978..c66a43c6eddcd5d4142b9387a26e69192d3296fc 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/authorize-advanced.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/authorize-advanced.jsp @@ -47,92 +47,82 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.dspace-admin.authorize-advanced.advanced" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.authorize-advanced.advanced" navbar="admin" locbar="link" parentlink="/dspace-admin" parenttitlekey="jsp.administer"> -<h1><fmt:message key="jsp.dspace-admin.authorize-advanced.advanced"/></h1> +<h1><fmt:message key="jsp.dspace-admin.authorize-advanced.advanced"/> +<dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") +\"#advancedpolicies\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> +</h1> <%-- <p>Allows you to do wildcard additions to and clearing of policies for types of content contained in a collection. Warning, dangerous - removing READ permissions from items will make them not viewable! <dspace:popup page="/help/site-admin.html#advancedpolicies">More help...</dspace:popup></p> --%> - <div><fmt:message key="jsp.dspace-admin.authorize-advanced.text"/> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") +\"#advancedpolicies\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <div class="alert alert-info"><fmt:message key="jsp.dspace-admin.authorize-advanced.text"/></div> <form method="post" action=""> - - <table class="miscTable" align="center" summary="Advanced policy manager"> - <tr> + <%-- <td>Collection:</td> --%> - <th id="t1"><label for ="tcollection"><fmt:message key="jsp.dspace-admin.authorize-advanced.col"/></label></th> - <td headers="t1"> - <select size="10" name="collection_id" id="tcollection"> + <div class="input-group"> + <span class="col-md-2"><label for="tcollection"><fmt:message key="jsp.dspace-admin.authorize-advanced.col"/></label></span> + <span class="col-md-10"> + <select class="form-control" size="10" name="collection_id" id="tcollection"> <% for(int i = 0; i < collections.length; i++ ) { %> <option value="<%= collections[i].getID() %>"> <%= collections[i].getMetadata("name")%> </option> <% } %> </select> - </td> - </tr> - - <tr> + </span> + <%-- <td>Content Type:</td> --%> - <th id="t2"><label for="tresource_type"><fmt:message key="jsp.dspace-admin.authorize-advanced.type"/></label></th> - <td headers="t2"> - <select name="resource_type" id="tresource_type"> + <span class="col-md-2"><label for="tresource_type"><fmt:message key="jsp.dspace-admin.authorize-advanced.type"/></label></span> + <span class="col-md-10"> + <select class="form-control" name="resource_type" id="tresource_type"> <%-- <option value="<%=Constants.ITEM%>">item</option> <option value="<%=Constants.BITSTREAM%>">bitstream</option> --%> <option value="<%=Constants.ITEM%>"><fmt:message key="jsp.dspace-admin.authorize-advanced.type1"/></option> <option value="<%=Constants.BITSTREAM%>"><fmt:message key="jsp.dspace-admin.authorize-advanced.type2"/></option> </select> - </td> - </tr> - - <tr> + </span> + <%-- <td>Group:</td> --%> - <th id="t3"><fmt:message key="jsp.dspace-admin.general.group-colon"/></th> - <td headers="t3"> - <select size="10" name="group_id" id="tgroup_id"> + <span class="col-md-2"> + <label for="tgroup_id"><fmt:message key="jsp.dspace-admin.general.group-colon"/></label> + </span> + <span class="col-md-10"> + <select class="form-control" size="10" name="group_id" id="tgroup_id"> <% for(int i = 0; i < groups.length; i++ ) { %> <option value="<%= groups[i].getID() %>"> <%= groups[i].getName()%> </option> <% } %> </select> - </td> - </tr> - - <tr> - <%-- <tr><td>Action:</td> --%> - <th id="t4"><label for="taction_id"><fmt:message key="jsp.dspace-admin.general.action-colon"/></label></th> - <td headers="t4"> - <select name="action_id" id="taction_id"> + </span> + + <span class="col-md-2"> + <%-- <tr><td>Action:</td> --%> + <label for="taction_id"><fmt:message key="jsp.dspace-admin.general.action-colon"/></label> + </span> + <span class="col-md-10"> + <select class="form-control" name="action_id" id="taction_id"> <% for( int i = 0; i < Constants.actionText.length; i++ ) { %> <option value="<%= i %>"> <%= Constants.actionText[i]%> </option> <% } %> </select> - </td> - </tr> - - </table> - - <center> - <table width="70%"> - <tr> - <td align="left"> - <%-- <input type="submit" name="submit_advanced_add" value="Add Policy"> --%> - <input type="submit" name="submit_advanced_add" value="<fmt:message key="jsp.dspace-admin.authorize-advanced.add"/>" /> - </td> - <td align="right"> - <%-- <input type="submit" name="submit_advanced_clear" value="Clear Policies"> (warning: clears all policies for a given set of objects) --%> - <input type="submit" name="submit_advanced_clear" value="<fmt:message key="jsp.dspace-admin.authorize-advanced.clear"/>" /></td> <td><fmt:message key="jsp.dspace-admin.authorize-advanced.warning"/> - </td> - </tr> - </table> - </center> + </span> + </div> + + <br/> + <div class="btn-group"> + <%-- <input type="submit" name="submit_advanced_add" value="Add Policy"> --%> + <input class="btn btn-primary" type="submit" name="submit_advanced_add" value="<fmt:message key="jsp.dspace-admin.authorize-advanced.add"/>" /> + <%-- <input type="submit" name="submit_advanced_clear" value="Clear Policies"> (warning: clears all policies for a given set of objects) --%> + <input class="btn btn-danger" type="submit" name="submit_advanced_clear" value="<fmt:message key="jsp.dspace-admin.authorize-advanced.clear"/>" /><span class="alert alert-warning"><fmt:message key="jsp.dspace-admin.authorize-advanced.warning"/></span> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/authorize-collection-edit.jsp b/dspace-jspui/src/main/webapp/dspace-admin/authorize-collection-edit.jsp index 03bfd1600cdc1a0f3cb9e5a024b13403034a8b74..b9990de0cb9065d860462bd2e4dea7ae34bf98f3 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/authorize-collection-edit.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/authorize-collection-edit.jsp @@ -50,43 +50,30 @@ (List<ResourcePolicy>) request.getAttribute("policies"); %> -<dspace:layout titlekey="jsp.dspace-admin.authorize-collection-edit.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.authorize-collection-edit.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin" nocache="true"> - <table width="95%"> - <tr> - <td align="left"> - <h1><fmt:message key="jsp.dspace-admin.authorize-collection-edit.policies"> + <h1><fmt:message key="jsp.dspace-admin.authorize-collection-edit.policies"> <fmt:param><%= collection.getMetadata("name") %></fmt:param> <fmt:param>hdl:<%= collection.getHandle() %></fmt:param> <fmt:param><%= collection.getID() %></fmt:param> - </fmt:message></h1> - </td> - <td align="right" class="standard"> + </fmt:message> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#collectionpolicies\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + </h1> + <form action="<%= request.getContextPath() %>/tools/authorize" method="post"> - <p align="center"> + <div class="row"> <input type="hidden" name="collection_id" value="<%=collection.getID()%>" /> - <input type="submit" name="submit_collection_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> - </p> + <input class="btn btn-success col-md-2 col-md-offset-5" type="submit" name="submit_collection_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> + </div> </form> - -<% - String row = "even"; - - for (ResourcePolicy rp : policies) - { -%> - <form action="<%= request.getContextPath() %>/tools/authorize" method="post"> - <table class="miscTable" align="center" summary="Collection Policy Edit Form"> + <br/> + <table class="table" summary="Collection Policy Edit Form"> <tr> <th class="oddRowOddCol"><strong><fmt:message key="jsp.general.id" /></strong></th> <th class="oddRowEvenCol"><strong><fmt:message key="jsp.dspace-admin.general.action"/></strong></th> @@ -94,7 +81,13 @@ <th class="oddRowEvenCol"> </th> <th class="oddRowOddCol"> </th> </tr> + +<% + String row = "even"; + for (ResourcePolicy rp : policies) + { +%> <tr> <td class="<%= row %>RowOddCol"><%= rp.getID() %></td> <td class="<%= row %>RowEvenCol"> @@ -104,19 +97,24 @@ <%= (rp.getGroup() == null ? "..." : rp.getGroup().getName() ) %> </td> <td class="<%= row %>RowEvenCol"> + <form action="<%= request.getContextPath() %>/tools/authorize" method="post"> <input type="hidden" name="policy_id" value="<%= rp.getID() %>" /> <input type="hidden" name="collection_id" value="<%= collection.getID() %>" /> - <input type="submit" name="submit_collection_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> + <input class="btn btn-primary" type="submit" name="submit_collection_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> + </form> </td> <td class="<%= row %>RowOddCol"> - <input type="submit" name="submit_collection_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + <form action="<%= request.getContextPath() %>/tools/authorize" method="post"> + <input type="hidden" name="policy_id" value="<%= rp.getID() %>" /> + <input type="hidden" name="collection_id" value="<%= collection.getID() %>" /> + <input class="btn btn-danger" type="submit" name="submit_collection_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + </form> </td> </tr> - </table> - </form> <% row = (row.equals("odd") ? "even" : "odd"); } %> + </table> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/authorize-community-edit.jsp b/dspace-jspui/src/main/webapp/dspace-admin/authorize-community-edit.jsp index d7cb8bf2c4616b4be8ce93405ab4fb795327a9bb..8baff92251b1d4725e4a715a73d264004376dace 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/authorize-community-edit.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/authorize-community-edit.jsp @@ -50,35 +50,30 @@ (List<ResourcePolicy>) request.getAttribute("policies"); %> -<dspace:layout titlekey="jsp.dspace-admin.authorize-community-edit.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.authorize-community-edit.title" navbar="admin" locbar="link" - parenttitle="general.administer" + parenttitlekey="jsp.administer" parentlink="/dspace-admin" nocache="true"> - <table width="95%"> - <tr> - <td align="left"> + <h1><fmt:message key="jsp.dspace-admin.authorize-community-edit.policies"> <fmt:param><%= community.getMetadata("name") %></fmt:param> <fmt:param>hdl:<%= community.getHandle() %></fmt:param> <fmt:param><%=community.getID()%></fmt:param> - </fmt:message></h1> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#communitypolicies\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + </fmt:message> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#communitypolicies\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </h1> + <form action="<%= request.getContextPath() %>/tools/authorize" method="post"> - <p align="center"> + <div class="row"> <input type="hidden" name="community_id" value="<%=community.getID()%>" /> - <input type="submit" name="submit_community_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> - </p> + <input class="btn btn-success col-md-2 col-md-offset-5" type="submit" name="submit_community_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> + </div> </form> - - <table class="miscTable" align="center" summary="Community Policy Edit Form"> + <br/> + <table class="table" summary="Community Policy Edit Form"> <tr> <th id="t1" class="oddRowOddCol"><strong><fmt:message key="jsp.general.id" /></strong></th> @@ -105,14 +100,14 @@ <form action="<%= request.getContextPath() %>/tools/authorize" method="post"> <input type="hidden" name="policy_id" value="<%= rp.getID() %>" /> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> - <input type="submit" name="submit_community_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> + <input class="btn btn-primary" type="submit" name="submit_community_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> </form> </td> <td headers="t5" class="<%= row %>RowOddCol"> <form action="<%= request.getContextPath() %>/tools/authorize" method="post"> <input type="hidden" name="policy_id" value="<%= rp.getID() %>" /> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> - <input type="submit" name="submit_community_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + <input class="btn btn-danger" type="submit" name="submit_community_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> </form> </td> </tr> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/authorize-item-edit.jsp b/dspace-jspui/src/main/webapp/dspace-admin/authorize-item-edit.jsp index cac87b67610a89bd1c269d4b1bbdd4cf7a49410a..d304a7603bc8b892bc8402151360c934650d3ccf 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/authorize-item-edit.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/authorize-item-edit.jsp @@ -69,39 +69,36 @@ Map bitstream_policies = (Map)request.getAttribute("bitstream_policies"); %> -<dspace:layout titlekey="jsp.dspace-admin.authorize-item-edit.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.authorize-item-edit.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin" nocache="true"> - <table width="95%"> - <tr> - <td align="left"> + <h1><fmt:message key="jsp.dspace-admin.authorize-item-edit.policies"> <fmt:param><%= item.getHandle() %></fmt:param> <fmt:param><%= item.getID() %></fmt:param> - </fmt:message></h1> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#itempolicies\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + </fmt:message> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#itempolicies\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </h1> - <p><fmt:message key="jsp.dspace-admin.authorize-item-edit.text1"/></p> - <p><fmt:message key="jsp.dspace-admin.authorize-item-edit.text2"/></p> + <p class="help-block"><fmt:message key="jsp.dspace-admin.authorize-item-edit.text1"/></p> + <p class="help-block"><fmt:message key="jsp.dspace-admin.authorize-item-edit.text2"/></p> - <h3><fmt:message key="jsp.dspace-admin.authorize-item-edit.item"/></h3> + <div class="panel panel-primary"> + <div class="panel-heading"><fmt:message key="jsp.dspace-admin.authorize-item-edit.item"/></div> + <div class="panel-body"> <form method="post" action=""> - <p align="center"> + <div class="row col-md-offset-4"> <input type="hidden" name="item_id" value="<%=item.getID()%>" /> - <input type="submit" name="submit_item_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> - </p> + <input class="btn btn-success col-md-4" type="submit" name="submit_item_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> + </div> </form> + <br/> - <table class="miscTable" align="center" summary="Item Policy Edit Form"> + <table class="table" summary="Item Policy Edit Form"> <tr> <th class="oddRowOddCol"><strong><fmt:message key="jsp.general.id" /></strong></th> <th class="oddRowEvenCol"><strong><fmt:message key="jsp.dspace-admin.general.action"/></strong></th> @@ -129,8 +126,8 @@ <form method="post" action=""> <input type="hidden" name="policy_id" value="<%= rp.getID() %>" /> <input type="hidden" name="item_id" value="<%= item.getID() %>" /> - <input type="submit" name="submit_item_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> - <input type="submit" name="submit_item_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + <input class="btn btn-primary col-md-4" type="submit" name="submit_item_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> + <input class="btn btn-danger col-md-4 col-md-offset-1" type="submit" name="submit_item_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> </form> </td> </tr> @@ -139,6 +136,8 @@ } %> </table> + </div> + </div> <% for( int b = 0; b < bundles.length; b++ ) { @@ -148,21 +147,23 @@ // display add policy // display bundle header w/ID -%> - <h3><fmt:message key="jsp.dspace-admin.authorize-item-edit.bundle"> +%> + <div class="panel panel-info"> + <div class="panel-heading"> + <fmt:message key="jsp.dspace-admin.authorize-item-edit.bundle"> <fmt:param><%=myBun.getName()%></fmt:param> <fmt:param><%=myBun.getID()%></fmt:param> - </fmt:message></h3> - + </fmt:message></div> + <div class="panel-body"> <form method="post" action=""> - <p align="center"> + <div class="row col-md-offset-4"> <input type="hidden" name="item_id" value="<%=item.getID()%>" /> <input type="hidden" name="bundle_id" value="<%=myBun.getID()%>" /> - <input type="submit" name="submit_bundle_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> - </p> - </form> - - <table class="miscTable" align="center" summary="Bundle Policy Edit Form"> + <input class="btn btn-success col-md-4" type="submit" name="submit_bundle_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> + </div> + </form> + <br/> + <table class="table" summary="Bundle Policy Edit Form"> <tr> <th class="oddRowOddCol"><strong><fmt:message key="jsp.general.id" /></strong></th> <th class="oddRowEvenCol"><strong><fmt:message key="jsp.dspace-admin.general.action"/></strong></th> @@ -192,8 +193,8 @@ <input type="hidden" name="policy_id" value="<%= rp.getID() %>" /> <input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="bundle_id" value="<%= myBun.getID() %>" /> - <input type="submit" name="submit_item_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> - <input type="submit" name="submit_item_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + <input class="btn btn-primary col-md-4" type="submit" name="submit_item_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> + <input class="btn btn-danger col-md-4 col-md-offset-1" type="submit" name="submit_item_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> </form> </td> </tr> @@ -202,7 +203,6 @@ } %> </table> - <% Bitstream [] bitstreams = myBun.getBitstreams(); @@ -215,18 +215,23 @@ // 'add policy' // display bitstream's policies %> - <p><fmt:message key="jsp.dspace-admin.authorize-item-edit.bitstream"> + <div class="panel panel-success"> + <div class="panel-heading"> + <fmt:message key="jsp.dspace-admin.authorize-item-edit.bitstream"> <fmt:param><%=myBits.getID()%></fmt:param> <fmt:param><%=myBits.getName()%></fmt:param> - </fmt:message></p> + </fmt:message></div> + + <div class="panel-body"> <form method="post" action=""> - <p align="center"> + <div class="row col-md-offset-4"> <input type="hidden" name="item_id"value="<%=item.getID()%>" /> <input type="hidden" name="bitstream_id" value="<%=myBits.getID()%>" /> - <input type="submit" name="submit_bitstream_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> - </p> + <input class="btn btn-success col-md-4" type="submit" name="submit_bitstream_add_policy" value="<fmt:message key="jsp.dspace-admin.general.addpolicy"/>" /> + </div> </form> - <table class="miscTable" align="center" summary="This table displays the bitstream data"> + <br/> + <table class="table" summary="This table displays the bitstream data"> <tr> <th class="oddRowOddCol"><strong><fmt:message key="jsp.general.id" /></strong></th> <th class="oddRowEvenCol"><strong><fmt:message key="jsp.dspace-admin.general.action"/></strong></th> @@ -256,8 +261,8 @@ <input type="hidden" name="policy_id" value="<%= rp.getID() %>" /> <input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="bitstream_id" value="<%= myBits.getID() %>" /> - <input type="submit" name="submit_item_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> - <input type="submit" name="submit_item_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + <input class="btn btn-primary col-md-4" type="submit" name="submit_item_edit_policy" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> + <input class="btn btn-danger col-md-4 col-md-offset-1" type="submit" name="submit_item_delete_policy" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> </form> </td> </tr> @@ -266,9 +271,15 @@ } %> </table> + </div> + </div> <% } + %> + </div> +</div> + <% } %> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/authorize-main.jsp b/dspace-jspui/src/main/webapp/dspace-admin/authorize-main.jsp index 56bcc8079cbc14e30155b7bc149de9b73f3ca294..219aec5b886c6378cf094f00def55e18df65de75 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/authorize-main.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/authorize-main.jsp @@ -41,57 +41,44 @@ // this space intentionally left blank %> -<dspace:layout titlekey="jsp.dspace-admin.authorize-main.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.authorize-main.title" navbar="admin" locbar="link" - parenttitle="general.administer" + parenttitlekey="jsp.administer" parentlink="/dspace-admin"> <%-- <h1>Administer Authorization Policies</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.authorize-main.adm"/></h1> - <table width="95%"> - <tr> - <td align="left"> + <h1><fmt:message key="jsp.dspace-admin.authorize-main.adm"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#authorize\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </h1> + <%-- <h3>Choose a resource to manage policies for:</h3> --%> <h3><fmt:message key="jsp.dspace-admin.authorize-main.choose"/></h3> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#authorize\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + + + <form method="post" action=""> - <center> - <table width="70%"> - <tr> - <td align="center"> + <div class="btn-group col-md-offset-5"> + <div class="row"> <%-- <input type="submit" name="submit_community" value="Manage a Community's Policies"> --%> - <input type="submit" name="submit_community" value="<fmt:message key="jsp.dspace-admin.authorize-main.manage1"/>" /> - </td> - </tr> - <tr> - <td align="center"> + <input class="btn btn-default col-md-12" type="submit" name="submit_community" value="<fmt:message key="jsp.dspace-admin.authorize-main.manage1"/>" /> + </div> + <div class="row"> <%-- <input type="submit" name="submit_collection" value="Manage Collection's Policies"> --%> - <input type="submit" name="submit_collection" value="<fmt:message key="jsp.dspace-admin.authorize-main.manage2"/>" /> - </td> - </tr> - <tr> - <td align="center"> + <input class="btn btn-default col-md-12" type="submit" name="submit_collection" value="<fmt:message key="jsp.dspace-admin.authorize-main.manage2"/>" /> + </div> + <div class="row"> <%-- <input type="submit" name="submit_item" value="Manage An Item's Policies"> --%> - <input type="submit" name="submit_item" value="<fmt:message key="jsp.dspace-admin.authorize-main.manage3"/>" /> - </td> - </tr> - <tr> - <td align="center"> + <input class="btn btn-default col-md-12" type="submit" name="submit_item" value="<fmt:message key="jsp.dspace-admin.authorize-main.manage3"/>" /> + </div> + <div class="row"> <%-- <input type="submit" name="submit_advanced" value="Advanced/Item Wildcard Policy Admin Tool"> --%> - <input type="submit" name="submit_advanced" value="<fmt:message key="jsp.dspace-admin.authorize-main.advanced"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-default col-md-12" type="submit" name="submit_advanced" value="<fmt:message key="jsp.dspace-admin.authorize-main.advanced"/>" /> + </div> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/authorize-policy-edit.jsp b/dspace-jspui/src/main/webapp/dspace-admin/authorize-policy-edit.jsp index 31d0cc94e1fa2afc3c1b0a4926fba8dc1b4f69cf..aea3929137cba6d17b863dfe26eaea3ea4529ec1 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/authorize-policy-edit.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/authorize-policy-edit.jsp @@ -65,49 +65,45 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.dspace-admin.authorize-policy-edit.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.authorize-policy-edit.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin" nocache="true"> - <table width="95%"> - <tr> - <td align="left"> + <%-- <h1>Edit Policy for <%= edit_title %>:</h1> --%> <h1><fmt:message key="jsp.dspace-admin.authorize-policy-edit.heading"> <fmt:param><%= edit_title %></fmt:param> - </fmt:message></h1> - </td> - <td align="right" class="standard"> + </fmt:message> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#authorize\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - + </h1> + <form action="<%= request.getContextPath() %>/tools/authorize" method="post"> - <table class="miscTable" align="center" summary="Edit Policy Form"> - <tr> - <%-- <td>Group:</td> --%> - <th id="t1"><label for="tgroup_id"><fmt:message key="jsp.dspace-admin.general.group-colon"/></label></th> - <td headers="t1"> - <select size="15" name="group_id" id="tgroup_id"> + <div class="input-group"> + <span class="col-md-2"> + <%-- <td>Group:</td> --%> + <label for="tgroup_id"><fmt:message key="jsp.dspace-admin.general.group-colon"/></label> + </span> + <span class="col-md-10"> + <select class="form-control" size="15" name="group_id" id="tgroup_id"> <% for(int i = 0; i < groups.length; i++ ) { %> <option value="<%= groups[i].getID() %>" <%= (groups[i].getID() == policy.getGroupID() ? "selected=\"selected\"" : "" ) %> > <%= groups[i].getName()%> </option> <% } %> </select> - </td> - </tr> + </span> + <%-- <tr><td>Action:</td> --%> - <tr> - <th id="t2"><label for="taction_id"><fmt:message key="jsp.dspace-admin.general.action-colon"/></label></th> - <td headers="t2"> + <span class="col-md-2"> + <label for="taction_id"><fmt:message key="jsp.dspace-admin.general.action-colon"/></label> + </span> + <span class="col-md-10"> <input type="hidden" name="<%=id_name%>" value="<%=id%>" /> <input type="hidden" name="policy_id" value="<%=policy.getID()%>" /> - <select name="action_id" id="taction_id"> + <select class="form-control" name="action_id" id="taction_id"> <% for( int i = 0; i < Constants.actionText.length; i++ ) { // only display if action i is relevant @@ -121,26 +117,16 @@ <% } } %> </select> - </td> - </tr> - </table> - + </span> + </div> <% if( newpolicy != null ) { %> <input name="newpolicy" type="hidden" value="<%=newpolicy%>"/> <% } %> - <center> - <table width="70%"> - <tr> - <td align="left"> + <div class="btn-group pull-right col-md-2"> <%-- <input type="submit" name="submit_save_policy" value="Save Policy"> --%> - <input type="submit" name="submit_save_policy" value="<fmt:message key="jsp.dspace-admin.general.save"/>" /> - </td> - <td align="right"> - <%-- <input type="submit" name="submit_cancel_policy" value="Cancel"> --%> - <input type="submit" name="submit_cancel_policy" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-primary" type="submit" name="submit_save_policy" value="<fmt:message key="jsp.dspace-admin.general.save"/>" /> + <%-- <input type="submit" name="submit_cancel_policy" value="Cancel"> --%> + <input class="btn btn-default" type="submit" name="submit_cancel_policy" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/collection-select.jsp b/dspace-jspui/src/main/webapp/dspace-admin/collection-select.jsp index a4edd737b3936dcea2b980a47ce0765dd919d18f..2a6eb1991b74061bce1778f13ca070f31de606d9 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/collection-select.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/collection-select.jsp @@ -38,7 +38,7 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.dspace-admin.collection-select.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.collection-select.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -48,35 +48,23 @@ <h1><fmt:message key="jsp.dspace-admin.collection-select.col"/></h1> <form method="post" action=""> - - <table class="miscTable" align="center" summary="Collection selection table"> - <tr> - <td> - <select size="12" name="collection_id"> + <div class="row col-md-4 col-md-offset-4"> + <select class="form-control" size="12" name="collection_id"> <% for (int i = 0; i < collections.length; i++) { %> <option value="<%= collections[i].getID()%>"> <%= collections[i].getMetadata("name")%> </option> <% } %> </select> - </td> - </tr> - </table> - - <center> - <table width="70%"> - <tr> - <td align="left"> + </div> + <br/> + <div class="btn-group pull-right col-md-7"> <%-- <input type="submit" name="submit_collection_select" value="Edit Policies"> --%> - <input type="submit" name="submit_collection_select" value="<fmt:message key="jsp.dspace-admin.general.editpolicy"/>" /> - </td> - <td align="right"> + <input class="btn btn-primary" type="submit" name="submit_collection_select" value="<fmt:message key="jsp.dspace-admin.general.editpolicy"/>" /> + <%-- <input type="submit" name="submit_collection_select_cancel" value="Cancel"> --%> - <input type="submit" name="submit_collection_select_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-default" type="submit" name="submit_collection_select_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/community-select.jsp b/dspace-jspui/src/main/webapp/dspace-admin/community-select.jsp index 9184b280f8dfee1bb0a5f82718e0357eaac6a98c..594f689d14a102995b68b3657058af1451886cf5 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/community-select.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/community-select.jsp @@ -38,7 +38,7 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.dspace-admin.community-select.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.community-select.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -49,34 +49,25 @@ <form method="post" action=""> - <table class="miscTable" align="center" summary="Community selection table"> - <tr> - <td> - <select size="12" name="community_id"> + <div class="row col-md-4 col-md-offset-4"> + <select class="form-control" size="12" name="community_id"> <% for (int i = 0; i < communities.length; i++) { %> <option value="<%= communities[i].getID()%>"> <%= communities[i].getMetadata("name")%> </option> <% } %> </select> - </td> - </tr> - </table> - - <center> - <table width="70%"> - <tr> - <td align="left"> + </div> + <br/> + <div class="btn-group pull-right col-md-7"> <%-- <input type="submit" name="submit_community_select" value="Edit Policies"> --%> - <input type="submit" name="submit_community_select" value="<fmt:message key="jsp.dspace-admin.general.editpolicy"/>" /> - </td> - <td align="right"> + + <input class="btn btn-primary" type="submit" name="submit_community_select" value="<fmt:message key="jsp.dspace-admin.general.editpolicy"/>" /> + <%-- <input type="submit" name="submit_community_select_cancel" value="Cancel"> --%> - <input type="submit" name="submit_community_select_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-default" type="submit" name="submit_community_select_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-format.jsp b/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-format.jsp index bc7b9b938f5a1770267297f039e533335a1d39f0..7782107c8d5e875ef6d2ecd5165096706a9112dc 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-format.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-format.jsp @@ -27,7 +27,7 @@ BitstreamFormat format = (BitstreamFormat) request.getAttribute("format"); %> -<dspace:layout titlekey="jsp.dspace-admin.confirm-delete-format.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.confirm-delete-format.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -40,30 +40,22 @@ <%-- <p>Are you sure the format <strong><%= format.getShortDescription() %></strong> should be deleted?</p> --%> - <p><fmt:message key="jsp.dspace-admin.confirm-delete-format.confirm"> + <p class="alert alert-info"><fmt:message key="jsp.dspace-admin.confirm-delete-format.confirm"> <fmt:param><%= format.getShortDescription() %></fmt:param> </fmt:message></p> <%-- <p>Any existing bitstreams of this format will be reverted to the <em>unknown</em> bitstream format.</p> --%> - <p><fmt:message key="jsp.dspace-admin.confirm-delete-format.warning"/></p> + <p class="alert alert-warning"><fmt:message key="jsp.dspace-admin.confirm-delete-format.warning"/></p> <form method="post" action=""> - <input type="hidden" name="format_id" value="<%= format.getID() %>"/> - - <center> - <table width="70%"> - <tr> - <td align="left"> + <input type="hidden" name="format_id" value="<%= format.getID() %>"/> + <div class="btn-group"> <%-- <input type="submit" name="submit_confirm_delete" value="Delete"> --%> - <input type="submit" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> - </td> - <td align="right"> + <input class="btn btn-danger" type="submit" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + <%-- <input type="submit" name="submit_cancel" value="Cancel"> --%> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-default" type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-mdfield.jsp b/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-mdfield.jsp index d5e5f13625e03e87fe024513c6cfa87688696482..bda5d8d41f983aa0e7b419a533efa0132cf491c1 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-mdfield.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-mdfield.jsp @@ -36,7 +36,7 @@ } %> -<dspace:layout titlekey="jsp.dspace-admin.confirm-delete-mdfield.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.confirm-delete-mdfield.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -49,32 +49,26 @@ <%-- <P>Are you sure the metadata field <strong><%= typeName %></strong> should be deleted?</p> --%> - <p><fmt:message key="jsp.dspace-admin.confirm-delete-mdfield.confirm"> + <p class="alert alert-info"><fmt:message key="jsp.dspace-admin.confirm-delete-mdfield.confirm"> <fmt:param><%= typeName %></fmt:param> </fmt:message></p> <% if (!failed) { %> <%-- <P>This will result in an error if any items have values for this metadata field.</P> --%> - <p><fmt:message key="jsp.dspace-admin.confirm-delete-mdfield.warning"/></p> + <p class="alert alert-warning"><fmt:message key="jsp.dspace-admin.confirm-delete-mdfield.warning"/></p> <form method="post" action=""> <input type="hidden" name="dc_type_id" value="<%= type.getFieldID() %>"> - <center> - <table width="70%"> - <tr> - <td align="left"> + <div class="btn-group"> <%-- <input type="submit" name="submit_confirm_delete" value="Delete"> --%> - <input type="submit" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + <input class="btn btn-danger" type="submit" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> <%-- <input type="submit" name="submit_cancel" value="Cancel"> --%> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-default" type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> </form><% } else {%> <%-- <P>Unable to delete this metadata field. This is most likely to be because it is referenced by at least one item.</P> --%> - <p><strong><fmt:message key="jsp.dspace-admin.confirm-delete-mdfield.failed"/></strong></p><% + <p class="alert alert-danger"><fmt:message key="jsp.dspace-admin.confirm-delete-mdfield.failed"/></p><% } %> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-mdschema.jsp b/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-mdschema.jsp index 8a952e340d17d980632d0f3424c5847a92588813..622f85e6f68648bbd5f91130c495bfa0e80d456f 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-mdschema.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/confirm-delete-mdschema.jsp @@ -27,7 +27,7 @@ MetadataSchema schema = (MetadataSchema) request.getAttribute("schema"); %> -<dspace:layout titlekey="jsp.dspace-admin.confirm-delete-dcschema.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.confirm-delete-dcschema.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -40,27 +40,20 @@ <%-- <P>Are you sure the schema <strong><%= schema.getNamespace() %></strong> should be deleted?</P> --%> - <P><fmt:message key="jsp.dspace-admin.confirm-delete-mdschema.confirm"> + <p class="alert alert-info"><fmt:message key="jsp.dspace-admin.confirm-delete-mdschema.confirm"> <fmt:param><%= schema.getName() %></fmt:param> </fmt:message></P> <%-- <P>This will result in an error if any metadata fields exist within this schema.</P> --%> - <P><fmt:message key="jsp.dspace-admin.confirm-delete-mdschema.warning"/></P> + <p class="alert alert-warning"><fmt:message key="jsp.dspace-admin.confirm-delete-mdschema.warning"/></p> <form method="post"> <input type="hidden" name="dc_schema_id" value="<%= schema.getSchemaID() %>"> - - <center> - <table width="70%"> - <tr> - <td align="left"> - <%-- <input type="submit" name="submit_confirm_delete" value="Delete"> --%> - <input type="submit" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>"> - <%-- <input type="submit" name="submit_cancel" value="Cancel"> --%> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>"> - </td> - </tr> - </table> - </center> + <div class="btn-group"> + <%-- <input type="submit" name="submit_confirm_delete" value="Delete"> --%> + <input class="btn btn-danger" type="submit" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>"> + <%-- <input type="submit" name="submit_cancel" value="Cancel"> --%> + <input class="btn btn-default" type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>"> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/eperson-confirm-delete.jsp b/dspace-jspui/src/main/webapp/dspace-admin/eperson-confirm-delete.jsp index bb740c8f4bed6cf2689756d5fb41b2a478f4d59c..4e42c815228ded8d4ff23385279d733873564014 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/eperson-confirm-delete.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/eperson-confirm-delete.jsp @@ -27,7 +27,7 @@ <% EPerson eperson = (EPerson) request.getAttribute("eperson"); %> -<dspace:layout titlekey="jsp.dspace-admin.eperson-confirm-delete.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.eperson-confirm-delete.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -40,25 +40,19 @@ </fmt:message></h1> <%-- <p>Are you sure this e-person should be deleted?</p> --%> - <p><fmt:message key="jsp.dspace-admin.eperson-confirm-delete.confirm"/></p> + <div class="row col-md-offset-4"> + <span class="col-md-6"><fmt:message key="jsp.dspace-admin.eperson-confirm-delete.confirm"/></span> + </div> <form method="post" action=""> <input type="hidden" name="eperson_id" value="<%= eperson.getID() %>"/> - - <center> - <table width="70%"> - <tr> - <td align="left"> - <%-- <input type="submit" name="submit_confirm_delete" value="Delete"> --%> - <input type="submit" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> - </td> - <td align="right"> - <%-- <input type="submit" name="submit_cancel" value="Cancel"> --%> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <div class="btn-group col-md-offset-5"> + <%-- <input type="submit" name="submit_confirm_delete" value="Delete"> --%> + <input type="submit" class="btn btn-danger col-md-6" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + <%-- <input type="submit" name="submit_cancel" value="Cancel"> --%> + <input type="submit" class="btn btn-default col-md-6" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> </form> + </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/eperson-deletion-error.jsp b/dspace-jspui/src/main/webapp/dspace-admin/eperson-deletion-error.jsp index 284ebe699fdf042d08281190264389a33a18531e..502150e79ce9201ec9f99383f849a6529bd84852 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/eperson-deletion-error.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/eperson-deletion-error.jsp @@ -37,7 +37,7 @@ Iterator tableIt = tableList.iterator(); %> -<dspace:layout titlekey="jsp.dspace-admin.eperson-deletion-error.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.eperson-deletion-error.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" diff --git a/dspace-jspui/src/main/webapp/dspace-admin/eperson-edit.jsp b/dspace-jspui/src/main/webapp/dspace-admin/eperson-edit.jsp index ab321bc364fc982c6881f6865c16045158b8e5e4..3596df300bc598cc5a500b655bebe280c7740d09 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/eperson-edit.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/eperson-edit.jsp @@ -68,7 +68,7 @@ boolean ldap_enabled = ConfigurationManager.getBooleanProperty("authentication-ldap", "enable"); %> -<dspace:layout titlekey="jsp.dspace-admin.eperson-edit.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.eperson-edit.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -76,74 +76,69 @@ nocache="true"> - <table width="95%"> - <tr> - <td align="left"> + <%-- <h1>Edit EPerson <%= eperson.getEmail() %>:</h1> --%> <h1><fmt:message key="jsp.dspace-admin.eperson-edit.heading"> - <fmt:param><%= eperson.getEmail() %></fmt:param> - </fmt:message></h1> - </td> - <td align="right" class="standard"> + <fmt:param><%= Utils.addEntities(eperson.getEmail()) %></fmt:param> + </fmt:message> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#epeople\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + </h1> + <% if (emailExists) - { %><p><strong> + { %><p class="alert alert-warning"> <fmt:message key="jsp.dspace-admin.eperson-edit.emailexists"/> - </strong></p> + </p> <% } %> <form method="post" action=""> - <table class="miscTable" align="center"> - <tr> + <div class="row"> <%-- <td>Email:</td> --%> - <td><label for="temail"><fmt:message key="jsp.dspace-admin.eperson-edit.email"/></label></td> - <td> - <input type="hidden" name="eperson_id" value="<%=eperson.getID()%>"/> - <input name="email" id="temail" size="24" value="<%=email == null ? "" : email%>"/> - </td> - </tr> - - <tr> + <label class="col-md-2" for="temail"><fmt:message key="jsp.dspace-admin.eperson-edit.email"/></label> + <div class="col-md-6"> + <input type="hidden" name="eperson_id" value="<%=eperson.getID()%>"/> + <input class="form-control" name="email" id="temail" size="24" value="<%=email == null ? "" : Utils.addEntities(email) %>"/> + </div> + </div> + + <div class="row"> <%-- <td>Last Name:</td> --%> - <td><label for="tlastname"><fmt:message key="jsp.dspace-admin.eperson.general.lastname"/></label></td> - <td> - <input name="lastname" id="tlastname" size="24" value="<%=lastName == null ? "" : Utils.addEntities(lastName) %>"/> - </td> - </tr> + <label class="col-md-2" for="tlastname"><fmt:message key="jsp.dspace-admin.eperson.general.lastname"/></label> + <div class="col-md-6"> + <input class="form-control" name="lastname" id="tlastname" size="24" value="<%=lastName == null ? "" : Utils.addEntities(lastName) %>"/> + </div> + </div> - <tr> + <div class="row"> <%-- <td>First Name:</td> --%> - <td><label for="tfirstname"><fmt:message key="jsp.dspace-admin.eperson.general.firstname"/></label></td> - <td> - <input name="firstname" id="tfirstname" size="24" value="<%=firstName == null ? "" : Utils.addEntities(firstName) %>"/> - </td> - </tr> + <label class="col-md-2" for="tfirstname"><fmt:message key="jsp.dspace-admin.eperson.general.firstname"/></label> + <div class="col-md-6"> + <input class="form-control" name="firstname" id="tfirstname" size="24" value="<%=firstName == null ? "" : Utils.addEntities(firstName) %>"/> + </div> + </div> <% if (ldap_enabled) { %> - <tr> - <td>LDAP NetID:</td> - <td> - <input name="netid" size="24" value="<%=netid == null ? "" : Utils.addEntities(netid) %>" /> - </td> - </tr> + <div class="row"> + <label class="col-md-2">LDAP NetID:</label> + <div class="col-md-6"> + <input class="form-control" name="netid" size="24" value="<%=netid == null ? "" : Utils.addEntities(netid) %>" /> + </div> + </div> <% } %> - <tr> + <div class="row"> <%-- <td>Phone:</td> --%> - <td><label for="tphone"><fmt:message key="jsp.dspace-admin.eperson-edit.phone"/></label></td> - <td> - <input name="phone" id="tphone" size="24" value="<%=phone == null ? "" : Utils.addEntities(phone) %>"/> - </td> - </tr> - <tr> - <td><label for="tlanguage"><fmt:message key="jsp.register.profile-form.language.field"/></label></td> - <td class="standard"> - <select name="language" id="tlanguage"> + <label class="col-md-2" for="tphone"><fmt:message key="jsp.dspace-admin.eperson-edit.phone"/></label> + <div class="col-md-6"> + <input class="form-control" name="phone" id="tphone" size="24" value="<%=phone == null ? "" : Utils.addEntities(phone) %>"/> + </div> + </div> + + <div class="row"> + <label class="col-md-2" for="tlanguage"><fmt:message key="jsp.register.profile-form.language.field"/></label> + <div class="col-md-6"> + <select class="form-control" name="language" id="tlanguage"> <% Locale[] supportedLocales = I18nUtil.getSupportedLocales(); @@ -167,48 +162,43 @@ } %> </select> - </td> - </tr> - - <tr> - <%-- <td>Can Log In:</td> --%> - <td><label for="tcan_log_in"><fmt:message key="jsp.dspace-admin.eperson-edit.can"/></label></td> - <td> - <input type="checkbox" name="can_log_in" id="tcan_log_in" value="true"<%= eperson.canLogIn() ? " checked=\"checked\"" : "" %> /> - </td> - </tr> - - <tr> - <%-- <td>Require Certificate:</td> --%> - <td><label for="trequire_certificate"><fmt:message key="jsp.dspace-admin.eperson-edit.require"/></label></td> - <td> - <input type="checkbox" name="require_certificate" id="trequire_certificate" value="true"<%= eperson.getRequireCertificate() ? " checked=\"checked\"" : "" %> /> - </td> - </tr> - </table> - - <center> - <table width="70%"> - <tr> - <td align="left"> + </div> + </div> + <div class="row"> + <%-- <td>Can Log In:</td> --%> + <label class="col-md-2" for="tcan_log_in"><fmt:message key="jsp.dspace-admin.eperson-edit.can"/></label> + <div class="col-md-6"> + <input class="form-control" type="checkbox" name="can_log_in" id="tcan_log_in" value="true"<%= eperson.canLogIn() ? " checked=\"checked\"" : "" %> /> + </div> + </div> + <div class="row"> + <%-- <td>Require Certificate:</td> --%> + <label class="col-md-2" for="trequire_certificate"><fmt:message key="jsp.dspace-admin.eperson-edit.require"/></label> + <div class="col-md-6"> + <input class="form-control" type="checkbox" name="require_certificate" id="trequire_certificate" value="true"<%= eperson.getRequireCertificate() ? " checked=\"checked\"" : "" %> /> + </div> + </div> + <br/> + <div class="col-md-4 btn-group"> <%-- <input type="submit" name="submit_save" value="Save Edits"> --%> - <input type="submit" name="submit_save" value="<fmt:message key="jsp.dspace-admin.general.save"/>" /> - </td> - <td align="right"> + <input class="btn btn-default" type="submit" name="submit_save" value="<fmt:message key="jsp.dspace-admin.general.save"/>" /> + <input class="btn btn-default" type="submit" name="submit_resetpassword" value="<fmt:message key="jsp.dspace-admin.eperson-main.ResetPassword.submit"/>"/> <%-- <input type="submit" name="submit_delete" value="Delete EPerson..."> --%> - <input type="submit" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> - </td> - </tr> - </table> - </center> - + <input class="btn btn-danger" type="submit" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + </div> + </form> <% if((groupMemberships != null) && (groupMemberships.length>0)) { %> - <h3><fmt:message key="jsp.dspace-admin.eperson-edit.groups"/></h3> + <br/> + <br/> + + <h3><fmt:message key="jsp.dspace-admin.eperson-edit.groups"/></h3> + + <div class="row"> <ul> <% for(int i=0; i<groupMemberships.length; i++) { @@ -222,6 +212,7 @@ <li><%=myLink%></li> <% } %> </ul> + </div> <% } %> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/eperson-main.jsp b/dspace-jspui/src/main/webapp/dspace-admin/eperson-main.jsp index e454a3beda9590485674246848f9a1f7f98858e5..e42d358968087e0fc8a046855e2d74209ed1f5cf 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/eperson-main.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/eperson-main.jsp @@ -14,6 +14,8 @@ - Attributes: - no_eperson_selected - if a user tries to edit or delete an EPerson without - first selecting one + - reset_password - if a user tries to reset password of an EPerson and the email with token is + - send successfull - - Returns: - submit_add - admin wants to add an eperson @@ -27,68 +29,71 @@ prefix="fmt" %> <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="org.dspace.core.ConfigurationManager" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <% boolean noEPersonSelected = (request.getAttribute("no_eperson_selected") != null); + boolean resetPassword = (request.getAttribute("reset_password") != null); + boolean loginAs = ConfigurationManager.getBooleanProperty("webui.user.assumelogin", false); %> -<dspace:layout titlekey="jsp.dspace-admin.eperson-main.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.eperson-main.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin"> <%-- <h1>Administer EPeople</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.eperson-main.heading"/></h1> - <table width="95%"> - <tr> - <td align="left"> - <%-- <h3>Choose an action:</h3> --%> - <h3><fmt:message key="jsp.dspace-admin.eperson-main.choose"/></h3> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"epeople\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + <h1><fmt:message key="jsp.dspace-admin.eperson-main.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"epeople\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </h1> + + <%-- <h3>Choose an action:</h3> --%> + <h3><fmt:message key="jsp.dspace-admin.eperson-main.choose"/></h3> + + + <% if (noEPersonSelected) - { %><p><strong> + { %><p class="alert alert-warning"> <fmt:message key="jsp.dspace-admin.eperson-main.noepersonselected"/> - </strong></p> + </p> <% } %> - +<% if (resetPassword) + { %><p class="alert alert-success"> + <fmt:message key="jsp.dspace-admin.eperson-main.ResetPassword.success_notice"/> + </p> +<% } %> <form name="epersongroup" method="post" action=""> + <div class="row"> + <%-- <input type="submit" name="submit_add" value="Add EPerson..."> --%> + <input class="btn btn-success col-md-2 col-md-offset-5" type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.eperson-main.add"/>" /> + </div> + <br/> - <center> - <table width="90%"> - <tr> - <td colspan="3" align="center"> - <%-- <input type="submit" name="submit_add" value="Add EPerson..."> --%> - <input type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.eperson-main.add"/>" /> - </td> - </tr> - <tr> - <%-- <td colspan="3"><strong>OR</strong></td> --%> - <td colspan="3"><strong><fmt:message key="jsp.dspace-admin.eperson-main.or"/></strong></td> - </tr> - <tr> - <td> - <dspace:selecteperson multiple="false" /> - </td> - <td> - <%-- then <input type="submit" name="submit_edit" value="Edit..." onclick="javascript:finishEPerson();"> --%> - <fmt:message key="jsp.dspace-admin.eperson-main.then"/> <input type="submit" name="submit_edit" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" onclick="javascript:finishEPerson();"/> - </td> - <td> - <%-- <input type="submit" name="submit_delete" value="Delete..." onclick="javascript:finishEPerson();"> --%> - <input type="submit" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete-w-confirm"/>" onclick="javascript:finishEPerson();"/> - </td> - </tr> - </table> - </center> - + <fmt:message key="jsp.dspace-admin.eperson-main.or"/> + + <div class="row"> + <div class="col-md-6"> + <dspace:selecteperson multiple="false" /> + </div> + + <%-- then <input type="submit" name="submit_edit" value="Edit..." onclick="javascript:finishEPerson();"> --%> + <div class="col-md-2"> + <fmt:message key="jsp.dspace-admin.eperson-main.then"/> + </div> + <div class="col-md-4"> + <input type="submit" class="btn btn-default col-md-4" name="submit_edit" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" onclick="javascript:finishEPerson();"/> + + <% if(loginAs) { %> <input type="submit" class="btn btn-default col-md-4" name="submit_login_as" value="<fmt:message key="jsp.dspace-admin.eperson-main.LoginAs.submit"/>" onclick="javascript:finishEPerson();"/> <% } %> + + <%-- <input type="submit" name="submit_delete" value="Delete..." onclick="javascript:finishEPerson();"> --%> + <input type="submit" class="btn btn-danger col-md-4" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete-w-confirm"/>" onclick="javascript:finishEPerson();"/> + + </div> + </div> </form> + </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/group-confirm-delete.jsp b/dspace-jspui/src/main/webapp/dspace-admin/group-confirm-delete.jsp index 619446ddd58f87a38c290da998b669aaddc21fc6..d9aadc0add9f4e303b79da97e7eb113bf8e15a2f 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/group-confirm-delete.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/group-confirm-delete.jsp @@ -22,7 +22,7 @@ <% Group group = (Group) request.getAttribute("group"); %> -<dspace:layout titlekey="jsp.dspace-admin.group-confirm-delete.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.group-confirm-delete.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -32,25 +32,14 @@ <fmt:param><%= group.getName() %></fmt:param> </fmt:message></h1> - <p><fmt:message key="jsp.dspace-admin.group-confirm-delete.confirm"/></p> - - - <center> - <table width="70%"> - <tr> - <td align="left"> - <form method="post" action=""> - <input type="hidden" name="group_id" value="<%= group.getID() %>"/> - <input type="submit" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> - </form> - </td> - <td align="right"> + <p class="alert alert-warning"><fmt:message key="jsp.dspace-admin.group-confirm-delete.confirm"/></p> + <form method="post" action=""> - <input type="submit" name="submit_cancel_delete" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + <div class="btn-group col-md-offset-5"> + <input type="hidden" name="group_id" value="<%= group.getID() %>"/> + <input class="btn btn-danger" type="submit" name="submit_confirm_delete" value="<fmt:message key="jsp.dspace-admin.general.delete"/>" /> + <input class="btn btn-default" type="submit" name="submit_cancel_delete" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> </form> - </td> - </tr> - </table> - </center> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/group-eperson-select.jsp b/dspace-jspui/src/main/webapp/dspace-admin/group-eperson-select.jsp index 1ae19c57970fd50acb439325458ac2187aedc7bd..c8fff6f0ab2b4b20c713d69fa14fbb704e484166 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/group-eperson-select.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/group-eperson-select.jsp @@ -37,7 +37,7 @@ (EPerson []) request.getAttribute("epeople"); %> -<dspace:layout titlekey="jsp.dspace-admin.group-eperson-select.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.group-eperson-select.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -51,36 +51,26 @@ <form method="post" action=""> - <table class="miscTable" align="center"> - <tr> - <td> + <input type="hidden" name="group_id" value="<%=group.getID()%>"/> - - <select size="15" name="eperson_id" multiple="multiple"> + <div class="row col-md-4 col-md-offset-4"> + <select class="form-control" size="15" name="eperson_id" multiple="multiple"> <% for (int i = 0; i < epeople.length; i++) { %> <option value="<%= epeople[i].getID()%>"> <%= epeople[i].getEmail()%> </option> <% } %> </select> - </td> - </tr> - </table> - - <center> - <table width="70%"> - <tr> - <td align="left"> - <%-- <input type="submit" name="submit_add_eperson_add" value="Add EPerson"> --%> - <input type="submit" name="submit_add_eperson_add" value="<fmt:message key="jsp.dspace-admin.group-eperson-select.add"/>" /> - </td> - <td align="right"> + </div> + + <br/> + <div class="btn-group pull-right col-md-7"> + <%-- <input type="submit" name="submit_add_eperson_add" value="Add EPerson"> --%> + <input class="btn btn-primary" type="submit" name="submit_add_eperson_add" value="<fmt:message key="jsp.dspace-admin.group-eperson-select.add"/>" /> + <%-- <input type="submit" name="submit_add_eperson_cancel" value="Cancel"> --%> - <input type="submit" name="submit_add_eperson_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-default" type="submit" name="submit_add_eperson_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/group-group-select.jsp b/dspace-jspui/src/main/webapp/dspace-admin/group-group-select.jsp index ecd04ffaa680a805e6057e196b02b43bae4fa88f..c2deb05ffc600f5c5035cab142679b7c9e50da27 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/group-group-select.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/group-group-select.jsp @@ -36,7 +36,7 @@ (Group []) request.getAttribute("groups"); %> -<dspace:layout titlekey="jsp.dspace-admin.group-group-select.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.group-group-select.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -50,36 +50,25 @@ <form method="post" action=""> - <table class="miscTable" align="center"> - <tr> - <td> + <input type="hidden" name="group_id" value="<%=group.getID()%>" /> - - <select size="15" name="groups_id" multiple="multiple"> + <div class="row col-md-4 col-md-offset-4"> + <select class="form-control" size="15" name="groups_id" multiple="multiple"> <% for (int i = 0; i < groups.length; i++) { %> <option value="<%= groups[i].getID()%>"> <%= groups[i].getName()%> </option> <% } %> </select> - </td> - </tr> - </table> - - <center> - <table width="70%"> - <tr> - <td align="left"> - <%--<input type="submit" name="submit_add_group_add" value="Add Group" />--%> - <input type="submit" name="submit_add_group_add" value="<fmt:message key="jsp.dspace-admin.group-group-select.add"/>" /> - </td> - <td align="right"> + </div> + <br/> + <div class="btn-group pull-right col-md-7"> + <%--<input type="submit" name="submit_add_group_add" value="Add Group" />--%> + <input class="btn btn-primary" type="submit" name="submit_add_group_add" value="<fmt:message key="jsp.dspace-admin.group-group-select.add"/>" /> + <%--<input type="submit" name="submit_add_group_cancel" value="Cancel" />--%> - <input type="submit" name="submit_add_group_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-default" type="submit" name="submit_add_group_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/index.jsp b/dspace-jspui/src/main/webapp/dspace-admin/index.jsp index c6350927d04c26bc655b6a38c18bd821f6314485..f53a794abba4b5e04c71c916012382995dbe00c1 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/index.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/index.jsp @@ -41,12 +41,12 @@ { context = UIUtil.obtainContext(request); %> -<dspace:layout locbar="link" navbar="admin" titlekey="jsp.administer"> +<dspace:layout style="submission" locbar="link" navbar="admin" titlekey="jsp.administer"> <%-- <h1>Administration Tools</h1> --%> <h1><fmt:message key="jsp.dspace-admin.index.heading"/></h1> - <%-- <p>Please select an operation from the navigation bar on the left.</p> --%> + <%-- <p>Please select an operation from the main menu bar.</p> --%> <p><fmt:message key="jsp.dspace-admin.index.text"/></p> </dspace:layout> <% diff --git a/dspace-jspui/src/main/webapp/dspace-admin/item-select.jsp b/dspace-jspui/src/main/webapp/dspace-admin/item-select.jsp index 49311b67ec747a5d0e458e2ac442d0ffd3767af7..8deca82c45488ad5380105851548cb5487be8cd9 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/item-select.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/item-select.jsp @@ -27,7 +27,7 @@ <%@ page import="org.dspace.core.ConfigurationManager" %> -<dspace:layout titlekey="jsp.dspace-admin.item-select.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.item-select.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -35,7 +35,9 @@ <%-- <h1>Select an Item</h1> --%> -<h1><fmt:message key="jsp.dspace-admin.item-select.heading"/></h1> +<h1><fmt:message key="jsp.dspace-admin.item-select.heading"/> +<dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#itempolicies\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> +</h1> <% if (request.getAttribute("invalid.id") != null) { %> @@ -43,38 +45,32 @@ edit a community or collection, you need to use the <a href="<%= request.getContextPath() %>/dspace-admin/edit-communities">communities/collections admin page.</a></p> --%> - <p><fmt:message key="jsp.dspace-admin.item-select.text"> + <p class="alert alert-warning"><fmt:message key="jsp.dspace-admin.item-select.text"> <fmt:param><%= request.getContextPath() %>/dspace-admin/edit-communities</fmt:param> </fmt:message></p> <% } %> <%-- <p>Enter the Handle or internal item ID of the item you wish to select. --%> - <div><fmt:message key="jsp.dspace-admin.item-select.enter"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#itempolicies\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> - + <div><fmt:message key="jsp.dspace-admin.item-select.enter"/></div> + <form method="post" action=""> - <center> - <table class="miscTable"> - <tr class="oddRowEvenCol"> - <%-- <td class="submitFormLabel">Handle:</td> --%> - <td class="submitFormLabel"><label for="thandle"><fmt:message key="jsp.dspace-admin.item-select.handle"/></label></td> - <td> - <input type="text" name="handle" id="thandle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>/" size=12> - <%-- <input type="submit" name="submit_item_select" value="Find"> --%> - <input type="submit" name="submit_item_select" value="<fmt:message key="jsp.dspace-admin.item-select.find"/>" /> - </td> - </tr> - <tr><td></td></tr> - <tr class="oddRowEvenCol"> - <%-- <td class="submitFormLabel">Internal ID:</td> --%> - <td class="submitFormLabel"><label for="titem_id"><fmt:message key="jsp.dspace-admin.item-select.id"/></label></td> - <td> - <input type="text" name="item_id" size="12"> - <%-- <input type="submit" name="submit_item_select" value="Find"> --%> - <input type="submit" name="submit_item_select" value="<fmt:message key="jsp.dspace-admin.item-select.find"/>" /> - </td> - </tr> - </table> - </center> + <div class="row"> + <label class="col-md-2" for="thandle"><fmt:message key="jsp.dspace-admin.item-select.handle"/></label> + <span class="col-md-3"><input class="form-control" type="text" name="handle" id="thandle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>/" size="12"/></span> + <%-- <input type="submit" name="submit" value="Find" /> --%> + <input class="btn btn-default" type="submit" name="submit_item_select" value="<fmt:message key="jsp.dspace-admin.item-select.find"/>" /> + </div> + <div class="row"> + <label class="col-md-2" for="thandle"><fmt:message key="jsp.dspace-admin.item-select.id"/></label> + <span class="col-md-3"><input class="form-control" type="text" name="item_id" id="titem_id" size="12"/></span> + <%-- <input type="submit" name="submit" value="Find"> --%> + <input class="btn btn-default" type="submit" name="submit_item_select" value="<fmt:message key="jsp.dspace-admin.item-select.find"/>" /> + </div> </form> + <br/> + <form method="post" action=""> + <div class="row col-md-offset-11"> + <input class="btn btn-default" type="submit" name="submit_collection_select_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </div> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/license-edit.jsp b/dspace-jspui/src/main/webapp/dspace-admin/license-edit.jsp index 58f8ecafc37ee7346a830fe00593fd247d6069b1..f111b13861708dc04ed5034bfdc9ab36cad111ce 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/license-edit.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/license-edit.jsp @@ -19,7 +19,7 @@ <%@ 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"%> <% // Get the existing license String license = (String)request.getAttribute("license"); @@ -44,13 +44,15 @@ %> -<dspace:layout titlekey="jsp.dspace-admin.license-edit.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.license-edit.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin"> - <h1><fmt:message key="jsp.dspace-admin.license-edit.heading"/></h1> + <h1><fmt:message key="jsp.dspace-admin.license-edit.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#editlicense\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </h1> <form action="<%= request.getContextPath() %>/dspace-admin/license-edit" method="post"> @@ -58,7 +60,7 @@ if (edited) { %> - <p> + <p class="alert alert-warning"> <strong><fmt:message key="jsp.dspace-admin.license-edit.edited"/></strong> </p> <% @@ -68,17 +70,18 @@ if (empty) { %> - <p> + <p class="alert alert-warning"> <strong><fmt:message key="jsp.dspace-admin.license-edit.empty"/></strong> </p> <% } %> - <p><fmt:message key="jsp.dspace-admin.license-edit.description"/></p> - <p><textarea name="license" rows="15" cols="70"><%= license %></textarea><br /> - <input type="submit" name="submit_save" value="<fmt:message key="jsp.dspace-admin.general.save"/>" /> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </p> + <p class="alert alert-info"><fmt:message key="jsp.dspace-admin.license-edit.description"/></p> + + <textarea class="form-control" name="license" rows="15" cols="70"><%= license %></textarea> + <input class="btn btn-primary" type="submit" name="submit_save" value="<fmt:message key="jsp.dspace-admin.general.save"/>" /> + <input class="btn btn-default" type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/list-formats.jsp b/dspace-jspui/src/main/webapp/dspace-admin/list-formats.jsp index ea58b46cd5fd4bc9bbacad96c663614349844a0c..6c37d5c393e5ad522baf557a6116f90a646a882b 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/list-formats.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/list-formats.jsp @@ -37,27 +37,28 @@ (BitstreamFormat[]) request.getAttribute("formats"); %> -<dspace:layout titlekey="jsp.dspace-admin.list-formats.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.list-formats.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin"> - <h1><fmt:message key="jsp.dspace-admin.list-formats.title"/></h1> + <h1><fmt:message key="jsp.dspace-admin.list-formats.title"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#bitstream\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </h1> - <p><fmt:message key="jsp.dspace-admin.list-formats.text1"/></p> - <p><fmt:message key="jsp.dspace-admin.list-formats.text2"/></p> - - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#bitstream\"%>"><fmt:message key="jsp.help"/></dspace:popup> + <p class="alert alert-info"><fmt:message key="jsp.dspace-admin.list-formats.text1"/></p> + <p class="alert alert-info"><fmt:message key="jsp.dspace-admin.list-formats.text2"/></p> <% Context context = UIUtil.obtainContext(request); %> - <table class="miscTable" align="center" summary="Bitstream Format Registry data table"> + <table class="table" summary="Bitstream Format Registry data table"> <tr> <th class="oddRowOddCol"> + <span class="col-md-offset-3"> <strong> <fmt:message key="jsp.general.id" /> / <fmt:message key="jsp.dspace-admin.list-formats.mime"/> @@ -67,6 +68,7 @@ / <fmt:message key="jsp.dspace-admin.list-formats.internal"/> / <fmt:message key="jsp.dspace-admin.list-formats.extensions"/> </strong> + </span> </th> </tr> <% @@ -88,53 +90,55 @@ %> <tr> <td> - <form method="post" action=""> - <table> - <tr> - <td class="<%= row %>RowOddCol"><%= formats[i].getID() %></td> - <td class="<%= row %>RowEvenCol"> - <input type="text" name="mimetype" value="<%= formats[i].getMIMEType() %>" size="14"/> - </td> - <td class="<%= row %>RowOddCol"> + <form class="form-inline" method="post" action=""> + + <span class="col-md-1"><%= formats[i].getID() %></span> + <div class="form-group"> + <label class="sr-only" for="mimetype"><fmt:message key="jsp.dspace-admin.list-formats.mime"/></label> + <input class="form-control" type="text" name="mimetype" value="<%= formats[i].getMIMEType()!=null?formats[i].getMIMEType():"" %>" size="14" placeholder="<fmt:message key="jsp.dspace-admin.list-formats.mime"/>"/> + </div> + <div class="form-group"> + <label class="sr-only" for="short_description"><fmt:message key="jsp.dspace-admin.list-formats.name"/></label> <% if (BitstreamFormat.findUnknown(context).getID() == formats[i].getID()) { %> - <i><%= formats[i].getShortDescription() %></i> - <% } else { %> - <input type="text" name="short_description" value="<%= formats[i].getShortDescription() %>" size="10"/> + <span class="form-control"><i><%= formats[i].getShortDescription() %></i></span> + <% } else { %> + <input class="form-control" type="text" name="short_description" value="<%= formats[i].getShortDescription()!=null?formats[i].getShortDescription():"" %>" size="10" placeholder="<fmt:message key="jsp.dspace-admin.list-formats.name"/>"/> <% } %> - </td> - <td class="<%= row %>RowEvenCol"> - <input type="text" name="description" value="<%= formats[i].getDescription() %>" size="20"/> - </td> - <td class="<%= row %>RowOddCol"> - <select name="support_level"> + </div> + <div class="form-group"> + <label class="sr-only" for="description"><fmt:message key="jsp.dspace-admin.list-formats.description"/></label> + <input class="form-control" type="text" name="description" value="<%= formats[i].getDescription()!=null?formats[i].getDescription():"" %>" size="20" placeholder="<fmt:message key="jsp.dspace-admin.list-formats.description"/>"/> + </div> + <div class="form-group"> + <select class="form-control" name="support_level"> <option value="0" <%= formats[i].getSupportLevel() == 0 ? "selected=\"selected\"" : "" %>><fmt:message key="jsp.dspace-admin.list-formats.unknown"/></option> <option value="1" <%= formats[i].getSupportLevel() == 1 ? "selected=\"selected\"" : "" %>><fmt:message key="jsp.dspace-admin.list-formats.known"/></option> <option value="2" <%= formats[i].getSupportLevel() == 2 ? "selected=\"selected\"" : "" %>><fmt:message key="jsp.dspace-admin.list-formats.supported"/></option> </select> - </td> - <td class="<%= row %>RowEvenCol" align="center"> - <input type="checkbox" name="internal" value="true"<%= formats[i].isInternal() ? " checked=\"checked\"" : "" %>/> - </td> - <td class="<%= row %>RowOddCol"> - <input type="text" name="extensions" value="<%= extValue %>" size="10"/> - </td> - <td class="<%= row %>RowEvenCol"> + </div> + <div class="form-group"> + <input class="form-control" type="checkbox" name="internal" value="true"<%= formats[i].isInternal() ? " checked=\"checked\"" : "" %>/> + </div> + <div class="form-group"> + <label class="sr-only" for="extensions"><fmt:message key="jsp.dspace-admin.list-formats.extensions"/></label> + <input class="form-control" type="text" name="extensions" value="<%= extValue %>" size="10" placeholder="<fmt:message key="jsp.dspace-admin.list-formats.extensions"/>"/> + </div> + <div class="btn-group pull-right"> <input type="hidden" name="format_id" value="<%= formats[i].getID() %>" /> - <input type="submit" name="submit_update" value="<fmt:message key="jsp.dspace-admin.general.update"/>"/> - </td> - <td class="<%= row %>RowOddCol"> + <input class="btn btn-primary" type="submit" name="submit_update" value="<fmt:message key="jsp.dspace-admin.general.update"/>"/> + <% if (BitstreamFormat.findUnknown(context).getID() != formats[i].getID()) { %> - <input type="submit" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete-w-confirm"/>" /> + <input class="btn btn-danger" type="submit" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete-w-confirm"/>" /> <% } %> - </td> - </tr> - </table> + </div> + + </form> </td> </tr> @@ -146,8 +150,8 @@ </table> <form method="post" action=""> - <p align="center"> - <input type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.general.addnew"/>" /> - </p> + + <input class="btn btn-success col-md-offset-5" type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.general.addnew"/>" /> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/list-metadata-fields.jsp b/dspace-jspui/src/main/webapp/dspace-admin/list-metadata-fields.jsp index d7e6d7181c279a8f138acdab6567df975b23f4ad..ce25d6bbb4797ff70250a98e7fdd5636483f2b80 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/list-metadata-fields.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/list-metadata-fields.jsp @@ -41,40 +41,37 @@ (MetadataSchema[]) request.getAttribute("schemas"); %> -<dspace:layout titlekey="jsp.dspace-admin.list-metadata-fields.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.list-metadata-fields.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin"> - <table width="95%"> - <tr> - <td align="left"> - <h1><fmt:message key="jsp.dspace-admin.list-metadata-fields.title"/></h1> - </td> - <td align="right" class="standard"> - <a href="<%=request.getContextPath()%>/dspace-admin/metadata-schema-registry"> - <fmt:message key="jsp.dspace-admin.list-metadata-fields.schemas"/> - </a> | - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#dublincore\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + + <h1><fmt:message key="jsp.dspace-admin.list-metadata-fields.title"/> + <a href="<%=request.getContextPath()%>/dspace-admin/metadata-schema-registry"> + <fmt:message key="jsp.dspace-admin.list-metadata-fields.schemas"/> + </a> | + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#dublincore\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </h1> + + + <% String error = (String)request.getAttribute("error"); if (error!=null) { %> - <p align="center"> - <font color="red"><%=error%></font> + <p class="alert alert-danger"> + <%=error%> </p> <% } %> - <p align="center"> + <p class="alert alert-info"> <fmt:message key="jsp.dspace-admin.list-metadata-fields.note"/> </p> - <table width="70%" class="miscTable" align="center" summary="Dublic Core Type Registry data table"> + <table class="table" summary="Dublic Core Type Registry data table"> <tr> <th class="oddRowOddCol"> <strong> @@ -93,29 +90,29 @@ if (error!=null) { %> <tr> <td> - <form method="post" action=""> - <table> - <tr> - <td class="<%= row %>RowOddCol"><%= types[i].getFieldID() %></td> - <td class="<%= row %>RowEvenCol"> - <input type="text" name="element" value="<%= types[i].getElement() %>" size="12"/> - </td> - <td class="<%= row %>RowOddCol"> - <input type="text" name="qualifier" value="<%= (types[i].getQualifier() == null ? "" : types[i].getQualifier()) %>" size="12"/> - </td> - <td class="<%= row %>RowEvenCol"> - <textarea name="scope_note" rows="3" cols="40"><%= (types[i].getScopeNote() == null ? "" : types[i].getScopeNote()) %></textarea> - </td> - <td class="<%= row %>RowOddCol"> + <form class="form-inline" method="post" action=""> + <span class="col-md-1"><%= types[i].getFieldID() %></span> + + <div class="form-group"> + <label class="sr-only" for="element"><fmt:message key="jsp.dspace-admin.list-metadata-fields.element"/></label> + <input class="form-control" type="text" name="element" value="<%= types[i].getElement() %>" size="12" placeholder="<fmt:message key="jsp.dspace-admin.list-metadata-fields.element"/>"/> + </div> + <div class="form-group"> + <label class="sr-only" for="qualifier"><fmt:message key="jsp.dspace-admin.list-metadata-fields.qualifier"/></label> + <input class="form-control" type="text" name="qualifier" value="<%= (types[i].getQualifier() == null ? "" : types[i].getQualifier()) %>" size="12" placeholder="<fmt:message key="jsp.dspace-admin.list-metadata-fields.qualifier"/>"/> + </div> + <div class="form-group"> + <label class="sr-only" for="scope_note"><fmt:message key="jsp.dspace-admin.list-metadata-fields.scope"/></label> + <textarea class="form-control" name="scope_note" rows="3" cols="40"><%= (types[i].getScopeNote() == null ? "" : types[i].getScopeNote()) %></textarea> + </div> + + <div class="btn-group pull-right"> + <input type="hidden" name="dc_type_id" value="<%= types[i].getFieldID() %>"/> - <input type="submit" name="submit_update" value="<fmt:message key="jsp.dspace-admin.general.update"/>"/> - </td> - <td class="<%= row %>RowEvenCol"> - <input type="hidden" name="dc_type_id" value="<%= types[i].getFieldID() %>"/> - <input type="submit" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete-w-confirm"/>"/> - </td> - </tr> - </table> + <input class="btn btn-primary" type="submit" name="submit_update" value="<fmt:message key="jsp.dspace-admin.general.update"/>"/> + + <input class="btn btn-danger" type="submit" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete-w-confirm"/>"/> + </div> </form> </td> </tr> @@ -128,39 +125,33 @@ if (error!=null) { <form method="post" action=""> <input type="hidden" name="dc_schema_id" value="<%= schema.getSchemaID() %>"/> - <table align="center" width="650"> - <tr><td colspan="2"><h2><fmt:message key="jsp.dspace-admin.list-metadata-fields.addfield"/></h2></td></tr> - <tr> - <td colspan="2"><p><fmt:message key="jsp.dspace-admin.list-metadata-fields.addfieldnote"/><br/><br/> - </p></td> - </tr> - <tr> - <td><p><fmt:message key="jsp.dspace-admin.list-metadata-fields.element"/>:</p></td> - <td><input type="text" name="element"/></td> - </tr> - <tr> - <td><p><fmt:message key="jsp.dspace-admin.list-metadata-fields.qualifier"/>:</p></td> - <td><input type="text" name="qualifier"/></td> - </tr> - <tr> - <td valign="top"><p><fmt:message key="jsp.dspace-admin.list-metadata-fields.scope"/>:</p></td> - <td><textarea name="scope_note" rows="3" cols="40"></textarea></td> - </tr> - <tr><td></td><td><input type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.general.addnew"/>"/></td></tr> - </table> + <h2><fmt:message key="jsp.dspace-admin.list-metadata-fields.addfield"/></h2> + <p class="alert alert-info"><fmt:message key="jsp.dspace-admin.list-metadata-fields.addfieldnote"/></p> + + <p><fmt:message key="jsp.dspace-admin.list-metadata-fields.element"/>:</p> + <input class="form-control" type="text" name="element"/> + + <p><fmt:message key="jsp.dspace-admin.list-metadata-fields.qualifier"/>:</p> + <input class="form-control" type="text" name="qualifier"/> + + <p><fmt:message key="jsp.dspace-admin.list-metadata-fields.scope"/>:</p> + <textarea class="form-control" name="scope_note" rows="3" cols="40"></textarea> + + <input class="btn btn-primary" type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.general.addnew"/>"/> + </form> <form method="post" action=""> - <table align="center" width="650"> - <tr><td colspan="2"><h2><fmt:message key="jsp.dspace-admin.list-metadata-fields.move"/></h2></td></tr> + + <h2><fmt:message key="jsp.dspace-admin.list-metadata-fields.move"/></h2> <% if (schemas.length > 1) { %> - <tr><td colspan="2"><p> + <p class="alert alert-info"> <fmt:message key="jsp.dspace-admin.list-metadata-fields.movenote"/></p> - </td></tr> - <tr> - <td valign="top"><p><fmt:message key="jsp.dspace-admin.list-metadata-fields.element"/>:</p></td><td> - <select name="dc_field_id" multiple="multiple" size="5"> + + + <p><fmt:message key="jsp.dspace-admin.list-metadata-fields.element"/>:</p> + <select class="form-control" name="dc_field_id" multiple="multiple" size="5"> <% for (int i = 0; i < types.length; i++) { @@ -168,9 +159,9 @@ if (error!=null) { %> <option value="<%= types[i].getFieldID() %>"><%= types[i].getElement()+qualifier %></option> <% } %> - </select></td></tr> - <tr><td><p><fmt:message key="jsp.dspace-admin.list-metadata-fields.schema"/>: </p></td><td> - <select name="dc_dest_schema_id"> + </select> + <p><fmt:message key="jsp.dspace-admin.list-metadata-fields.schema"/>: </p> + <select class="form-control" name="dc_dest_schema_id"> <% for (int i = 0; i < schemas.length; i++) { @@ -180,15 +171,15 @@ if (error!=null) { <% } } %> - </select></td></tr> - <tr><td></td><td><p><input type="submit" name="submit_move" value="<fmt:message key="jsp.dspace-admin.list-metadata-fields.movesubmit"/>"/></p></td></tr> + </select> + <p><input class="btn btn-primary" type="submit" name="submit_move" value="<fmt:message key="jsp.dspace-admin.list-metadata-fields.movesubmit"/>"/></p> <% } else { %> - <tr><td colspan="2"> - <p><fmt:message key="jsp.dspace-admin.list-metadata-fields.moveformnote"/><br/><br/> + + <p class="alert alert-info"><fmt:message key="jsp.dspace-admin.list-metadata-fields.moveformnote"/><br/><br/> </p> - </td></tr> + <% } %> - </table> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/list-metadata-schemas.jsp b/dspace-jspui/src/main/webapp/dspace-admin/list-metadata-schemas.jsp index d8daa23ae228f4d1f0f3c576bffc2d5672cf49e1..a9c3e8ef20272c14806bb93d2b442503a8645d31 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/list-metadata-schemas.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/list-metadata-schemas.jsp @@ -34,34 +34,28 @@ (MetadataSchema[]) request.getAttribute("schemas"); %> -<dspace:layout titlekey="jsp.dspace-admin.list-metadata-schemas.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.list-metadata-schemas.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin"> - <table width="95%"> - <tr> - <td align="left"> - <h1><fmt:message key="jsp.dspace-admin.list-metadata-schemas.title"/></h1> - </td> - <td align="right" class="standard"> + + <h1><fmt:message key="jsp.dspace-admin.list-metadata-schemas.title"/> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#dublincore\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + </h1> <% String error = (String)request.getAttribute("error"); if (error!=null) { %> - <p align="center"> - <font color="red"><%=error%></font> + <p class="alert alert-danger"> + <%=error%> </p> <% } %> - <table class="miscTable" align="center" width="500"> + <table class="table" width="500"> <tr> <th class="oddRowOddCol"><strong><fmt:message key="jsp.general.id" /></strong></th> <th class="oddRowEvenCol"><strong><fmt:message key="jsp.dspace-admin.list-metadata-schemas.namespace"/></strong></th> @@ -86,8 +80,8 @@ if (error!=null) { <% if ( schemas[i].getSchemaID() != 1 ) { %> <form method="post" action=""> <input type="hidden" name="dc_schema_id" value="<%= schemas[i].getSchemaID() %>"/> - <input type="button" name="submit_update" value="<fmt:message key="jsp.dspace-admin.general.update"/>" onclick="javascript:document.schema.namespace.value='<%= schemas[i].getNamespace() %>';document.schema.short_name.value='<%= schemas[i].getName() %>';document.schema.dc_schema_id.value='<%= schemas[i].getSchemaID() %>';return null;"/> - <input type="submit" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete-w-confirm"/>"/> + <input class="btn btn-primary" type="button" name="submit_update" value="<fmt:message key="jsp.dspace-admin.general.update"/>" onclick="javascript:document.schema.namespace.value='<%= schemas[i].getNamespace() %>';document.schema.short_name.value='<%= schemas[i].getName() %>';document.schema.dc_schema_id.value='<%= schemas[i].getSchemaID() %>';return null;"/> + <input class="btn btn-danger" type="submit" name="submit_delete" value="<fmt:message key="jsp.dspace-admin.general.delete-w-confirm"/>"/> </form> <% } %> </td> @@ -100,26 +94,26 @@ if (error!=null) { <form method="post" name="schema" action=""> <input type="hidden" name="dc_schema_id" value=""/> - <table align="center" width="600"> - <tr> - <td align="left" colspan="2"> - <p> - <br/><fmt:message key="jsp.dspace-admin.list-metadata-schemas.instruction"/> - <br/><br/> + + <p class="alert alert-info"> + <fmt:message key="jsp.dspace-admin.list-metadata-schemas.instruction"/> </p> - </td> - </tr> - <tr> - <td><p><fmt:message key="jsp.dspace-admin.list-metadata-schemas.namespace"/>:</p></td> - <td><input type="text" name="namespace" value=""/></td> - </tr> - <tr> - <td><p><fmt:message key="jsp.dspace-admin.list-metadata-schemas.name"/>:</p></td> - <td><input type="text" name="short_name" value=""/></td> - </tr> - <tr> - <td><p><input type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.general.save"/>"/></p></td> - </tr> - </table> + <div class="input-group col-md-6"> + <div class="input-group-addon"> + <span class="col-md-2"><fmt:message key="jsp.dspace-admin.list-metadata-schemas.namespace"/>:</span> + </div> + <input class="form-control" type="text" name="namespace" value=""/> + </div> + <div class="input-group col-md-6"> + <div class="input-group-addon"> + <span class="col-md-2"><fmt:message key="jsp.dspace-admin.list-metadata-schemas.name"/>:</span> + </div> + <input class="form-control" type="text" name="short_name" value=""/> + </div> + <br/><br/><br/> + <div class="row col-md-offset-5"> + <input class="btn btn-success col-md-3" type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.general.save"/>"/> + </div> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/metadataimport-error.jsp b/dspace-jspui/src/main/webapp/dspace-admin/metadataimport-error.jsp index 93cefbf54e4caf392628be83267d2b7dfbcd2e07..0c1e1f77d1b97a1eebacb139254fc75cbb6d532c 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/metadataimport-error.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/metadataimport-error.jsp @@ -47,7 +47,7 @@ %> -<dspace:layout titlekey="jsp.dspace-admin.metadataimport.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.metadataimport.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" diff --git a/dspace-jspui/src/main/webapp/dspace-admin/metadataimport-showchanges.jsp b/dspace-jspui/src/main/webapp/dspace-admin/metadataimport-showchanges.jsp index 43a2c06dc5f9cc8e83ba8723f0590b52ccd29a5e..5ef039873fa85cc641d6430308bfbabd9fb02936 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/metadataimport-showchanges.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/metadataimport-showchanges.jsp @@ -36,7 +36,7 @@ boolean allow = ((Boolean)request.getAttribute("allow")).booleanValue(); %> -<dspace:layout titlekey="jsp.dspace-admin.metadataimport.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.metadataimport.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -64,7 +64,7 @@ } %> - <table class="miscTable"> + <table class="table"> <% // Display the changes @@ -326,17 +326,16 @@ <p align="center"> <form method="post" action=""> <input type="hidden" name="type" value="confirm" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.dspace-admin.metadataimport.apply"/>" /> + <input class="btn btn-default" type="submit" name="submit" value="<fmt:message key="jsp.dspace-admin.metadataimport.apply"/>" /> </form> <form method="post" action=""> <input type="hidden" name="type" value="cancel" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + <input class="btn btn-default" type="submit" name="submit" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> </form> </p> <% } %> - - </form> + </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/metadataimport.jsp b/dspace-jspui/src/main/webapp/dspace-admin/metadataimport.jsp index 11f4cd3c6b2f85d71216e8b39d26e74d6c687dcc..30dd3028d245d11f536ce391cd0a646eb87e46d3 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/metadataimport.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/metadataimport.jsp @@ -29,7 +29,7 @@ } %> -<dspace:layout titlekey="jsp.dspace-admin.metadataimport.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.metadataimport.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -43,11 +43,11 @@ <%= message %> <p align="center"> - <input type="file" size="40" name="file"/> + <input class="form-control" type="file" size="40" name="file"/> </p> <p align="center"> - <input type="submit" name="submit" value="<fmt:message key="jsp.dspace-admin.general.upload"/>" /> + <input class="btn btn-default" type="submit" name="submit" value="<fmt:message key="jsp.dspace-admin.general.upload"/>" /> </p> </form> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/news-edit.jsp b/dspace-jspui/src/main/webapp/dspace-admin/news-edit.jsp index 8836f7e1f2ccc3e670f92e547f3598cc9cdaa0df..8ba34b97eba4ccdb3b0c3d9221e648fa602bcf32 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/news-edit.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/news-edit.jsp @@ -37,7 +37,7 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.dspace-admin.news-edit.title" +<dspace:layout style="submission" titlekey="jsp.dspace-admin.news-edit.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -50,7 +50,7 @@ <form action="<%= request.getContextPath() %>/dspace-admin/news-edit" method="post"> - <p> + <p class="alert alert-info"> <% if (position.contains("top")) { %> <fmt:message key="jsp.dspace-admin.news-edit.text.topbox"/> @@ -61,24 +61,17 @@ <% } %> </p> <%-- <p>You may format the text using HTML tags, but please note that the HTML will not be validated here.</p> --%> - <p><fmt:message key="jsp.dspace-admin.news-edit.text3"/></p> - <center> - <table> - <tr> - <%-- <td class="submitFormLabel">News:</td> --%> - <td class="submitFormLabel"><fmt:message key="jsp.dspace-admin.news-edit.news"/></td> - <td><textarea name="news" rows="10" cols="50"><%= news %></textarea></td> - </tr> - <tr> - <td colspan="2" align="center"> - <input type="hidden" name="position" value='<%= position %>'/> - <%-- <input type="submit" name="submit_save" value="Save"> --%> - <input type="submit" name="submit_save" value="<fmt:message key="jsp.dspace-admin.general.save"/>" /> - <%-- <input type="submit" name="cancel" value="Cancel"> --%> - <input type="submit" name="cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <p class="alert alert-warning"><fmt:message key="jsp.dspace-admin.news-edit.text3"/></p> + + <%-- <td class="submitFormLabel">News:</td> --%> + <span class="col-md-2"><fmt:message key="jsp.dspace-admin.news-edit.news"/></span> + <textarea class="form-control" name="news" rows="10" cols="50"><%= news %></textarea> + + <input type="hidden" name="position" value='<%= position %>'/> + <%-- <input type="submit" name="submit_save" value="Save"> --%> + <input class="btn btn-primary" type="submit" name="submit_save" value="<fmt:message key="jsp.dspace-admin.general.save"/>" /> + <%-- <input type="submit" name="cancel" value="Cancel"> --%> + <input class="btn btn-default" type="submit" name="cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/news-main.jsp b/dspace-jspui/src/main/webapp/dspace-admin/news-main.jsp index 968290d99b1ed00da7642bef7fff7bdb3ce39648..5eda8dd4565ac411429bff1027bc169363418b32 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/news-main.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/news-main.jsp @@ -39,49 +39,24 @@ %> -<dspace:layout titlekey ="jsp.dspace-admin.news-main.title" +<dspace:layout style="submission" titlekey ="jsp.dspace-admin.news-main.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin" nocache="true"> - <table width="95%"> - <tr> - <td align="left"> + <%-- <h1>News Editor</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.news-main.heading"/></h1> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#editnews\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - - <form action="<%= request.getContextPath() %>/dspace-admin/news-edit" method="post"> - <table class="miscTable" align="center"> - <tr> - <%-- <td class="oddRowOddCol">Top News</td> --%> - <th id="t1" class="oddRowOddCol"><fmt:message key="jsp.dspace-admin.news-main.news.top"/></th> - <td headers="t1" class="oddRowEvenCol"> - <input type="hidden" name="position" value="<fmt:message key="news-top.html"/>" /> - <%-- <input type="submit" name="submit_edit" value="Edit..."> --%> - <input type="submit" name="submit_edit" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> - </td> - </tr> - </table> - </form> - <form action="<%= request.getContextPath() %>/dspace-admin/news-edit" method="post"> - <table class="miscTable" align="center"> - <tr> - <%-- <td class="evenRowOddCol">Sidebar News</td> --%> - <th id="t2" class="evenRowOddCol"><fmt:message key="jsp.dspace-admin.news-main.news.sidebar"/></th> - <td headers="t2" class="evenRowEvenCol"> - <input type="hidden" name="position" value="<fmt:message key="news-side.html" />" /> - <%-- <input type="submit" name="submit_edit" value="Edit..."> --%> - <input type="submit" name="submit_edit" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> - </td> - </tr> - </table> - </form> + <h1><fmt:message key="jsp.dspace-admin.news-main.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#editnews\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </h1> + + <form action="<%= request.getContextPath() %>/dspace-admin/news-edit" method="post"> + <select class="form-control" name="position" size="5"> + <option value="<fmt:message key="news-top.html"/>"><fmt:message key="jsp.dspace-admin.news-main.news.top"/></option> + <option value="<fmt:message key="news-side.html"/>"><fmt:message key="jsp.dspace-admin.news-main.news.sidebar"/></option> + </select> + <input class="btn btn-primary" type="submit" name="submit_edit" value="<fmt:message key="jsp.dspace-admin.general.edit"/>" /> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/supervise-confirm-remove.jsp b/dspace-jspui/src/main/webapp/dspace-admin/supervise-confirm-remove.jsp index 5c76409ce57d4ae7ff85135c3222939f7af5bb3b..a8e2231bcb0913abd4e4e3a989ec2d68cf59489e 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/supervise-confirm-remove.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/supervise-confirm-remove.jsp @@ -37,7 +37,8 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.dspace-admin.supervise-confirm-remove.title" +<dspace:layout style="submission" + titlekey="jsp.dspace-admin.supervise-confirm-remove.title" navbar="admin" locbar="link" parentlink="/dspace-admin" @@ -45,20 +46,16 @@ <h1><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.heading"/></h1> -<h3><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.subheading"/></h3> - -<br/><br/> - -<div align="center"/> +<p class="help-block"><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.subheading"/></p> <% DCValue[] titleArray = wsItem.getItem().getDC("title", null, Item.ANY); // String title = (titleArray.length > 0 ? titleArray[0].value : "Untitled"); EPerson submitter = wsItem.getItem().getSubmitter(); %> - -<strong><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.titleheader"/></strong>: -<br/> +<div class="row"> +<label class="col-md-2"><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.titleheader"/>:</label> +<span> <% if (titleArray.length > 0) { @@ -73,24 +70,31 @@ <% } %> -<br/><br/> -<strong><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.authorheader"/></strong>: -<br/> +</span> +</div> +<div class="row"> +<label class="col-md-2"><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.authorheader"/>:</label> +<span> <a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a> -<br/><br/> -<strong><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.supervisorgroupheader"/></strong>: -<br/> +</span> +</div> +<div class="row"> +<label class="col-md-2"><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.supervisorgroupheader"/>:</label> +<span> <%= group.getName() %> -<br/><br/> - -<fmt:message key="jsp.dspace-admin.supervise-confirm-remove.confirm"/> +</span> +</div> +<br/> +<p class="text-danger lead"><fmt:message key="jsp.dspace-admin.supervise-confirm-remove.confirm"/></p> +<div class="pull-right"> <%-- form to request removal of supervisory linking --%> <form method="post" action=""> <input type="hidden" name="gID" value="<%= group.getID() %>"/> <input type="hidden" name="siID" value="<%= wsItem.getID() %>"/> - <input type="submit" name="submit_doremove" value="<fmt:message key="jsp.dspace-admin.general.remove"/>"/> - <input type="submit" name="submit_base" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>"/> + <input class="btn btn-default" type="submit" name="submit_base" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>"/> + <input class="btn btn-danger" type="submit" name="submit_doremove" value="<fmt:message key="jsp.dspace-admin.general.remove"/>"/> </form> +</div> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/supervise-duplicate.jsp b/dspace-jspui/src/main/webapp/dspace-admin/supervise-duplicate.jsp index da18b52b3522da57261357c8ccfb950e8410e20e..df9c603ac8966d0837f5dae4ced0241340502fac 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/supervise-duplicate.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/supervise-duplicate.jsp @@ -20,7 +20,9 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> -<dspace:layout titlekey="jsp.dspace-admin.supervise-duplicate.title" +<dspace:layout + style="submission" + titlekey="jsp.dspace-admin.supervise-duplicate.title" navbar="admin" locbar="link" parentlink="/dspace-admin" diff --git a/dspace-jspui/src/main/webapp/dspace-admin/supervise-link.jsp b/dspace-jspui/src/main/webapp/dspace-admin/supervise-link.jsp index 7a84afd5f036984756b8e436650a4aadec507f30..0aa4778f8df3a25c5344329fd346ab694bb6b90f 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/supervise-link.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/supervise-link.jsp @@ -29,6 +29,7 @@ <%@ page import="org.dspace.eperson.Group" %> <%@ page import="org.dspace.eperson.Supervisor" %> <%@ page import="org.dspace.core.Utils" %> +<%@page import="javax.servlet.jsp.jstl.fmt.LocaleSupport"%> <% // get objects from request @@ -37,24 +38,26 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.dspace-admin.supervise-link.title" +<dspace:layout style="submission" + titlekey="jsp.dspace-admin.supervise-link.title" navbar="admin" locbar="link" parentlink="/dspace-admin" parenttitlekey="jsp.administer"> -<h1><fmt:message key="jsp.dspace-admin.supervise-link.heading"/></h1> +<h1><fmt:message key="jsp.dspace-admin.supervise-link.heading"/> +<dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#supervision\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> +</h1> -<h3><fmt:message key="jsp.dspace-admin.supervise-link.choose"/></h3> +<p class="help-block"><fmt:message key="jsp.dspace-admin.supervise-link.choose"/></p> <form method="post" action=""> -<table> +<div class="input-group"> <%-- Select the group to supervise --%> - <tr> - <td> - <b><fmt:message key="jsp.dspace-admin.supervise-link.group"/></b> - <select name="TargetGroup"> + + <label class="input-group-addon"><fmt:message key="jsp.dspace-admin.supervise-link.group"/></label> + <select class="form-control" name="TargetGroup"> <% for (int i = 0; i < groups.length; i++) { @@ -64,30 +67,23 @@ } %> </select> - <br/><br/> - </td> - </tr> + <%-- Select the defaul policy type --%> - <tr> - <td> - <b><fmt:message key="jsp.dspace-admin.supervise-link.policy"/></b> - <select name="PolicyType"> + + <label class="input-group-addon"><fmt:message key="jsp.dspace-admin.supervise-link.policy"/></label> + <select class="form-control" name="PolicyType"> <option value="<%= Supervisor.POLICY_NONE %>" selected="selected"><fmt:message key="jsp.dspace-admin.supervise-link.policynone"/></option> <option value="<%= Supervisor.POLICY_EDITOR %>"><fmt:message key="jsp.dspace-admin.supervise-link.policyeditor"/></option> <option value="<%= Supervisor.POLICY_OBSERVER %>"><fmt:message key="jsp.dspace-admin.supervise-link.policyobserver"/></option> </select> - <br/><br/> - </td> - </tr> - +</div> <%-- Select the workspace item to be supervised --%> - <tr> - <td> - <b><fmt:message key="jsp.dspace-admin.supervise-link.workspace"/></b> - <br/><br/> - <div align="left"> - <table class="miscTable"> +<br/> +<div> + <p><b><fmt:message key="jsp.dspace-admin.supervise-link.workspace"/></b></p> + + <table class="table"> <tr> <th class="odRowOddCol"><fmt:message key="jsp.dspace-admin.supervise-link.id"/></th> <th class="oddRowEvenCol"><fmt:message key="jsp.dspace-admin.supervise-link.submittedby"/></th> @@ -140,18 +136,11 @@ } %> </table> - </div> - <br/><br/> - </td> - </tr> - <tr> - <td> - <input type="submit" name="submit_link" value="<fmt:message key="jsp.dspace-admin.supervise-link.submit.button"/>"/> - <input type="submit" name="submit_base" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>"/> - </td> - </tr> -</table> - +</div> +<div class="pull-right"> + <input class="btn btn-default" type="submit" name="submit_base" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>"/> + <input class="btn btn-success" type="submit" name="submit_link" value="<fmt:message key="jsp.dspace-admin.supervise-link.submit.button"/>"/> +</div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/supervise-list.jsp b/dspace-jspui/src/main/webapp/dspace-admin/supervise-list.jsp index bac956bbcbba504bf9c54a1c6975faccf4f9911f..1c7a88d4d450597bd1e9153d0cadc26a83903df5 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/supervise-list.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/supervise-list.jsp @@ -20,6 +20,7 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> +<%@page import="javax.servlet.jsp.jstl.fmt.LocaleSupport"%> <%@ page import="org.dspace.content.DCValue" %> <%@ page import="org.dspace.content.Item" %> <%@ page import="org.dspace.content.SupervisedItem" %> @@ -33,26 +34,22 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.dspace-admin.supervise-list.title" +<dspace:layout + style="submission" + titlekey="jsp.dspace-admin.supervise-list.title" navbar="admin" locbar="link" parentlink="/dspace-admin" parenttitlekey="jsp.administer"> -<h1><fmt:message key="jsp.dspace-admin.supervise-list.heading"/></h1> +<h1><fmt:message key="jsp.dspace-admin.supervise-list.heading"/> +<dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#supervision\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> +</h1> -<h3><fmt:message key="jsp.dspace-admin.supervise-list.subheading"/></h3> +<p class="help-block"><fmt:message key="jsp.dspace-admin.supervise-list.subheading"/></p> -<br/><br/> -<div align="center" /> -<%-- form to navigate to the "add supervisory settings" page --%> -<form method="post" action=""> - <input type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.supervise-list.add.button"/>"/> - <input type="submit" name="submit_base" value="<fmt:message key="jsp.dspace-admin.supervise-list.back.button"/>"/> -</form> - -<table class="miscTable"> +<table class="table"> <tr> <th class="oddRowOddCol"> @@ -91,7 +88,7 @@ <%-- form to navigate to the item policies --%> <form action="<%= request.getContextPath() %>/tools/authorize" method="post"> <input type="hidden" name="item_id" value="<%=supervisedItems[i].getItem().getID() %>"/> - <input type="submit" name="submit_item_select" value="<fmt:message key="jsp.dspace-admin.supervise-list.policies.button"/>"/> + <input class="btn btn-info" type="submit" name="submit_item_select" value="<fmt:message key="jsp.dspace-admin.supervise-list.policies.button"/>"/> </form> </td> <td class="<%= row %>RowEvenCol"> @@ -121,7 +118,7 @@ <form method="post" action=""> <input type="hidden" name="gID" value="<%= supervisors[j].getID() %>"/> <input type="hidden" name="siID" value="<%= supervisedItems[i].getID() %>"/> - <input type="submit" name="submit_remove" value="<fmt:message key="jsp.dspace-admin.general.remove"/>"/> + <input class="btn btn-danger" type="submit" name="submit_remove" value="<fmt:message key="jsp.dspace-admin.general.remove"/>"/> </form> </td> </tr> @@ -133,4 +130,11 @@ %> </table> +<div class="pull-right"> +<%-- form to navigate to the "add supervisory settings" page --%> +<form method="post" action=""> + <input class="btn btn-default" type="submit" name="submit_base" value="<fmt:message key="jsp.dspace-admin.supervise-list.back.button"/>"/> + <input class="btn btn-success" type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.supervise-list.add.button"/>"/> +</form> +</div> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/supervise-main.jsp b/dspace-jspui/src/main/webapp/dspace-admin/supervise-main.jsp index 88852e01bdd982476077e362523e49e7e6cc0f37..7a39548724205e6b7626fdac6438b66ba40dbaaf 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/supervise-main.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/supervise-main.jsp @@ -17,13 +17,18 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> -<dspace:layout titlekey="jsp.dspace-admin.supervise-main.title" +<%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> + +<dspace:layout style="submission" + titlekey="jsp.dspace-admin.supervise-main.title" navbar="admin" locbar="link" parentlink="/dspace-admin" parenttitlekey="jsp.administer"> -<h1><fmt:message key="jsp.dspace-admin.supervise-main.heading"/></h1> +<h1><fmt:message key="jsp.dspace-admin.supervise-main.heading"/> +<dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#supervision\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> +</h1> <h3><fmt:message key="jsp.dspace-admin.supervise-main.subheading"/></h3> @@ -32,11 +37,15 @@ <div align="center" /> <%-- form to navigate to any of the three options available --%> <form method="post" action=""> - <input type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.supervise-main.add.button"/>"/> - <br/><br/> - <input type="submit" name="submit_view" value="<fmt:message key="jsp.dspace-admin.supervise-main.view.button"/>"/> - <br/><br/> - <input type="submit" name="submit_clean" value="<fmt:message key="jsp.dspace-admin.supervise-main.clean.button"/>"/> + <div class="row"> + <input class="btn btn-primary col-md-6 col-md-offset-3" type="submit" name="submit_add" value="<fmt:message key="jsp.dspace-admin.supervise-main.add.button"/>"/> + </div> + <div class="row"> + <input class="btn btn-info col-md-6 col-md-offset-3" type="submit" name="submit_view" value="<fmt:message key="jsp.dspace-admin.supervise-main.view.button"/>"/> + </div> + <div class="row"> + <input class="btn btn-warning col-md-6 col-md-offset-3" type="submit" name="submit_clean" value="<fmt:message key="jsp.dspace-admin.supervise-main.clean.button"/>"/> + </div> </form> <div align="center" /> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/wizard-basicinfo.jsp b/dspace-jspui/src/main/webapp/dspace-admin/wizard-basicinfo.jsp index 9454d020419917c0b042c45d9d3753375661b229..640700a1854ec30b0ae56d739b77b7f29f0242f3 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/wizard-basicinfo.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/wizard-basicinfo.jsp @@ -29,158 +29,111 @@ <% Collection collection = (Collection) request.getAttribute("collection"); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.dspace-admin.wizard-basicinfo.title" nocache="true"> -<table width="95%"> - <tr> - <td> + <%-- <h1>Describe the Collection</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.wizard-basicinfo.title"/></h1> - </td> - <td class="standard" align="right"> + <h1><fmt:message key="jsp.dspace-admin.wizard-basicinfo.title"/> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#wizard_description\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + </h1> <form action="<%= request.getContextPath() %>/tools/collection-wizard" method="post" enctype="multipart/form-data"> - <table summary="Describe the Collection table"> - <tr> - <%-- <td><p class="submitFormLabel">Name:</p></td> --%> - <td><p class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.name"/></p></td> - <td><input type="text" name="name" size="50" id="tname" /></td> - </tr> + + <div class="form-group"> + <label for="short_description"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.name"/></label> + <%-- <td><p class="submitFormLabel">Name:</p></td> --%> + <input class="form-control" type="text" name="name" size="50" id="tname" /> + </div> <%-- Hints about table width --%> - <tr> - <td width="40%"> </td> - <td> </td> - <td width="40%"> </td> - </tr> - <tr> + + <%-- <td colspan="3" class="submitFormHelp"> Shown in list on community home page </td> --%> - <td colspan="3" class="submitFormHelp"> + <div class="help-block"> <fmt:message key="jsp.dspace-admin.wizard-basicinfo.shown"/> - </td> - </tr> - <tr> - <%-- <td><p class="submitFormLabel">Short Description:</p></td> --%> - <td><p class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.description"/></p></td> - <td><input type="text" name="short_description" size="50"/></td> - </tr> - - <tr><td> </td></tr> - - <tr> - <td colspan="3" class="submitFormHelp"> + </div> + <div class="form-group"> + <%-- <td><p class="submitFormLabel">Short Description:</p></td> --%> + <label for="short_description"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.description"/></label> + <input class="form-control" type="text" name="short_description" size="50"/> + </div> + + + <div class="help-block"> <%-- HTML, shown in center of collection home page. Be sure to enclose in <P> </P> tags! --%> <fmt:message key="jsp.dspace-admin.wizard-basicinfo.html1"/> - </td> - </tr> - <tr> - <%-- <td><p class="submitFormLabel">Introductory text:</p></td> --%> - <td><p class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.intro"/></p></td> - <td><textarea name="introductory_text" rows="4" cols="50"></textarea></td> - </tr> - - <tr><td> </td></tr> - - <tr> - <td colspan="3" class="submitFormHelp"> - <%-- Plain text, shown at bottom of collection home page --%> + </div> + <div class="form-group"> + <%-- <td><p class="submitFormLabel">Introductory text:</p></td> --%> + <label for="introductory_text"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.intro"/></label> + <textarea class="form-control" name="introductory_text" rows="4" cols="50"></textarea> + </div> + + <div class="help-block"> + <%-- Plain text, shown at bottom of collection home page --%> <fmt:message key="jsp.dspace-admin.wizard-basicinfo.plain"/> - </td> - </tr> - <tr> - <%-- <td><p class="submitFormLabel">Copyright text:</p></td> --%> - <td><p class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.copyright"/></p></td> - <td><textarea name="copyright_text" rows="3" cols="50"></textarea></td> - </tr> - - <tr><td> </td></tr> - - <tr> - <td colspan="3" class="submitFormHelp"> - <%-- HTML, shown on right-hand side of collection home page. Be sure to enclose in <P> </P> tags! --%> + </div> + <div class="form-group"> + <%-- <td><p class="submitFormLabel">Copyright text:</p></td> --%> + <label for="copyright_text"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.copyright"/></label> + <textarea class="form-control" name="copyright_text" rows="3" cols="50"></textarea> + </div> + + <div class="help-block"> + <%-- HTML, shown on right-hand side of collection home page. Be sure to enclose in <P> </P> tags! --%> <fmt:message key="jsp.dspace-admin.wizard-basicinfo.html2"/> - </td> - </tr> - <tr> - <%-- <td><p class="submitFormLabel">Side bar text:</p></td> --%> - <td><p class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.side"/></p></td> - <td><textarea name="side_bar_text" rows="4" cols="50"></textarea></td> - </tr> - - <tr><td> </td></tr> - - <tr> - <td colspan="32" class="submitFormHelp"> + </div> + + <div class="form-group"> + <%-- <td><p class="submitFormLabel">Side bar text:</p></td> --%> + <label for="side_bar_text"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.side"/></label> + <textarea class="form-control" name="side_bar_text" rows="4" cols="50"></textarea> + </div> + + + <div class="help-block"> <%-- Licence that submitters must grant. Leave this blank to use the default license. --%> <fmt:message key="jsp.dspace-admin.wizard-basicinfo.license1"/> - </td> - </tr> - <tr> - + </div> + <div class="form-group"> <%-- <td><p class="submitFormLabel">License:</p></td> --%> - <td><p class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.license2"/></p></td> - <td><textarea name="license" rows="4" cols="50"></textarea></td> - </tr> - - <tr><td> </td></tr> + <label for="side_bar_text"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.license2"/></label> + <textarea class="form-control" name="license" rows="4" cols="50"></textarea></td> + </div> - <tr> - <td colspan="3" class="submitFormHelp"> + <div class="help-block"> <%-- Plain text, any provenance information about this collection. Not shown on collection pages. --%> <fmt:message key="jsp.dspace-admin.wizard-basicinfo.plain2"/> - - </td> - </tr> - <tr> - - <%-- <td><p class="submitFormLabel">Provenance:</p></td> --%> - <td><p class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.provenance"/></p></td> - <td><textarea name="provenance_description" rows="4" cols="50"></textarea></td> - </tr> - - <tr><td> </td></tr> - - <tr> - <td colspan="3" class="submitFormHelp"> - <%-- Choose a JPEG or GIF logo for the collection home page. Should be quite small. --%> + </div> + <div class="form-group"> + <%-- <td><p class="submitFormLabel">Provenance:</p></td> --%> + <label for="provenance_description"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.provenance"/></label> + <textarea class="form-control" name="provenance_description" rows="4" cols="50"></textarea> + </div> + + <div class="help-block"> + <%-- Choose a JPEG or GIF logo for the collection home page. Should be quite small. --%> <fmt:message key="jsp.dspace-admin.wizard-basicinfo.choose"/> - - </td> - </tr> - <tr> - <%-- <td><p class="submitFormLabel">Logo:</p></td> --%> - <td><p class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.logo"/></p></td> - <td><input type="file" size="40" name="file"/></td> - </tr> - </table> - - <p> </p> - -<%-- Hidden fields needed for servlet to know which collection and page to deal with --%> + </div> + <div class="form-group"> + <%-- <td><p class="submitFormLabel">Provenance:</p></td> --%> + <label for="file"><fmt:message key="jsp.dspace-admin.wizard-basicinfo.logo"/></label> + <input class="form-control" type="file" size="40" name="file"/> + </div> + + <div class="col-md-6 pull-right btn-group"> + <%-- Hidden fields needed for servlet to know which collection and page to deal with --%> <input type="hidden" name="collection_id" value="<%= ((Collection) request.getAttribute("collection")).getID() %>" /> <input type="hidden" name="stage" value="<%= CollectionWizardServlet.BASIC_INFO %>" /> - - <center> - <table border="0" width="80%"> - <tr> - <td width="100%"> - </td> - <td> - <%-- <input type="submit" name="submit_next" value="Next >"> --%> - <input type="submit" name="submit_next" value="<fmt:message key="jsp.dspace-admin.general.next.button"/>" /> - </td> - </tr> - </table> - </center> + <%-- <input type="submit" name="submit_next" value="Next >"> --%> + <input class="btn btn-primary pull-right col-md-6" type="submit" name="submit_next" value="<fmt:message key="jsp.dspace-admin.general.next.button"/>" /> + </div> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/wizard-permissions.jsp b/dspace-jspui/src/main/webapp/dspace-admin/wizard-permissions.jsp index cbaa0fb77a9fc70ced7449aaf49d369d66e2c81f..f8483f712ba50702eadddba1f4d1bbdabfeb2111 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/wizard-permissions.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/wizard-permissions.jsp @@ -37,7 +37,7 @@ boolean mitGroup = (request.getAttribute("mitgroup") != null); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.dspace-admin.wizard-permissions.title" nocache="true"> @@ -49,27 +49,33 @@ %> <%-- <h1>Authorization to Read</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading1"/></h1> + <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading1"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#wizard_permissions\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p>Who has (by default) permission to read new items submitted to this collection? --%> - <p><fmt:message key="jsp.dspace-admin.wizard-permissions.text1"/></p> + <p class="help-block"><fmt:message key="jsp.dspace-admin.wizard-permissions.text1"/></p> <% break; case CollectionWizardServlet.PERM_SUBMIT: %> <%-- <h1>Authorization to Submit</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading2"/></h1> + <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading2"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#wizard_permissions\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p>Who has permission to submit new items to this collection? --%> - <p><fmt:message key="jsp.dspace-admin.wizard-permissions.text2"/></p> + <p class="help-block"><fmt:message key="jsp.dspace-admin.wizard-permissions.text2"/></p> <% break; case CollectionWizardServlet.PERM_WF1: %> <%-- <h1>Submission Workflow Accept/Reject Step</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading3"/></h1> + <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading3"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#wizard_permissions\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p>Who is responsible for performing the <strong>accept/reject</strong> step? They will be able to accept or reject incoming submissions. They will not be @@ -82,19 +88,23 @@ case CollectionWizardServlet.PERM_WF2: %> <%-- <h1>Submission Workflow Accept/Reject/Edit Metadata Step</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading4"/></h1> + <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading4"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#wizard_permissions\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p>Who is responsible for performing the <strong>accept/reject/edit metadata</strong> step? They will be able to edit the metadata of incoming submissions, and then accept or reject them. Only one of the group need perform the step for each submission. --%> - <p><fmt:message key="jsp.dspace-admin.wizard-permissions.text4"/></p> + <p class="help-block"><fmt:message key="jsp.dspace-admin.wizard-permissions.text4"/></p> <% break; case CollectionWizardServlet.PERM_WF3: %> <%-- <h1>Submission Workflow Edit Metadata Step</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading5"/></h1> + <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading5"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#wizard_permissions\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p>Who is responsible for performing the <strong>edit metadata</strong> step? They will be able to edit the metadata of incoming submissions, but will not @@ -106,7 +116,9 @@ case CollectionWizardServlet.PERM_ADMIN: %> <%-- <h1>Delegated Collection Administrators</h1> --%> - <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading6"/></h1> + <h1><fmt:message key="jsp.dspace-admin.wizard-permissions.heading6"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#wizard_permissions\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p>Who are the collection administrators for this collection? They will be able to decide who can submit items to the collection, withdraw items, edit item metadata (after submission), and add (map) existing items from other collections to this collection (subject to authorization from that collection).</p>--%> @@ -115,13 +127,12 @@ break; } %> - <div><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#wizard_permissions\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <%-- <p>You can change this later using the relevant sections of the DSpace admin UI.</p> --%> - <p><fmt:message key="jsp.dspace-admin.wizard-permissions.change"/></p> + <p class="alert alert-info"><fmt:message key="jsp.dspace-admin.wizard-permissions.change"/></p> <form name="epersongroup" action="<%= request.getContextPath() %>/tools/collection-wizard" method="post"> - <center> - <table> + <% // MIT group checkbox - only if there's an MIT group and on the READ and SUBMIT pages // (Sorry, everyone who isn't running DSpace at MIT, I know this isn't very elegant!) @@ -130,62 +141,37 @@ (perm == CollectionWizardServlet.PERM_READ || perm == CollectionWizardServlet.PERM_SUBMIT)) { %> - <tr> - <td></td> + <%-- <td><input type="checkbox" name="mitgroup" value="true" /> <span class="submitFormLabel">All MIT users</span> --%> - <td><input type="checkbox" name="mitgroup" value="true"/> <span class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-permissions.mit"/></span> - </td> - </tr> - <tr> - <td colspan="2"> </td> - </tr> - <tr> + <input type="checkbox" name="mitgroup" value="true"/> <span class="submitFormLabel"><fmt:message key="jsp.dspace-admin.wizard-permissions.mit"/></span> + <%-- <td colspan="2" class="submitFormHelp"><strong>OR</strong></td> --%> - <td colspan="2" class="submitFormHelp"><strong><fmt:message key="jsp.dspace-admin.wizard-permissions.or"/></strong></td> - </tr> - <tr> - <td colspan="2"> </td> - </tr> + <strong><fmt:message key="jsp.dspace-admin.wizard-permissions.or"/></strong> + <% } %> - - <tr> - <td colspan="2"> - <table align="center" width="80%"> - <tr> - <td class="submitFormHelp"><fmt:message key="jsp.dspace-admin.wizard-permissions.click"/><br/> - <dspace:selecteperson multiple="true" /> - </td> - <td> </td> - <td class="submitFormHelp"><fmt:message key="jsp.dspace-admin.wizard-permissions.click2"/><br/> - <dspace:selectgroup multiple="true" /> - </td> - </tr> - </table> - </td> - </tr> - </table> - </center> - -<%-- Hidden fields needed for servlet to know which collection and page to deal with --%> + <div class="row"> + <div class="col-md-6"> + <label for="eperson_id"><fmt:message key="jsp.dspace-admin.wizard-permissions.click"/></label> + <dspace:selecteperson multiple="true" /> + </div> + + <div class="col-md-6"> + <label for="eperson_id"><fmt:message key="jsp.dspace-admin.wizard-permissions.click2"/></label> + <dspace:selectgroup multiple="true" /> + </div> + </div> + <br/> + + <%-- Hidden fields needed for servlet to know which collection and page to deal with --%> <input type="hidden" name="collection_id" value="<%= ((Collection) request.getAttribute("collection")).getID() %>" /> <input type="hidden" name="stage" value="<%= CollectionWizardServlet.PERMISSIONS %>" /> <input type="hidden" name="permission" value="<%= perm %>" /> - <center> - <table border="0" width="80%"> - <tr> - <td width="100%"> - - </td> - <td> - <%-- <input type="submit" name="submit_next" value="Next >" onclick="javascript:finishEPerson();finishGroups();"> --%> - <input type="submit" name="submit_next" value="<fmt:message key="jsp.dspace-admin.general.next.button"/>" onclick="javascript:finishEPerson();finishGroups();"/> - </td> - </tr> - </table> - </center> + <%-- <input type="submit" name="submit_next" value="Next >" onclick="javascript:finishEPerson();finishGroups();"> --%> + <div class="row container"><input class="btn btn-primary pull-right col-md-2" type="submit" name="submit_next" value="<fmt:message key="jsp.dspace-admin.general.next.button"/>" onclick="javascript:finishEPerson();finishGroups();"/></div> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/wizard-questions.jsp b/dspace-jspui/src/main/webapp/dspace-admin/wizard-questions.jsp index b6dc5e982e66f10ef3a08e751701da0ed94e2084..8263cb76998c00bb8614d6843aed166ed862981b 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/wizard-questions.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/wizard-questions.jsp @@ -46,163 +46,125 @@ -<dspace:layout locbar="off" +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.dspace-admin.wizard-questions.title" nocache="true"> <%-- <h1>Describe the Collection</h1> --%> -<h1><fmt:message key="jsp.dspace-admin.wizard-questions.title"/></h1> +<h1><fmt:message key="jsp.dspace-admin.wizard-questions.title"/> +<dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#createcollection\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> +</h1> <form action="<%= request.getContextPath() %>/tools/collection-wizard" method="post"> <%--<p>Please check the boxes next to the statements that apply to the collection. --%> - <div><fmt:message key="jsp.dspace-admin.wizard-questions.text"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#createcollection\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> - <center> - <table class="miscTable"> - <tr class="oddRowOddCol"> - <td class="oddRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"> - <% if(!sysadmin_button ) { %> <input type="hidden" name="public_read" value="true"/> - <input type="checkbox" name="public_read" value="true" disabled="disabled" checked="checked"/> + <div class="help-block"><fmt:message key="jsp.dspace-admin.wizard-questions.text"/></div> + + <div class="input-group"> + <span class="input-group-addon"> + <% if(!sysadmin_button ) { %> + <input type="hidden" name="public_read" value="true"/> + <input type="checkbox" name="public_read" value="true" disabled="disabled" checked="checked"/> <% } else { %> - <input type="checkbox" name="public_read" value="true" checked="checked"/> + <input type="checkbox" name="public_read" value="true" checked="checked"/> <% } %> - </td> + </span> <%-- <td class="submitFormLabel" nowrap>New items should be publicly readable</td> --%> - <td class="submitFormLabel" nowrap="nowrap"> - <fmt:message key="jsp.dspace-admin.wizard-questions.check1"/> + <label class="form-control" for="public_read"> + <fmt:message key="jsp.dspace-admin.wizard-questions.check1"/> + <% if(!sysadmin_button ) { %> <fmt:message key="jsp.dspace-admin.wizard-questions.check1-disabled"/> <% } %> - </td> - </tr> - </table> - </td> - </tr> - <tr class="evenRowOddCol"> - <td class="evenRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"> + </label> + </div> + <div class="input-group"> + <span class="input-group-addon"> <% if(!bSubmittersButton) { %> <input type="hidden" name="submitters" value="false" /> <input type="checkbox" name="submitters" value="true" disabled="disabled"/> <% } else { %> <input type="checkbox" name="submitters" value="true" checked="checked"/> <% } %> - </td> + </span> + <label class="form-control" for="submitters"> <%-- <td class="submitFormLabel" nowrap>Some users will be able to submit to this collection</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.dspace-admin.wizard-questions.check2"/></td> - </tr> - </table> - </td> - </tr> - <tr class="oddRowOddCol"> - <td class="oddRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"> + <fmt:message key="jsp.dspace-admin.wizard-questions.check2"/> + </label> + </div> + <div class="input-group"> + <span class="input-group-addon"> <% if(!bWorkflowsButton) { %> <input type="hidden" name="workflow1" value="false" /> <input type="checkbox" name="workflow1" value="true" disabled="disabled"/> <% } else { %> <input type="checkbox" name="workflow1" value="true"/> <% } %> - </td> + </span> + <label class="form-control" for="workflow1"> <%-- <td class="submitFormLabel" nowrap>The submission workflow will include an <em>accept/reject</em> step</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.dspace-admin.wizard-questions.check3"/></td> - </tr> - </table> - </td> - </tr> - <tr class="evenRowOddCol"> - <td class="evenRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"> + <fmt:message key="jsp.dspace-admin.wizard-questions.check3"/> + </label> + </div> + <div class="input-group"> + <span class="input-group-addon"> <% if(!bWorkflowsButton) { %> <input type="hidden" name="workflow2" value="false" /> <input type="checkbox" name="workflow2" value="true" disabled="disabled"/> <% } else { %> <input type="checkbox" name="workflow2" value="true"/> <% } %> - </td> + </span> + <label class="form-control" for="workflow2"> <%-- <td class="submitFormLabel" nowrap>The submission workflow will include an <em>accept/reject/edit metadata</em> step</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.dspace-admin.wizard-questions.check4"/></td> - </tr> - </table> - </td> - </tr> - <tr class="oddRowOddCol"> - <td class="oddRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"> + <fmt:message key="jsp.dspace-admin.wizard-questions.check4"/> + </label> + </div> + <div class="input-group"> + <span class="input-group-addon"> <% if(!bWorkflowsButton) { %> <input type="hidden" name="workflow3" value="false" /> <input type="checkbox" name="workflow3" value="true" disabled="disabled"/> <% } else { %> <input type="checkbox" name="workflow3" value="true"/> <% } %> - </td> + </span> + <label class="form-control" for="workflow3"> <%-- <td class="submitFormLabel" nowrap>The submission workflow will include an <em>edit metadata</em> step</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.dspace-admin.wizard-questions.check5"/></td> - </tr> - </table> - </td> - </tr> - <tr class="evenRowOddCol"> - <td class="evenRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"> + <fmt:message key="jsp.dspace-admin.wizard-questions.check5"/> + </label> + </div> + <div class="input-group"> + <span class="input-group-addon"> <% if(!bAdminCreateGroup) { %> <input type="hidden" name="admins" value="false" /> <input type="checkbox" name="admins" value="true" disabled="disabled"/> <% } else { %> <input type="checkbox" name="admins" value="true"/> <% } %> - </td> + </span> + <label class="form-control" for="admins"> <%-- <td class="submitFormLabel" nowrap>This collection will have delegated collection administrators</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.dspace-admin.wizard-questions.check6"/></td> - </tr> - </table> - </td> - </tr> - <tr class="oddRowOddCol"> - <td class="oddRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"> + <fmt:message key="jsp.dspace-admin.wizard-questions.check6"/> + </label> + </div> + <div class="input-group"> + <span class="input-group-addon"> <% if(!bTemplateButton) { %> <input type="hidden" name="default.item" value="false" /> <input type="checkbox" name="default.item" value="true" disabled="disabled"/> <% } else { %> - <input type="checkbox" name="default.item" value="true"/></td> + <input type="checkbox" name="default.item" value="true"/> <% } %> + </span> + <label class="form-control" for="default.item"> <%-- <td class="submitFormLabel" nowrap>New submissions will have some metadata already filled out with defaults</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.dspace-admin.wizard-questions.check7"/></td> - </tr> - </table> - </td> - </tr> - </table> - </center> - - <p> </p> - -<%-- Hidden fields needed for servlet to know which collection and page to deal with --%> - <input type="hidden" name="collection_id" value="<%= ((Collection) request.getAttribute("collection")).getID() %>" /> - <input type="hidden" name="stage" value="<%= CollectionWizardServlet.INITIAL_QUESTIONS %>" /> - - <center> - <table border="0" width="80%"> - <tr> - <td width="100%"> - - </td> - <td> - <input type="submit" name="submit_next" value="<fmt:message key="jsp.dspace-admin.general.next.button"/>" /> - </td> - </tr> - </table> - </center> - </form> + <fmt:message key="jsp.dspace-admin.wizard-questions.check7"/> + </label> + </div> + + + <div class="row"> + <div class="col-md-6 pull-right btn-group"> + <%-- Hidden fields needed for servlet to know which collection and page to deal with --%> + <input type="hidden" name="collection_id" value="<%= ((Collection) request.getAttribute("collection")).getID() %>" /> + <input type="hidden" name="stage" value="<%= CollectionWizardServlet.INITIAL_QUESTIONS %>" /> + <input class="btn btn-primary pull-right col-md-6" type="submit" name="submit_next" value="<fmt:message key="jsp.dspace-admin.general.next.button"/>" /> + </div> + </div> +</form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/workflow-abort-confirm.jsp b/dspace-jspui/src/main/webapp/dspace-admin/workflow-abort-confirm.jsp index 3afe42e8fba80d4f994f879e2c590dbd81aedcc2..80ae8e0b2253623be57e36425eec7dfe543cd3b9 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/workflow-abort-confirm.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/workflow-abort-confirm.jsp @@ -30,7 +30,8 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.dspace-admin.workflow-abort-confirm.title" +<dspace:layout style="submission" + titlekey="jsp.dspace-admin.workflow-abort-confirm.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -43,36 +44,33 @@ </fmt:message></h1> <%-- <p>Are you sure you want to abort this workflow? It will return to the user's personal workspace</p> --%> <p><fmt:message key="jsp.dspace-admin.workflow-abort-confirm.warning"/></p> - <ul> + <div class="row"> <%-- <li>Collection: <%= workflow.getCollection().getMetadata("name") %></li> --%> - <li><fmt:message key="jsp.dspace-admin.workflow-abort-confirm.collection"> + <span class="col-md-4"><fmt:message key="jsp.dspace-admin.workflow-abort-confirm.collection"> <fmt:param><%= workflow.getCollection().getMetadata("name") %></fmt:param> - </fmt:message></li> + </fmt:message></span> + </div> + <div class="row"> <%-- <li>Submitter: <%= WorkflowManager.getSubmitterName(workflow) %></li> --%> - <li><fmt:message key="jsp.dspace-admin.workflow-abort-confirm.submitter"> + <span class="col-md-4"><fmt:message key="jsp.dspace-admin.workflow-abort-confirm.submitter"> <fmt:param><%= WorkflowManager.getSubmitterName(workflow) %></fmt:param> - </fmt:message></li> + </fmt:message></span> + </div> + <div class="row"> <%-- <li>Title: <%= WorkflowManager.getItemTitle(workflow) %></li> --%> - <li><fmt:message key="jsp.dspace-admin.workflow-abort-confirm.item-title"> + <span class="col-md-4"><fmt:message key="jsp.dspace-admin.workflow-abort-confirm.item-title"> <fmt:param><%= WorkflowManager.getItemTitle(workflow) %></fmt:param> - </fmt:message></li> - </ul> + </fmt:message></span> + </div> <form method="post" action=""> <input type="hidden" name="workflow_id" value="<%= workflow.getID() %>"/> - <center> - <table width="70%"> - <tr> - <td align="left"> + <%-- <input type="submit" name="submit_abort_confirm" value="Abort"/> --%> - <input type="submit" name="submit_abort_confirm" value="<fmt:message key="jsp.dspace-admin.workflow-abort-confirm.button"/>" /> - </td> - <td align="right"> + <input class="btn btn-default" type="submit" name="submit_abort_confirm" value="<fmt:message key="jsp.dspace-admin.workflow-abort-confirm.button"/>" /> + <%-- <input type="submit" name="submit_cancel" value="Cancel"/> --%> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-default" type="submit" name="submit_cancel" value="<fmt:message key="jsp.dspace-admin.general.cancel"/>" /> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/dspace-admin/workflow-list.jsp b/dspace-jspui/src/main/webapp/dspace-admin/workflow-list.jsp index e0663644dc5e28a7ca54425f62b1f2f2e7e03364..7f096597ee2dc6f2a24fff121e05629700023fbc 100644 --- a/dspace-jspui/src/main/webapp/dspace-admin/workflow-list.jsp +++ b/dspace-jspui/src/main/webapp/dspace-admin/workflow-list.jsp @@ -37,25 +37,17 @@ (WorkflowItem[]) request.getAttribute("workflows"); %> -<dspace:layout titlekey="jsp.dspace-admin.workflow-list.title" +<dspace:layout style="submission" + titlekey="jsp.dspace-admin.workflow-list.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin" nocache="true"> -<table width="95%"> - <tr> - <%-- <td align="left"> <h1>Currently Active Workflows</h1> --%> - <td align="left"><h1><fmt:message key="jsp.dspace-admin.workflow-list.heading"/></h1> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#workflow\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + <h1><fmt:message key="jsp.dspace-admin.workflow-list.heading"/><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#workflow\"%>"><fmt:message key="jsp.help"/></dspace:popup></h1> - <table class="miscTable" align="center" summary="Table displaying list of currently active workflows"> + <table class="table" align="center" summary="Table displaying list of currently active workflows"> <tr> <th class="oddRowOddCol"> <strong>ID</strong></th> <th class="oddRowEvenCol"><strong><fmt:message key="jsp.dspace-admin.workflow-list.collection"/></strong></th> @@ -82,7 +74,7 @@ <td class="<%= row %>RowOddCol"> <form method="post" action=""> <input type="hidden" name="workflow_id" value="<%= workflows[i].getID() %>"/> - <input type="submit" name="submit_abort" value="<fmt:message key="jsp.dspace-admin.general.abort-w-confirm"/>" /> + <input class="btn btn-default" type="submit" name="submit_abort" value="<fmt:message key="jsp.dspace-admin.general.abort-w-confirm"/>" /> </form> </td> </tr> diff --git a/dspace-jspui/src/main/webapp/home.jsp b/dspace-jspui/src/main/webapp/home.jsp index 49bae7afd84c614726b936f9bfbe202e66b98f15..79e850c53079c667d1789665adb026ede52b1194 100644 --- a/dspace-jspui/src/main/webapp/home.jsp +++ b/dspace-jspui/src/main/webapp/home.jsp @@ -12,8 +12,10 @@ - - Attributes: - communities - Community[] all communities in DSpace + - recent.submissions - RecetSubmissions --%> +<%@page import="org.dspace.content.Bitstream"%> <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> @@ -27,9 +29,13 @@ <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> <%@ page import="org.dspace.core.I18nUtil" %> <%@ page import="org.dspace.app.webui.util.UIUtil" %> +<%@ page import="org.dspace.app.webui.components.RecentSubmissions" %> <%@ page import="org.dspace.content.Community" %> <%@ page import="org.dspace.core.ConfigurationManager" %> +<%@ page import="org.dspace.core.NewsManager" %> <%@ page import="org.dspace.browse.ItemCounter" %> +<%@ page import="org.dspace.content.DCValue" %> +<%@ page import="org.dspace.content.Item" %> <% Community[] communities = (Community[]) request.getAttribute("communities"); @@ -37,8 +43,8 @@ Locale[] supportedLocales = I18nUtil.getSupportedLocales(); Locale sessionLocale = UIUtil.getSessionLocale(request); Config.set(request.getSession(), Config.FMT_LOCALE, sessionLocale); - String topNews = ConfigurationManager.readNewsFile(LocaleSupport.getLocalizedMessage(pageContext, "news-top.html")); - String sideNews = ConfigurationManager.readNewsFile(LocaleSupport.getLocalizedMessage(pageContext, "news-side.html")); + String topNews = NewsManager.readNewsFile(LocaleSupport.getLocalizedMessage(pageContext, "news-top.html")); + String sideNews = NewsManager.readNewsFile(LocaleSupport.getLocalizedMessage(pageContext, "news-side.html")); boolean feedEnabled = ConfigurationManager.getBooleanProperty("webui.feed.enable"); String feedData = "NONE"; @@ -48,13 +54,12 @@ } ItemCounter ic = new ItemCounter(UIUtil.obtainContext(request)); + + RecentSubmissions submissions = (RecentSubmissions) request.getAttribute("recent.submissions"); %> <dspace:layout locbar="nolink" titlekey="jsp.home.title" feedData="<%= feedData %>"> - <table width="95%" align="center"> - <tr align="right"> - <td align="right"> <% if (supportedLocales != null && supportedLocales.length > 1) { %> @@ -74,75 +79,22 @@ for (int i = supportedLocales.length-1; i >= 0; i--) } } %> - </td> - </tr> - <tr> - <td class="oddRowEvenCol"><%= topNews %></td> - </tr> - </table> - <br/> - <form action="<%= request.getContextPath() %>/simple-search" method="get"> - <table class="miscTable" width="95%" align="center"> - <tr> - <td class="oddRowEvenCol"> - <h3><fmt:message key="jsp.home.search1"/></h3> - <p><label for="tquery"><fmt:message key="jsp.home.search2"/></label></p> - <p><input type="text" name="query" size="20" id="tquery" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.general.search.button"/>" /></p> - </td> - </tr> - </table> - </form> - <table class="miscTable" width="95%" align="center"> - <tr> - <td class="oddRowEvenCol"> - <h3><fmt:message key="jsp.home.com1"/></h3> - <p><fmt:message key="jsp.home.com2"/></p> - - -<% - if (communities.length != 0) - { -%> - <table border="0" cellpadding="2"> -<% - - for (int i = 0; i < communities.length; i++) - { -%> <tr> - <td class="standard"> - <a href="<%= request.getContextPath() %>/handle/<%= communities[i].getHandle() %>"><%= communities[i].getMetadata("name") %></a> -<% - if (ConfigurationManager.getBooleanProperty("webui.strengths.show")) - { -%> - [<%= ic.getCount(communities[i]) %>] -<% - } + <div class="jumbotron"> + <%= topNews %> + </div> -%> - </td> - </tr> +<div class="row"> <% - } +if (submissions != null && submissions.count() > 0) +{ %> - </table> -<% - } -%> - - </td> - </tr> - </table> - <dspace:sidebar> - <%= sideNews %> - <% + <div class="col-md-8"> + <div class="panel panel-primary"> + <div id="recent-submissions-carousel" class="panel-heading carousel slide"> + <h3><fmt:message key="jsp.collection-home.recentsub"/> + <% if(feedEnabled) { - %> - <center> - <h4><fmt:message key="jsp.home.feeds"/></h4> - <% String[] fmts = feedData.substring(feedData.indexOf(':')+1).split(","); String icon = null; int width = 0; @@ -167,11 +119,115 @@ for (int i = supportedLocales.length-1; i >= 0; i--) <a href="<%= request.getContextPath() %>/feed/<%= fmts[j] %>/site"><img src="<%= request.getContextPath() %>/image/<%= icon %>" alt="RSS Feed" width="<%= width %>" height="15" vspace="3" border="0" /></a> <% } - %> - </center> - <% } %> + </h3> + + <!-- Wrapper for slides --> + <div class="carousel-inner"> + <% + boolean first = true; + for (Item item : submissions.getRecentSubmissions()) + { + DCValue[] dcv = item.getMetadata("dc", "title", null, Item.ANY); + String displayTitle = "Untitled"; + if (dcv != null & dcv.length > 0) + { + displayTitle = dcv[0].value; + } + dcv = item.getMetadata("dc", "description", "abstract", Item.ANY); + String displayAbstract = ""; + if (dcv != null & dcv.length > 0) + { + displayAbstract = dcv[0].value; + } + %> + <div style="padding-bottom: 50px; min-height: 200px;" class="item <%= first?"active":""%>"> + <div style="padding-left: 80px; padding-right: 80px; display: inline-block;"><%= StringUtils.abbreviate(displayTitle, 400) %> + <a href="<%= request.getContextPath() %>/handle/<%=item.getHandle() %>"> + <button class="btn btn-success" type="button">See</button> + </a> + <p><%= StringUtils.abbreviate(displayAbstract, 500) %></p> + </div> + </div> + <% + first = false; + } + %> + </div> + + <!-- Controls --> + <a class="left carousel-control" href="#recent-submissions-carousel" data-slide="prev"> + <span class="icon-prev"></span> + </a> + <a class="right carousel-control" href="#recent-submissions-carousel" data-slide="next"> + <span class="icon-next"></span> + </a> + + <ol class="carousel-indicators"> + <li data-target="#recent-submissions-carousel" data-slide-to="0" class="active"></li> + <% for (int i = 1; i < submissions.count(); i++){ %> + <li data-target="#recent-submissions-carousel" data-slide-to="<%= i %>"></li> + <% } %> + </ol> + </div></div></div> +<% +} +%> +<div class="col-md-4"> + <%= sideNews %> +</div> +</div> +<div class="container row"> +<% +if (communities != null && communities.length != 0) +{ +%> + <div class="col-md-4"> + <h3><fmt:message key="jsp.home.com1"/></h3> + <p><fmt:message key="jsp.home.com2"/></p> + <div class="list-group"> +<% + boolean showLogos = ConfigurationManager.getBooleanProperty("jspui.home-page.logos", true); + for (int i = 0; i < communities.length; i++) + { +%><div class="list-group-item row"> +<% + Bitstream logo = communities[i].getLogo(); + if (showLogos && logo != null) { %> + <div class="col-md-3"> + <img alt="Logo" class="img-responsive" src="<%= request.getContextPath() %>/retrieve/<%= logo.getID() %>" /> + </div> + <div class="col-md-9"> +<% } else { %> + <div class="col-md-12"> +<% } %> + <h4 class="list-group-item-heading"><a href="<%= request.getContextPath() %>/handle/<%= communities[i].getHandle() %>"><%= communities[i].getMetadata("name") %></a> +<% + if (ConfigurationManager.getBooleanProperty("webui.strengths.show")) + { +%> + <span class="badge pull-right"><%= ic.getCount(communities[i]) %></span> +<% + } + +%> + </h4> + <p><%= communities[i].getMetadata("short_description") %></p> + </div> +</div> +<% + } +%> + </div> + </div> +<% +} +%> + <% + int discovery_panel_cols = 8; + int discovery_facet_cols = 4; + %> <%@ include file="discovery/static-sidebar-facet.jsp" %> - </dspace:sidebar> +</div> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/index.jsp b/dspace-jspui/src/main/webapp/index.jsp index b9f9630a1e78e7daa0d9bc0f9e2dd8e38c79b80b..cf9dfc5552c18d389a918e6ec7072fdbb260fed0 100644 --- a/dspace-jspui/src/main/webapp/index.jsp +++ b/dspace-jspui/src/main/webapp/index.jsp @@ -66,10 +66,6 @@ throw new ServletException(e); } - // Home page shows community list - Community[] communities = Community.findAllTop(context); - request.setAttribute("communities", communities); - // Show home page JSP JSPManager.showJSP(request, response, "/home.jsp"); } diff --git a/dspace-jspui/src/main/webapp/layout/footer-default.jsp b/dspace-jspui/src/main/webapp/layout/footer-default.jsp index 309660dbd7a1cf47b03d92e9d32cf0c7cbdbbdb8..68ac2fa3c8032233e33901a7e85d36b90d66aeae 100644 --- a/dspace-jspui/src/main/webapp/layout/footer-default.jsp +++ b/dspace-jspui/src/main/webapp/layout/footer-default.jsp @@ -20,50 +20,35 @@ <% String sidebar = (String) request.getAttribute("dspace.layout.sidebar"); - int overallColSpan = 3; - if (sidebar == null) - { - overallColSpan = 2; - } %> - <%-- End of page content --%> - <p> </p> - </td> <%-- Right-hand side bar if appropriate --%> <% if (sidebar != null) { %> - <td class="sidebar"> + </div> + <div class="col-md-3"> <%= sidebar %> - </td> + </div> + </div> <% } %> - </tr> - +</div> +</main> <%-- Page footer --%> - <tr class="pageFooterBar"> - <td colspan="<%= overallColSpan %>" class="pageFootnote"> - <table class="pageFooterBar" width="100%"> - <tr> - <td> - <a href="http://validator.w3.org/check?uri=referer"><img - src="<%= request.getContextPath() %>/image/valid-xhtml10.png" - alt="Valid XHTML 1.0!" height="31" width="88" /></a> - </td> - <td class="pageFootnote"> - <fmt:message key="jsp.layout.footer-default.text"/> - + <footer class="navbar navbar-inverse navbar-bottom"> + <div id="designedby" class="container text-muted"> + <fmt:message key="jsp.layout.footer-default.theme-by"/> <a href="http://www.cineca.it"><img + src="<%= request.getContextPath() %>/image/logo-cineca-small.png" + alt="Logo CINECA" /></a> + <div id="footer_feedback" class="pull-right"> + <p class="text-muted"><fmt:message key="jsp.layout.footer-default.text"/> - <a target="_blank" href="<%= request.getContextPath() %>/feedback"><fmt:message key="jsp.layout.footer-default.feedback"/></a> - <a href="<%= request.getContextPath() %>/htmlmap"></a> - </td> - <td nowrap="nowrap" valign="middle"> <%-- nowrap, valign for broken NS 4.x --%> - </td> - </tr> - </table> - </td> - </tr> - </table> + <a href="<%= request.getContextPath() %>/htmlmap"></a></p> + </div> + </div> + </footer> </body> </html> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/layout/header-default.jsp b/dspace-jspui/src/main/webapp/layout/header-default.jsp index 7361f1e298c1c2df3d73b01676ff5db2c40258b6..250124b2fa4f2dc7e4cb08650bd0b92fc1eae5db 100644 --- a/dspace-jspui/src/main/webapp/layout/header-default.jsp +++ b/dspace-jspui/src/main/webapp/layout/header-default.jsp @@ -42,17 +42,18 @@ String analyticsKey = ConfigurationManager.getProperty("jspui.google.analytics.key"); %> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<!DOCTYPE html> <html> <head> <title><%= siteName %>: <%= title %></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta name="Generator" content="<%= generator %>" /> - <link rel="stylesheet" href="<%= request.getContextPath() %>/styles.css" type="text/css" /> - <link rel="stylesheet" href="<%= request.getContextPath() %>/print.css" media="print" type="text/css" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="shortcut icon" href="<%= request.getContextPath() %>/favicon.ico" type="image/x-icon"/> - <link rel="stylesheet" href="<%= request.getContextPath() %>/css/discovery.css" type="text/css" /> - <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/jquery-ui-1.8.22.custom/redmond/jquery-ui-1.8.22.custom.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/jquery-ui-1.10.3.custom/redmond/jquery-ui-1.10.3.custom.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/bootstrap/bootstrap.min.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/bootstrap/bootstrap-theme.min.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/bootstrap/dspace-theme.css" type="text/css" /> <% if (!"NONE".equals(feedRef)) { @@ -78,13 +79,11 @@ } %> - <script type='text/javascript' src='<%= request.getContextPath() %>/static/js/jquery/jquery-1.7.2.min.js'></script> - <script type='text/javascript' src='<%= request.getContextPath() %>/static/js/jquery/jquery-ui-1.8.22.custom.min.js'></script> + <script type='text/javascript' src="<%= request.getContextPath() %>/static/js/jquery/jquery-1.10.2.min.js"></script> + <script type='text/javascript' src='<%= request.getContextPath() %>/static/js/jquery/jquery-ui-1.10.3.custom.min.js'></script> + <script type='text/javascript' src='<%= request.getContextPath() %>/static/js/bootstrap/bootstrap.min.js'></script> + <script type='text/javascript' src='<%= request.getContextPath() %>/static/js/holder.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> <%--Gooogle Analytics recording.--%> @@ -111,70 +110,68 @@ <% } %> + +<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries --> +<!--[if lt IE 9]> + <script src="<%= request.getContextPath() %>/static/js/html5shiv.js"></script> + <script src="<%= request.getContextPath() %>/static/js/respond.min.js"></script> +<![endif]--> </head> <%-- HACK: leftmargin, topmargin: for non-CSS compliant Microsoft IE browser --%> <%-- HACK: marginwidth, marginheight: for non-CSS compliant Netscape browser --%> - <body> - - <%-- DSpace top-of-page banner --%> - <%-- HACK: width, border, cellspacing, cellpadding: for non-CSS compliant Netscape, Mozilla browsers --%> - <table class="pageBanner" width="100%" border="0" cellpadding="0" cellspacing="0"> - - <%-- DSpace logo --%> - <tr> - <td> - <a href="<%= request.getContextPath() %>/"><img src="<%= request.getContextPath() %>/image/dspace-blue.gif" alt="<fmt:message key="jsp.layout.header-default.alt"/>" width="198" height="79" border="0"/></a></td> - <td class="tagLine" width="99%"> <%-- Make as wide as possible. cellpadding repeated for broken NS 4.x --%> - <a class="tagLineText" target="_blank" href="http://www.dspace.org/"><fmt:message key="jsp.layout.header-default.about"/></a> - </td> - <td nowrap="nowrap" valign="middle"> - </td> - </tr> - <tr class="stripe"> <%-- Blue stripe --%> - <td colspan="3"> </td> - </tr> - </table> - - <%-- Localization --%> -<%-- <c:if test="${param.locale != null}">--%> -<%-- <fmt:setLocale value="${param.locale}" scope="session" /> --%> -<%-- </c:if> --%> -<%-- <fmt:setBundle basename="Messages" scope="session"/> --%> - - <%-- Page contents --%> - - <%-- HACK: width, border, cellspacing, cellpadding: for non-CSS compliant Netscape, Mozilla browsers --%> - <table class="centralPane" width="99%" border="0" cellpadding="3" cellspacing="1"> - - <%-- HACK: valign: for non-CSS compliant Netscape browser --%> - <tr valign="top"> - - <%-- Navigation bar --%> -<% + <body class="undernavigation"> +<a class="sr-only" href="#content">Skip navigation</a> +<header class="navbar navbar-inverse navbar-fixed-top"> + <% if (!navbar.equals("off")) { %> - <td class="navigationBar"> + <div class="container"> <dspace:include page="<%= navbar %>" /> - </td> + </div> <% } + else + { + %> + <div class="container"> + <dspace:include page="/layout/navbar-minimal.jsp" /> + </div> +<% + } %> - <%-- Page Content --%> - - <%-- HACK: width specified here for non-CSS compliant Netscape 4.x --%> - <%-- HACK: Width shouldn't really be 100%, but omitting this means --%> - <%-- navigation bar gets far too wide on certain pages --%> - <td class="pageContents" width="100%"> - +</header> + +<main id="content" role="main"> +<div class="container banner"> + <div class="row"> + <div class="col-md-9 brand"> + <h1><fmt:message key="jsp.layout.header-default.brand.heading" /></h1> + <fmt:message key="jsp.layout.header-default.brand.description" /> + </div> + <div class="col-md-3"><img class="pull-right" src="<%= request.getContextPath() %>/image/logo.gif"> + </div> + </div> +</div> +<br/> <%-- Location bar --%> <% if (locbar) { %> +<div class="container"> <dspace:include page="/layout/location-bar.jsp" /> +</div> <% } %> + + + <%-- Page contents --%> +<div class="container"> +<% if (request.getAttribute("dspace.layout.sidebar") != null) { %> + <div class="row"> + <div class="col-md-9"> +<% } %> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/layout/location-bar.jsp b/dspace-jspui/src/main/webapp/layout/location-bar.jsp index 953d39e024e95b853be7921bcf82a790bcae8f00..9fe72c56b44cefb042e1b8271cf545d579afab61 100644 --- a/dspace-jspui/src/main/webapp/layout/location-bar.jsp +++ b/dspace-jspui/src/main/webapp/layout/location-bar.jsp @@ -25,8 +25,7 @@ <%@ page contentType="text/html;charset=UTF-8" %> <%@ page import="java.util.List" %> - -<p class="locationBar"> +<ol class="breadcrumb btn-success"> <% List parentTitles = (List) request.getAttribute("dspace.layout.parenttitles"); List parentLinks = (List) request.getAttribute("dspace.layout.parentlinks"); @@ -36,24 +35,26 @@ String s = (String) parentTitles.get(i); String u = (String) parentLinks.get(i); - // New line for each breadcrumb (no <br> needed for first) - if (i > 0) - { -%><br/><% - } - if (u.equals("")) { + if (i == parentTitles.size()) + { %> -<%= s %> > -<% +<li class="active"><%= s %></li> +<% + } + else + { +%> +<li><%= s %></li> +<% } } else { %> -<a href="<%= request.getContextPath() %><%= u %>"><%= s %></a> > + <li><a href="<%= request.getContextPath() %><%= u %>"><%= s %></a></li> <% } } %> -</p> +</ol> diff --git a/dspace-jspui/src/main/webapp/layout/navbar-admin.jsp b/dspace-jspui/src/main/webapp/layout/navbar-admin.jsp index fa967e470d30bb44f205d43dc3e1e2f8541c2944..ac07ae0cab8cbd0ede64a113378af910555d70bf 100644 --- a/dspace-jspui/src/main/webapp/layout/navbar-admin.jsp +++ b/dspace-jspui/src/main/webapp/layout/navbar-admin.jsp @@ -21,12 +21,16 @@ <%@ page import="org.dspace.browse.BrowseInfo" %> <%@ page import="org.dspace.sort.SortOption" %> <%@ page import="org.dspace.app.webui.util.UIUtil" %> - +<%@ page import="org.dspace.eperson.EPerson" %> +<%@page import="org.apache.commons.lang.StringUtils"%> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <% + // Is anyone logged in? + EPerson user = (EPerson) request.getAttribute("dspace.current.user"); + // Get the current page, minus query string String currentPage = UIUtil.getOriginalURL(request); int c = currentPage.indexOf( '?' ); @@ -34,164 +38,84 @@ { currentPage = currentPage.substring(0, c); } -%> - -<%-- HACK: width, border, cellspacing, cellpadding: for non-CSS compliant Netscape, Mozilla browsers --%> -<table width="100%" border="0" cellspacing="2" cellpadding="2"> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/tools/edit-communities") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/tools/edit-communities"><fmt:message key="jsp.layout.navbar-admin.communities-collections"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/dspace-admin/edit-epeople") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin/edit-epeople"><fmt:message key="jsp.layout.navbar-admin.epeople"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/tools/group-edit") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/tools/group-edit"><fmt:message key="jsp.layout.navbar-admin.groups"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/tools/edit-item") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/tools/edit-item"><fmt:message key="jsp.layout.navbar-admin.items"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/dspace-admin/metadata-schema-registry") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin/metadata-schema-registry"><fmt:message key="jsp.layout.navbar-admin.metadataregistry"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/dspace-admin/format-registry") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin/format-registry"><fmt:message key="jsp.layout.navbar-admin.formatregistry"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/dspace-admin/workflow") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin/workflow"><fmt:message key="jsp.layout.navbar-admin.workflow"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/tools/authorize") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/tools/authorize"><fmt:message key="jsp.layout.navbar-admin.authorization"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/dspace-admin/news-edit") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin/news-edit"><fmt:message key="jsp.layout.navbar-admin.editnews"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/dspace-admin/license-edit") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin/license-edit"><fmt:message key="jsp.layout.navbar-admin.editlicense"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/dspace-admin/supervise") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin/supervise"><fmt:message key="jsp.layout.navbar-admin.supervisors"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/statistics") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/statistics"><fmt:message key="jsp.layout.navbar-admin.statistics"/></a> - </td> - </tr> - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/metadataimport") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin/metadataimport"><fmt:message key="jsp.layout.navbar-admin.metadataimport"/></a> - </td> - </tr> - - <tr> - <td colspan="2"> </td> - </tr> + // E-mail may have to be truncated + String navbarEmail = null; + if (user != null) + { + navbarEmail = user.getEmail(); + } -<% - // get the browse indices - BrowseInfo binfo = (BrowseInfo) request.getAttribute("browse.info"); %> - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= ( binfo != null ? "arrow-highlight" : "arrow" ) %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin/withdrawn"><fmt:message key="jsp.layout.navbar-admin.withdrawn"/></a> - </td> - </tr> - - <tr> - <td colspan="2"> </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/arrow.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\")%>"><fmt:message key="jsp.layout.navbar-admin.help"/></dspace:popup> - </td> - </tr> - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/arrow.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/logout"><fmt:message key="jsp.layout.navbar-admin.logout"/></a> - </td> - </tr> -</table> + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="<%= request.getContextPath() %>/"><img height="25px" src="<%= request.getContextPath() %>/image/dspace-logo-only.png" /></a> + </div> + <nav class="collapse navbar-collapse bs-navbar-collapse" role="navigation"> + <ul class="nav navbar-nav"> + <li><a href="<%= request.getContextPath() %>/"><span class="glyphicon glyphicon-home"></span> <fmt:message key="jsp.layout.navbar-default.home"/></a></li> + + <li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><fmt:message key="jsp.layout.navbar-admin.contents"/> <b class="caret"></b></a> + <ul class="dropdown-menu"> + <li><a href="<%= request.getContextPath() %>/tools/edit-communities"><fmt:message key="jsp.layout.navbar-admin.communities-collections"/></a></li> + <li class="divider"></li> + <li><a href="<%= request.getContextPath() %>/tools/edit-item"><fmt:message key="jsp.layout.navbar-admin.items"/></a></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/workflow"><fmt:message key="jsp.layout.navbar-admin.workflow"/></a></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/supervise"><fmt:message key="jsp.layout.navbar-admin.supervisors"/></a></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/curate"><fmt:message key="jsp.layout.navbar-admin.curate"/></a></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/withdrawn"><fmt:message key="jsp.layout.navbar-admin.withdrawn"/></a></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/privateitems"><fmt:message key="jsp.layout.navbar-admin.privateitems"/></a></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/metadataimport"><fmt:message key="jsp.layout.navbar-admin.metadataimport"/></a></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/batchmetadataimport"><fmt:message key="jsp.layout.navbar-admin.batchmetadataimport"/></a></li> + </ul> + </li> + + <li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><fmt:message key="jsp.layout.navbar-admin.accesscontrol"/> <b class="caret"></b></a> + <ul class="dropdown-menu"> + <li><a href="<%= request.getContextPath() %>/dspace-admin/edit-epeople"><fmt:message key="jsp.layout.navbar-admin.epeople"/></a></li> + <li><a href="<%= request.getContextPath() %>/tools/group-edit"><fmt:message key="jsp.layout.navbar-admin.groups"/></a></li> + <li><a href="<%= request.getContextPath() %>/tools/authorize"><fmt:message key="jsp.layout.navbar-admin.authorization"/></a></li> + </ul> + </li> + <li><a href="<%= request.getContextPath() %>/statistics"><fmt:message key="jsp.layout.navbar-admin.statistics"/></a></li> + <li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><fmt:message key="jsp.layout.navbar-admin.settings"/> <b class="caret"></b></a> + <ul class="dropdown-menu"> + <li><a href="<%= request.getContextPath() %>/dspace-admin/metadata-schema-registry"><fmt:message key="jsp.layout.navbar-admin.metadataregistry"/></a></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/format-registry"><fmt:message key="jsp.layout.navbar-admin.formatregistry"/></a></li> + <li class="divider"></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/news-edit"><fmt:message key="jsp.layout.navbar-admin.editnews"/></a></li> + <li class="divider"></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin/license-edit"><fmt:message key="jsp.layout.navbar-admin.editlicense"/></a></li> + </ul> + </li> + <li class="<%= ( currentPage.endsWith( "/help" ) ? "active" : "" ) %>"><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") %>"><fmt:message key="jsp.layout.navbar-admin.help"/></dspace:popup></li> + </ul> + <div class="nav navbar-nav navbar-right"> + <ul class="nav navbar-nav navbar-right"> + <li class="dropdown"> + + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-user"></span> <fmt:message key="jsp.layout.navbar-default.loggedin"> + <fmt:param><%= StringUtils.abbreviate(navbarEmail, 20) %></fmt:param> + </fmt:message> <b class="caret"></b></a> + <ul class="dropdown-menu"> + <li><a href="<%= request.getContextPath() %>/subscribe"><fmt:message key="jsp.layout.navbar-default.receive"/></a></li> + <li><a href="<%= request.getContextPath() %>/mydspace"><fmt:message key="jsp.layout.navbar-default.users"/></a></li> + <li><a href="<%= request.getContextPath() %>/profile"><fmt:message key="jsp.layout.navbar-default.edit"/></a></li> + + + <li><a href="<%= request.getContextPath() %>/logout"><span class="glyphicon glyphicon-log-out"></span> <fmt:message key="jsp.layout.navbar-default.logout"/></a></li> + + </ul> + </li> + </ul> + + </div> +</nav> diff --git a/dspace-jspui/src/main/webapp/layout/navbar-default.jsp b/dspace-jspui/src/main/webapp/layout/navbar-default.jsp index f78b16a95462d47808e5c54305c8bcd5affa4b17..9077d09620ba59629a3474914994fb54782d8d5c 100644 --- a/dspace-jspui/src/main/webapp/layout/navbar-default.jsp +++ b/dspace-jspui/src/main/webapp/layout/navbar-default.jsp @@ -11,6 +11,7 @@ - Default navigation bar --%> +<%@page import="org.apache.commons.lang.StringUtils"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ page contentType="text/html;charset=UTF-8" %> @@ -50,10 +51,6 @@ if (user != null) { navbarEmail = user.getEmail(); - if (navbarEmail.length() > 18) - { - navbarEmail = navbarEmail.substring(0, 17) + "..."; - } } // get the browse indices @@ -74,32 +71,87 @@ } %> -<%-- Search Box --%> -<form method="get" action="<%= request.getContextPath() %>/simple-search"> -<% + <div class="navbar-header"> + <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + <span class="icon-bar"></span> + </button> + <a class="navbar-brand" href="<%= request.getContextPath() %>/"><img height="25px" src="<%= request.getContextPath() %>/image/dspace-logo-only.png" /></a> + </div> + <nav class="collapse navbar-collapse bs-navbar-collapse" role="navigation"> + <ul class="nav navbar-nav"> + <li class="<%= currentPage.endsWith("/home.jsp")? "active" : "" %>"><a href="<%= request.getContextPath() %>/"><span class="glyphicon glyphicon-home"></span> <fmt:message key="jsp.layout.navbar-default.home"/></a></li> + + <li class="dropdown"> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><fmt:message key="jsp.layout.navbar-default.browse"/> <b class="caret"></b></a> + <ul class="dropdown-menu"> + <li><a href="<%= request.getContextPath() %>/community-list"><fmt:message key="jsp.layout.navbar-default.communities-collections"/></a></li> + <li class="divider"></li> + <li class="dropdown-header">Browse Items by:</li> + <%-- Insert the dynamic browse indices here --%> + + <% + for (int i = 0; i < bis.length; i++) + { + BrowseIndex bix = bis[i]; + String key = "browse.menu." + bix.getName(); + %> + <li><a href="<%= request.getContextPath() %>/browse?type=<%= bix.getName() %>"><fmt:message key="<%= key %>"/></a></li> + <% + } + %> + + <%-- End of dynamic browse indices --%> + + </ul> + </li> + <li class="<%= ( currentPage.endsWith( "/help" ) ? "active" : "" ) %>"><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") %>"><fmt:message key="jsp.layout.navbar-default.help"/></dspace:popup></li> + </ul> + <div class="nav navbar-nav navbar-right"> + <ul class="nav navbar-nav navbar-right"> + <li class="dropdown"> + <% if (user != null) { -%> - <p class="loggedIn"><fmt:message key="jsp.layout.navbar-default.loggedin"> - <fmt:param><%= navbarEmail %></fmt:param> - </fmt:message> - (<a href="<%= request.getContextPath() %>/logout"><fmt:message key="jsp.layout.navbar-default.logout"/></a>)</p> -<% - } -%> - <table width="100%" class="searchBox"> - <tr> - <td> - <table width="100%" border="0" cellspacing="0" > - <tr> - <td class="searchBoxLabel"><label for="tequery"><fmt:message key="jsp.layout.navbar-default.search"/></label></td> - </tr> - <tr> - <td class="searchBoxLabelSmall" valign="middle" nowrap="nowrap"> - <%-- <input type="text" name="query" id="tequery" size="10"/><input type=image border="0" src="<%= request.getContextPath() %>/image/search-go.gif" name="submit" alt="Go" value="Go"/> --%> - <input type="text" name="query" id="tequery" size="8"/><input type="submit" name="submit" value="<fmt:message key="jsp.layout.navbar-default.go"/>" /> - <br/><a href="<%= request.getContextPath() %>/advanced-search"><fmt:message key="jsp.layout.navbar-default.advanced"/></a> + %> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-user"></span> <fmt:message key="jsp.layout.navbar-default.loggedin"> + <fmt:param><%= StringUtils.abbreviate(navbarEmail, 20) %></fmt:param> + </fmt:message> <b class="caret"></b></a> + <% + } else { + %> + <a href="#" class="dropdown-toggle" data-toggle="dropdown"><span class="glyphicon glyphicon-user"></span> <fmt:message key="jsp.layout.navbar-default.sign"/> <b class="caret"></b></a> + <% } %> + <ul class="dropdown-menu"> + <li><a href="<%= request.getContextPath() %>/mydspace"><fmt:message key="jsp.layout.navbar-default.users"/></a></li> + <li><a href="<%= request.getContextPath() %>/subscribe"><fmt:message key="jsp.layout.navbar-default.receive"/></a></li> + <li><a href="<%= request.getContextPath() %>/profile"><fmt:message key="jsp.layout.navbar-default.edit"/></a></li> + + <% + if (isAdmin) + { + %> + <li class="divider"></li> + <li><a href="<%= request.getContextPath() %>/dspace-admin"><fmt:message key="jsp.administer"/></a></li> + <% + } + if (user != null) { + %> + <li><a href="<%= request.getContextPath() %>/logout"><span class="glyphicon glyphicon-log-out"></span> <fmt:message key="jsp.layout.navbar-default.logout"/></a></li> + <% } %> + </ul> + </li> + </ul> + + <%-- Search Box --%> + <form method="get" action="<%= request.getContextPath() %>/simple-search" class="navbar-form navbar-right" scope="search"> + <div class="form-group"> + <input type="text" class="form-control" placeholder="<fmt:message key="jsp.layout.navbar-default.search"/>" name="query" id="tequery" size="25"/> + </div> + <button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button> +<%-- <br/><a href="<%= request.getContextPath() %>/advanced-search"><fmt:message key="jsp.layout.navbar-default.advanced"/></a> <% if (ConfigurationManager.getBooleanProperty("webui.controlledvocabulary.enable")) { @@ -107,138 +159,6 @@ <br/><a href="<%= request.getContextPath() %>/subject-search"><fmt:message key="jsp.layout.navbar-default.subjectsearch"/></a> <% } -%> - </td> - </tr> - </table> - </td> - </tr> - </table> -</form> - -<%-- HACK: width, border, cellspacing, cellpadding: for non-CSS compliant Netscape, Mozilla browsers --%> -<table width="100%" border="0" cellspacing="2" cellpadding="2"> - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= (currentPage.endsWith("/index.jsp") ? "arrow-highlight" : "arrow") %>.gif" width="16" height="16"/> - </td> - - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/"><fmt:message key="jsp.layout.navbar-default.home"/></a> - </td> - </tr> - - <tr> - <td colspan="2"> </td> - </tr> - - <tr> - <td nowrap="nowrap" colspan="2" class="navigationBarSublabel"><fmt:message key="jsp.layout.navbar-default.browse"/></td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= ( currentPage.endsWith( "/community-list" ) ? "arrow-highlight" : "arrow" ) %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/community-list"><fmt:message key="jsp.layout.navbar-default.communities-collections"/></a> - </td> - </tr> - - -<%-- Insert the dynamic browse indices here --%> - -<% - for (int i = 0; i < bis.length; i++) - { - BrowseIndex bix = bis[i]; - String key = "browse.menu." + bix.getName(); - %> - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= ( browseCurrent.equals(bix.getName()) ? "arrow-highlight" : "arrow" ) %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/browse?type=<%= bix.getName() %>"><fmt:message key="<%= key %>"/></a> - </td> - </tr> - <% - } -%> - -<%-- End of dynamic browse indices --%> - - <tr> - <td colspan="2"> </td> - </tr> - - <tr> - <td nowrap="nowrap" colspan="2" class="navigationBarSublabel"><fmt:message key="jsp.layout.navbar-default.sign"/></td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= ( currentPage.endsWith( "/subscribe" ) ? "arrow-highlight" : "arrow" ) %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/subscribe"><fmt:message key="jsp.layout.navbar-default.receive"/></a> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= ( currentPage.endsWith( "/mydspace" ) ? "arrow-highlight" : "arrow" ) %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/mydspace"><fmt:message key="jsp.layout.navbar-default.users"/></a><br/> - <fmt:message key="jsp.layout.navbar-default.users-authorized" /> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= ( currentPage.endsWith( "/profile" ) ? "arrow-highlight" : "arrow" ) %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/profile"><fmt:message key="jsp.layout.navbar-default.edit"/></a> - </td> - </tr> - -<% - if (isAdmin) - { -%> - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= ( currentPage.endsWith( "/dspace-admin" ) ? "arrow-highlight" : "arrow" ) %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="<%= request.getContextPath() %>/dspace-admin"><fmt:message key="jsp.administer"/></a> - </td> - </tr> -<% - } -%> - - <tr> - <td colspan="2"> </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= ( currentPage.endsWith( "/help" ) ? "arrow-highlight" : "arrow" ) %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\")%>"><fmt:message key="jsp.layout.navbar-default.help"/></dspace:popup> - </td> - </tr> - - <tr class="navigationBarItem"> - <td> - <img alt="" src="<%= request.getContextPath() %>/image/<%= ( currentPage.endsWith( "/about" ) ? "arrow-highlight" : "arrow" ) %>.gif" width="16" height="16"/> - </td> - <td nowrap="nowrap" class="navigationBarItem"> - <a href="http://www.dspace.org/"><fmt:message key="jsp.layout.navbar-default.about"/></a> - </td> - </tr> -</table> +%> --%> + </form></div> + </nav> diff --git a/dspace-jspui/src/main/webapp/login/incorrect.jsp b/dspace-jspui/src/main/webapp/login/incorrect.jsp index 135064d12de15e27a0cd7b29a9a2b9967a58c071..cd6386e7eb168750a8349a184d4dabec3b45fc9c 100644 --- a/dspace-jspui/src/main/webapp/login/incorrect.jsp +++ b/dspace-jspui/src/main/webapp/login/incorrect.jsp @@ -22,26 +22,28 @@ <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> -<dspace:layout navbar="off" +<dspace:layout style="submission" navbar="default" locbar="nolink" titlekey="jsp.login.incorrect.title"> - <table border="0" width="90%"> - <tr> - <td align="left"> + <%-- <h1>Log In to DSpace</h1> --%> - <h1><fmt:message key="jsp.login.incorrect.heading"/></h1> - </td> - <td align="right" class="standard"> + <h1><fmt:message key="jsp.login.incorrect.heading"/> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#login\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> + </h1> + + + <%-- <p align="center"><strong>The e-mail address and password you supplied were not valid. Please try again, or have you <a href="<%= request.getContextPath() %>/forgot">forgotten your password</a>?</strong></p> --%> - <p align="center"><strong><fmt:message key="jsp.login.incorrect.text"> + <p class="alert alert-warning"><strong><fmt:message key="jsp.login.incorrect.text"> <fmt:param><%= request.getContextPath() %>/forgot</fmt:param> </fmt:message></strong></p> + <div class="panel panel-primary"> + <div class="panel-heading"><fmt:message key="jsp.login.password.heading"/> + <span class="pull-right"><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#login\"%>"><fmt:message key="jsp.help"/></dspace:popup></span> + </div> <dspace:include page="/components/login-form.jsp" /> + </div> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/login/password.jsp b/dspace-jspui/src/main/webapp/login/password.jsp index 08f924079b79b326de2a1fef9c31dabe6301970e..1778245dc7d6fcca8fc12369e6605bec8fe209f8 100644 --- a/dspace-jspui/src/main/webapp/login/password.jsp +++ b/dspace-jspui/src/main/webapp/login/password.jsp @@ -19,19 +19,11 @@ <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> -<dspace:layout navbar="off" locbar="off" titlekey="jsp.login.password.title" nocache="true"> - - <table border="0" width="90%"> - <tr> - <td align="left"> - <%-- <h1>Log In to DSpace</h1> --%> - <h1><fmt:message key="jsp.login.password.heading"/></h1> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#login\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - - <dspace:include page="/components/login-form.jsp" /> +<dspace:layout navbar="default" locbar="off" titlekey="jsp.login.password.title" nocache="true"> + <div class="panel panel-primary"> + <div class="panel-heading"><fmt:message key="jsp.login.password.heading"/> + <span class="pull-right"><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#login\"%>"><fmt:message key="jsp.help"/></dspace:popup></span> + </div> + <dspace:include page="/components/login-form.jsp" /> + </div> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/mydspace/in-archive.jsp b/dspace-jspui/src/main/webapp/mydspace/in-archive.jsp index e98dec5b66dda97f53261147ee74e10e7d32185d..901068ef23bf4670b9c26e0f9c112c8a647aa8b7 100644 --- a/dspace-jspui/src/main/webapp/mydspace/in-archive.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/in-archive.jsp @@ -25,7 +25,8 @@ String handle = (String) request.getAttribute("handle"); %> -<dspace:layout locbar="link" +<dspace:layout style="submission" + locbar="link" parentlink="/mydspace" parenttitlekey="jsp.mydspace" titlekey="jsp.mydspace.in-archive.title"> diff --git a/dspace-jspui/src/main/webapp/mydspace/main.jsp b/dspace-jspui/src/main/webapp/mydspace/main.jsp index 40a7c15c2c9293f1a68b9985f9215de739ba4372..171c4a02acf5f975c361f979ee039ab16e8e7aeb 100644 --- a/dspace-jspui/src/main/webapp/mydspace/main.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/main.jsp @@ -71,34 +71,34 @@ boolean displayGroupMembership = (displayMembership == null ? false : displayMembership.booleanValue()); %> -<dspace:layout titlekey="jsp.mydspace" nocache="true"> - -<table width="100%" border="0"> - <tr> - <td align="left"> - <h1> +<dspace:layout style="submission" titlekey="jsp.mydspace" nocache="true"> + <div class="panel panel-primary"> + <div class="panel-heading"> <fmt:message key="jsp.mydspace"/>: <%= Utils.addEntities(user.getFullName()) %> - </h1> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#mydspace\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - + <span class="pull-right"><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#mydspace\"%>"><fmt:message key="jsp.help"/></dspace:popup></span> + </div> + + <div class="panel-body"> + <form action="<%= request.getContextPath() %>/mydspace" method="post"> + <input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>" /> + <input class="btn btn-success" type="submit" name="submit_new" value="<fmt:message key="jsp.mydspace.main.start.button"/>" /> + <input class="btn btn-info" type="submit" name="submit_own" value="<fmt:message key="jsp.mydspace.main.view.button"/>" /> + </form> + + <%-- Task list: Only display if the user has any tasks --%> <% if (owned.length > 0) { %> - <h2><fmt:message key="jsp.mydspace.main.heading2"/></h2> + <h3><fmt:message key="jsp.mydspace.main.heading2"/></h3> <p class="submitFormHelp"> <%-- Below are the current tasks that you have chosen to do. --%> <fmt:message key="jsp.mydspace.main.text1"/> </p> - <table class="miscTable" align="center" summary="Table listing owned tasks"> + <table class="table" align="center" summary="Table listing owned tasks"> <tr> <th id="t1" class="oddRowOddCol"><fmt:message key="jsp.mydspace.main.task"/></th> <th id="t2" class="oddRowOddCol"><fmt:message key="jsp.mydspace.main.item"/></th> @@ -141,8 +141,8 @@ <form action="<%= request.getContextPath() %>/mydspace" method="post"> <input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>" /> <input type="hidden" name="workflow_id" value="<%= owned[i].getID() %>" /> - <input type="submit" name="submit_perform" value="<fmt:message key="jsp.mydspace.main.perform.button"/>" /> - <input type="submit" name="submit_return" value="<fmt:message key="jsp.mydspace.main.return.button"/>" /> + <input class="btn btn-primary" type="submit" name="submit_perform" value="<fmt:message key="jsp.mydspace.main.perform.button"/>" /> + <input class="btn btn-default" type="submit" name="submit_return" value="<fmt:message key="jsp.mydspace.main.return.button"/>" /> </form> </td> </tr> @@ -158,19 +158,20 @@ if (pooled.length > 0) { %> - <h2><fmt:message key="jsp.mydspace.main.heading3"/></h2> + <h3><fmt:message key="jsp.mydspace.main.heading3"/></h3> <p class="submitFormHelp"> <%--Below are tasks in the task pool that have been assigned to you. --%> <fmt:message key="jsp.mydspace.main.text2"/> </p> - <table class="miscTable" align="center" summary="Table listing the tasks in the pool"> + <table class="table" align="center" summary="Table listing the tasks in the pool"> <tr> <th id="t6" class="oddRowOddCol"><fmt:message key="jsp.mydspace.main.task"/></th> <th id="t7" class="oddRowEvenCol"><fmt:message key="jsp.mydspace.main.item"/></th> <th id="t8" class="oddRowOddCol"><fmt:message key="jsp.mydspace.main.subto"/></th> <th id="t9" class="oddRowEvenCol"><fmt:message key="jsp.mydspace.main.subby"/></th> + <th class="oddRowOddCol"> </th> </tr> <% // even or odd row: Starts even since header row is odd (1). Toggled @@ -204,7 +205,7 @@ <form action="<%= request.getContextPath() %>/mydspace" method="post"> <input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>" /> <input type="hidden" name="workflow_id" value="<%= pooled[i].getID() %>" /> - <input type="submit" name="submit_claim" value="<fmt:message key="jsp.mydspace.main.take.button"/>" /> + <input class="btn btn-default" type="submit" name="submit_claim" value="<fmt:message key="jsp.mydspace.main.take.button"/>" /> </form> </td> </tr> @@ -215,27 +216,7 @@ </table> <% } -%> - - <form action="<%= request.getContextPath() %>/mydspace" method="post"> - <input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>" /> - <center> - <table border="0" width="70%"> - <tr> - <td align="left"> - <input type="submit" name="submit_new" value="<fmt:message key="jsp.mydspace.main.start.button"/>" /> - </td> - <td align="right"> - <input type="submit" name="submit_own" value="<fmt:message key="jsp.mydspace.main.view.button"/>" /> - </td> - </tr> - </table> - </center> - </form> - - <p align="center"><a href="<%= request.getContextPath() %>/subscribe"><fmt:message key="jsp.mydspace.main.link"/></a></p> -<% // Display workspace items (authoring or supervised), if any if (workspaceItems.length > 0 || supervisedItems.length > 0) { @@ -243,11 +224,11 @@ String row = "even"; %> - <h2><fmt:message key="jsp.mydspace.main.heading4"/></h2> + <h3><fmt:message key="jsp.mydspace.main.heading4"/></h3> <p><fmt:message key="jsp.mydspace.main.text4" /></p> - <table class="miscTable" align="center" summary="Table listing unfinished submissions"> + <table class="table" align="center" summary="Table listing unfinished submissions"> <tr> <th class="oddRowOddCol"> </th> <th id="t10" class="oddRowEvenCol"><fmt:message key="jsp.mydspace.main.subby"/></th> @@ -280,7 +261,7 @@ <td class="<%= row %>RowOddCol"> <form action="<%= request.getContextPath() %>/workspace" method="post"> <input type="hidden" name="workspace_id" value="<%= workspaceItems[i].getID() %>"/> - <input type="submit" name="submit_open" value="<fmt:message key="jsp.mydspace.general.open" />"/> + <input class="btn btn-default" type="submit" name="submit_open" value="<fmt:message key="jsp.mydspace.general.open" />"/> </form> </td> <td headers="t10" class="<%= row %>RowEvenCol"> @@ -292,7 +273,7 @@ <form action="<%= request.getContextPath() %>/mydspace" method="post"> <input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>"/> <input type="hidden" name="workspace_id" value="<%= workspaceItems[i].getID() %>"/> - <input type="submit" name="submit_delete" value="<fmt:message key="jsp.mydspace.general.remove" />"/> + <input class="btn btn-danger" type="submit" name="submit_delete" value="<fmt:message key="jsp.mydspace.general.remove" />"/> </form> </td> </tr> @@ -327,7 +308,7 @@ <td class="<%= row %>RowOddCol"> <form action="<%= request.getContextPath() %>/workspace" method="post"> <input type="hidden" name="workspace_id" value="<%= supervisedItems[i].getID() %>"/> - <input type="submit" name="submit_open" value="<fmt:message key="jsp.mydspace.general.open" />"/> + <input class="btn btn-default" type="submit" name="submit_open" value="<fmt:message key="jsp.mydspace.general.open" />"/> </form> </td> <td class="<%= row %>RowEvenCol"> @@ -339,7 +320,7 @@ <form action="<%= request.getContextPath() %>/mydspace" method="post"> <input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>"/> <input type="hidden" name="workspace_id" value="<%= supervisedItems[i].getID() %>"/> - <input type="submit" name="submit_delete" value="<fmt:message key="jsp.mydspace.general.remove" />"/> + <input class="btn btn-default" type="submit" name="submit_delete" value="<fmt:message key="jsp.mydspace.general.remove" />"/> </form> </td> </tr> @@ -359,9 +340,9 @@ // even or odd row: Starts even since header row is odd (1) String row = "even"; %> - <h2><fmt:message key="jsp.mydspace.main.heading5"/></h2> + <h3><fmt:message key="jsp.mydspace.main.heading5"/></h3> - <table class="miscTable" align="center" summary="Table listing submissions in workflow process"> + <table class="table" align="center" summary="Table listing submissions in workflow process"> <tr> <th id="t14" class="oddRowOddCol"><fmt:message key="jsp.mydspace.main.elem1"/></th> <th id="t15" class="oddRowEvenCol"><fmt:message key="jsp.mydspace.main.elem2"/></th> @@ -395,7 +376,7 @@ if(displayGroupMembership && groupMemberships.length>0) { %> - <h2><fmt:message key="jsp.mydspace.main.heading6"/></h2> + <h3><fmt:message key="jsp.mydspace.main.heading6"/></h3> <ul> <% for(int i=0; i<groupMemberships.length; i++) @@ -411,11 +392,13 @@ %> <%if(exportsAvailable!=null && exportsAvailable.size()>0){ %> - <h2><fmt:message key="jsp.mydspace.main.heading7"/></h2> + <h3><fmt:message key="jsp.mydspace.main.heading7"/></h3> <ol class="exportArchives"> <%for(String fileName:exportsAvailable){%> <li><a href="<%=request.getContextPath()+"/exportdownload/"+fileName%>" title="<fmt:message key="jsp.mydspace.main.export.archive.title"><fmt:param><%= fileName %></fmt:param></fmt:message>"><%=fileName%></a></li> <% } %> </ol> <%} %> + </div> +</div> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/mydspace/own-submissions.jsp b/dspace-jspui/src/main/webapp/mydspace/own-submissions.jsp index c4ec73b6a43268c1a13316d4e6de762542a42ea8..a6bf46c82150a49722af8a850cd03a57c73eb896 100644 --- a/dspace-jspui/src/main/webapp/mydspace/own-submissions.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/own-submissions.jsp @@ -31,7 +31,7 @@ Item[] items = (Item[]) request.getAttribute("items"); %> -<dspace:layout locbar="link" +<dspace:layout style="submission" locbar="link" parentlink="/mydspace" parenttitlekey="jsp.mydspace" titlekey="jsp.mydspace"> diff --git a/dspace-jspui/src/main/webapp/mydspace/perform-task.jsp b/dspace-jspui/src/main/webapp/mydspace/perform-task.jsp index bd097c45fb06515612bce113a1cc74a504d2cd87..e27c3a68208ea765aa2c299a67bfaeca71ddd390 100644 --- a/dspace-jspui/src/main/webapp/mydspace/perform-task.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/perform-task.jsp @@ -36,7 +36,7 @@ Item item = workflowItem.getItem(); %> -<dspace:layout locbar="link" +<dspace:layout style="submission" locbar="link" parentlink="/mydspace" parenttitlekey="jsp.mydspace" titlekey="jsp.mydspace.perform-task.title" @@ -79,103 +79,97 @@ <form action="<%= request.getContextPath() %>/mydspace" method="post"> <input type="hidden" name="workflow_id" value="<%= workflowItem.getID() %>"/> <input type="hidden" name="step" value="<%= MyDSpaceServlet.PERFORM_TASK_PAGE %>"/> - <table class="miscTable" width="80%"> <% - String row = "odd"; if (workflowItem.getState() == WorkflowManager.WFSTATE_STEP1 || workflowItem.getState() == WorkflowManager.WFSTATE_STEP2) { %> - <tr> - <td class="<%= row %>RowOddCol"> + <div class="input-group"> + <%-- <input type="submit" name="submit_approve" value="Approve"> --%> + <span class="input-group-addon"> + <input style="width:150px;" class="btn btn-success" type="submit" name="submit_approve" value="<fmt:message key="jsp.mydspace.general.approve"/>" /> + </span> + <span class="form-control"> <%-- If you have reviewed the item and it is suitable for inclusion in the collection, select "Approve". --%> <fmt:message key="jsp.mydspace.perform-task.instruct1"/> - </td> - <td class="<%= row %>RowEvenCol" valign="middle"> - <%-- <input type="submit" name="submit_approve" value="Approve"> --%> - <input type="submit" name="submit_approve" value="<fmt:message key="jsp.mydspace.general.approve"/>" /> - </td> - </tr> + </span> + </div> <% } else { // Must be an editor (step 3) %> - <tr> - <td class="<%= row %>RowOddCol"> + + <div class="input-group"> + <span class="input-group-addon"> + <%-- <input type="submit" name="submit_approve" value="Commit to Archive"> --%> + <input style="width:150px;" class="btn btn-success" type="submit" name="submit_approve" value="<fmt:message key="jsp.mydspace.perform-task.commit.button"/>" /> + </span> + <span class="form-control"> <%-- Once you've edited the item, use this option to commit the item to the archive. --%> <fmt:message key="jsp.mydspace.perform-task.instruct2"/> - </td> - <td class="<%= row %>RowEvenCol" valign="middle"> - <%-- <input type="submit" name="submit_approve" value="Commit to Archive"> --%> - <input type="submit" name="submit_approve" value="<fmt:message key="jsp.mydspace.perform-task.commit.button"/>" /> - </td> - </tr> + </span> + </div> <% } - row = "even"; if (workflowItem.getState() == WorkflowManager.WFSTATE_STEP1 || workflowItem.getState() == WorkflowManager.WFSTATE_STEP2) { %> - <tr> - <td class="<%= row %>RowOddCol"> + <div class="input-group"> + <span class="input-group-addon"> + <input style="width:150px;" class="btn btn-danger" type="submit" name="submit_reject" value="<fmt:message key="jsp.mydspace.general.reject"/>"/> + </span> + <span class="form-control"> <%-- If you have reviewed the item and found it is <strong>not</strong> suitable for inclusion in the collection, select "Reject". You will then be asked to enter a message indicating why the item is unsuitable, and whether the submitter should change something and re-submit. --%> <fmt:message key="jsp.mydspace.perform-task.instruct3"/> - </td> - <td class="<%= row %>RowEvenCol" valign="middle"> - <input type="submit" name="submit_reject" value="<fmt:message key="jsp.mydspace.general.reject"/>"/> - </td> - </tr> + </span> + </div> + <% - row = ( row.equals( "odd" ) ? "even" : "odd" ); } if (workflowItem.getState() == WorkflowManager.WFSTATE_STEP2 || workflowItem.getState() == WorkflowManager.WFSTATE_STEP3) { %> - <tr> - <td class="<%= row %>RowOddCol"> + <div class="input-group"> + <span class="input-group-addon"> + <input style="width:150px;" class="btn btn-primary" type="submit" name="submit_edit" value="<fmt:message key="jsp.mydspace.perform-task.edit.button"/>" /> + </span> + <span class="form-control"> <%-- Select this option to correct, amend or otherwise edit the item's metadata. --%> - <fmt:message key="jsp.mydspace.perform-task.instruct4"/> - </td> - <td class="<%= row %>RowEvenCol" valign="middle"> - <input type="submit" name="submit_edit" value="<fmt:message key="jsp.mydspace.perform-task.edit.button"/>" /> - </td> - </tr> + <fmt:message key="jsp.mydspace.perform-task.instruct4"/> + </span> + </div> + <% - row = (row.equals( "odd" ) ? "even" : "odd"); } %> - <tr> - <td class="<%= row %>RowOddCol"> + <div class="input-group"> + <span class="input-group-addon"> + <input style="width:150px;" class="btn btn-default" type="submit" name="submit_cancel" value="<fmt:message key="jsp.mydspace.perform-task.later.button"/>" /> + </span> + <span class="form-control"> <%-- If you wish to leave this task for now, and return to your "My DSpace", use this option. --%> <fmt:message key="jsp.mydspace.perform-task.instruct5"/> - </td> - <td class="<%= row %>RowEvenCol" valign="middle"> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.mydspace.perform-task.later.button"/>" /> - </td> - </tr> -<% - row = (row.equals( "odd" ) ? "even" : "odd"); -%> - <tr> - <td class="<%= row %>RowOddCol"> + </span> + </div> + <div class="input-group"> + <span class="input-group-addon"> + <input style="width:150px;" class="btn btn-default" type="submit" name="submit_pool" value="<fmt:message key="jsp.mydspace.perform-task.return.button"/>" /> + </span> + <span class="form-control"> <%-- To return the task to the pool so that another user can perform the task, use this option. --%> <fmt:message key="jsp.mydspace.perform-task.instruct6"/> - </td> - <td class="<%= row %>RowEvenCol" valign="middle"> - <input type="submit" name="submit_pool" value="<fmt:message key="jsp.mydspace.perform-task.return.button"/>" /> - </td> - </tr> - </table> + </span> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/mydspace/preview-task.jsp b/dspace-jspui/src/main/webapp/mydspace/preview-task.jsp index c437e57a592a19059fe4cf2f80124c9bbb15cb6b..e39b09d0bdfa640475c26339fa04cd9c0585c38d 100644 --- a/dspace-jspui/src/main/webapp/mydspace/preview-task.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/preview-task.jsp @@ -35,7 +35,8 @@ Item item = workflowItem.getItem(); %> -<dspace:layout locbar="link" +<dspace:layout style="submission" + locbar="link" parentlink="/mydspace" parenttitlekey="jsp.mydspace" titlekey="jsp.mydspace.preview-task.title" @@ -75,15 +76,7 @@ <form action="<%= request.getContextPath() %>/mydspace" method="post"> <input type="hidden" name="workflow_id" value="<%= workflowItem.getID() %>"/> <input type="hidden" name="step" value="<%= MyDSpaceServlet.PREVIEW_TASK_PAGE %>"/> - <table border="0" width="90%" cellpadding="10" align="center"> - <tr> - <td align="left"> - <input type="submit" name="submit_start" value="<fmt:message key="jsp.mydspace.preview-task.accept.button"/>" /> - </td> - <td align="right"> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.mydspace.general.cancel"/>" /> - </td> - </tr> - </table> + <input class="btn btn-default col-md-2" type="submit" name="submit_cancel" value="<fmt:message key="jsp.mydspace.general.cancel"/>" /> + <input class="btn btn-primary col-md-2 pull-right" type="submit" name="submit_start" value="<fmt:message key="jsp.mydspace.preview-task.accept.button"/>" /> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/mydspace/reject-reason.jsp b/dspace-jspui/src/main/webapp/mydspace/reject-reason.jsp index bc6546ef10c2c867d5b94a93453c5fb14204cb12..1d60677518431a99350714aa70436fa6e9607762 100644 --- a/dspace-jspui/src/main/webapp/mydspace/reject-reason.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/reject-reason.jsp @@ -31,7 +31,7 @@ (WorkflowItem) request.getAttribute("workflow.item"); %> -<dspace:layout locbar="link" +<dspace:layout style="submission" locbar="link" parentlink="/mydspace" parenttitlekey="jsp.mydspace" title="reject-reason.title" @@ -48,21 +48,14 @@ <form action="<%= request.getContextPath() %>/mydspace" method="post"> <input type="hidden" name="workflow_id" value="<%= workflowItem.getID() %>"/> <input type="hidden" name="step" value="<%= MyDSpaceServlet.REJECT_REASON_PAGE %>"/> - <center> - <textarea rows="6" cols="50" name="reason"></textarea> - </center> - - <table border="0" width="90%" cellpadding="10" align="center"> - <tr> - <td align="left"> - <%-- <input type="submit" name="submit_send" value="Reject Item" /> --%> - <input type="submit" name="submit_send" value="<fmt:message key="jsp.mydspace.reject-reason.reject.button"/>" /> - </td> - <td align="right"> - <%-- <input type="submit" name="submit_cancel" value="Cancel Rejection" /> --%> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.mydspace.reject-reason.cancel.button"/>" /> - </td> - </tr> - </table> + <textarea class="form-control" rows="6" cols="50" name="reason"></textarea> + <br/> + <div class="row container"> + <%-- <input type="submit" name="submit_cancel" value="Cancel Rejection" /> --%> + <input class="btn btn-default" type="submit" name="submit_cancel" value="<fmt:message key="jsp.mydspace.reject-reason.cancel.button"/>" /> + + <%-- <input type="submit" name="submit_send" value="Reject Item" /> --%> + <input class="btn btn-danger pull-right" type="submit" name="submit_send" value="<fmt:message key="jsp.mydspace.reject-reason.reject.button"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/mydspace/remove-item.jsp b/dspace-jspui/src/main/webapp/mydspace/remove-item.jsp index edaf3ecf1ea13826323ab0451cb005dcf1b971e2..1acfbba2ea1cf157a2d3338ec362692272613ca7 100644 --- a/dspace-jspui/src/main/webapp/mydspace/remove-item.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/remove-item.jsp @@ -33,8 +33,7 @@ parenttitlekey="jsp.mydspace" titlekey="jsp.mydspace.remove-item.title" nocache="true"> - -<h1><fmt:message key="jsp.mydspace.remove-item.title"/></h1> +<h2><fmt:message key="jsp.mydspace.remove-item.title"/></h2> <%-- <p>Are you sure you want to remove the following incomplete item?</p> --%> <p><fmt:message key="jsp.mydspace.remove-item.confirmation"/></p> @@ -45,17 +44,9 @@ <input type="hidden" name="workspace_id" value="<%= wi.getID() %>"/> <input type="hidden" name="step" value="<%= MyDSpaceServlet.REMOVE_ITEM_PAGE %>"/> - <table align="center" border="0" width="90%"> - <tr> - <td align="left"> - <%-- <input type="submit" name="submit_delete" value="Remove the Item" /> --%> - <input type="submit" name="submit_delete" value="<fmt:message key="jsp.mydspace.remove-item.remove.button"/>" /> - </td> - <td align="right"> - <%-- <input type="submit" name="submit_cancel" value="Cancel Removal" /> --%> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.mydspace.remove-item.cancel.button"/>" /> - </td> - </tr> - </table> + <div class="pull-right"> + <input class="btn btn-danger" type="submit" name="submit_delete" value="<fmt:message key="jsp.mydspace.remove-item.remove.button"/>" /> + <input class="btn btn-success" type="submit" name="submit_cancel" value="<fmt:message key="jsp.mydspace.remove-item.cancel.button"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/mydspace/subscriptions.jsp b/dspace-jspui/src/main/webapp/mydspace/subscriptions.jsp index 54c5a626934ff545e02c065183d8ab940759f9a5..be7f748b7fd52d30ebb4ba21a38e4a1f148ab595 100644 --- a/dspace-jspui/src/main/webapp/mydspace/subscriptions.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/subscriptions.jsp @@ -27,48 +27,60 @@ <%@ page import="org.dspace.content.Community" %> <%@ page import="org.dspace.content.Collection" %> +<%@ page import="org.dspace.app.util.CollectionDropDown" %> <% + Collection[] availableSubscriptions = + (Collection[]) request.getAttribute("availableSubscriptions"); Collection[] subscriptions = (Collection[]) request.getAttribute("subscriptions"); boolean updated = ((Boolean) request.getAttribute("updated")).booleanValue(); %> -<dspace:layout locbar="link" +<dspace:layout style="submission" locbar="link" parentlink="/mydspace" parenttitlekey="jsp.mydspace" titlekey="jsp.mydspace.subscriptions.title"> - <table width="100%" border="0"> - <tr> - <td align="left"> <%-- <h1>Your Subscriptions</h1> --%> - <h1><fmt:message key="jsp.mydspace.subscriptions.title"/></h1> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") +\"#subscribe\" %>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - +<h1><fmt:message key="jsp.mydspace.subscriptions.title"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") +\"#subscribe\" %>"><fmt:message key="jsp.help"/></dspace:popup> +</h1> <% if (updated) { %> <p><strong><fmt:message key="jsp.mydspace.subscriptions.info1"/></strong></p> + <p><fmt:message key="jsp.mydspace.subscriptions.info2"/></p> <% } %> - <p><fmt:message key="jsp.mydspace.subscriptions.info2"/></p> + <form class="form-group" action="<%= request.getContextPath() %>/subscribe" method="post"> + <div class="col-md-6"> + <select id="available-subscriptions" class="form-control" name="collection"> + <option value="-1"><fmt:message key="jsp.mydspace.subscriptions.select_collection" /></option> +<% + for (int i = 0; i < availableSubscriptions.length; i++) + { +%> + <option value="<%= availableSubscriptions[i].getID() %>"><%= CollectionDropDown.collectionPath(availableSubscriptions[i], 0) %></option> +<% + } +%> + </select> + </div> + <input class="btn btn-success" type="submit" name="submit_subscribe" value="<fmt:message key="jsp.collection-home.subscribe"/>" /> + <input class="btn btn-danger" type="submit" name="submit_clear" value="<fmt:message key="jsp.mydspace.subscriptions.remove.button"/>" /> + </form> + <% if (subscriptions.length > 0) { %> <p><fmt:message key="jsp.mydspace.subscriptions.info3"/></p> - <center> - <table class="miscTable" summary="Table displaying your subscriptions"> + <table class="table" summary="Table displaying your subscriptions"> <% String row = "odd"; @@ -82,12 +94,12 @@ --%> <td class="<%= row %>RowOddCol"> - <a href="<%= request.getContextPath() %>/handle/<%= subscriptions[i].getHandle() %>"><%= subscriptions[i].getMetadata("name") %></a> + <a href="<%= request.getContextPath() %>/handle/<%= subscriptions[i].getHandle() %>"><%= CollectionDropDown.collectionPath(subscriptions[i],0) %></a> </td> <td class="<%= row %>RowEvenCol"> <form method="post" action=""> <input type="hidden" name="collection" value="<%= subscriptions[i].getID() %>" /> - <input type="submit" name="submit_unsubscribe" value="<fmt:message key="jsp.mydspace.subscriptions.unsub.button"/>" /> + <input class="btn btn-warning" type="submit" name="submit_unsubscribe" value="<fmt:message key="jsp.mydspace.subscriptions.unsub.button"/>" /> </form> </td> </tr> @@ -96,15 +108,9 @@ } %> </table> - </center> <br/> - <center> - <form method="post" action=""> - <input type="submit" name="submit_clear" value="<fmt:message key="jsp.mydspace.subscriptions.remove.button"/>" /> - </form> - </center> <% } else diff --git a/dspace-jspui/src/main/webapp/mydspace/task-complete.jsp b/dspace-jspui/src/main/webapp/mydspace/task-complete.jsp index 5991365b0fe365d20ac8933e4896954f67a008a9..f369de58fc5172639b4a3cefa0dc054c0d18e968 100644 --- a/dspace-jspui/src/main/webapp/mydspace/task-complete.jsp +++ b/dspace-jspui/src/main/webapp/mydspace/task-complete.jsp @@ -18,7 +18,7 @@ <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> -<dspace:layout locbar="link" +<dspace:layout style="submission" locbar="link" parentlink="/mydspace" parenttitlekey="jsp.mydspace" titlekey="jsp.mydspace.task-complete.title"> diff --git a/dspace-jspui/src/main/webapp/register/edit-profile.jsp b/dspace-jspui/src/main/webapp/register/edit-profile.jsp index fcc41efb40834a7d7bd8c20227f0c7f890dbbeb0..52d2964e30d7d9730ffed79aaafe1cf02d0449f4 100644 --- a/dspace-jspui/src/main/webapp/register/edit-profile.jsp +++ b/dspace-jspui/src/main/webapp/register/edit-profile.jsp @@ -44,17 +44,19 @@ boolean ldap_eperson = (ldap_enabled && (eperson.getNetid() != null) && (eperson.getNetid().equals("") == false)); %> -<dspace:layout titlekey="jsp.register.edit-profile.title" nocache="true"> +<dspace:layout style="submission" titlekey="jsp.register.edit-profile.title" nocache="true"> <%-- <h1>Edit Your Profile</h1> --%> - <h1><fmt:message key="jsp.register.edit-profile.title"/></h1> + <h1><fmt:message key="jsp.register.edit-profile.title"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#editprofile\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <% if (missingFields) { %> <%-- <p><strong>Please fill out all of the required fields.</strong></p> --%> - <p><strong><fmt:message key="jsp.register.edit-profile.info1"/></strong></p> + <p class="alert alert-info"><fmt:message key="jsp.register.edit-profile.info1"/></p> <% } @@ -63,15 +65,14 @@ %> <%-- <p><strong>The passwords you enter below must match, and need to be at least 6 characters long.</strong></p> --%> - <p><strong><fmt:message key="jsp.register.edit-profile.info2"/></strong></p> + <p class="alert alert-warning"><fmt:message key="jsp.register.edit-profile.info2"/></p> <% } %> - <div><fmt:message key="jsp.register.edit-profile.info3"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#editprofile\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <div class="alert alert-info"><fmt:message key="jsp.register.edit-profile.info3"/></div> - <form action="<%= request.getContextPath() %>/profile" method="post"> + <form class="form-horizontal" action="<%= request.getContextPath() %>/profile" method="post"> <dspace:include page="/register/profile-form.jsp" /> @@ -83,30 +84,27 @@ %> <%-- <p><strong>Optionally</strong>, you can choose a new password and enter it into the box below, and confirm it by typing it again into the second box for verification. It should be at least six characters long.</p> --%> - <p><fmt:message key="jsp.register.edit-profile.info5"/></p> - - <table class="misc" align="center"> - <tr> - <td class="oddRowEvenCol"> - <table border="0" cellpadding="5"> - <tr> + <p class="alert"><fmt:message key="jsp.register.edit-profile.info5"/></p> + <div class="form-group"> <%-- <td align="right" class="standard"><label for="tpassword"><strong>New Password:</strong></label></td> --%> - <td align="right" class="standard"><label for="tpassword"><strong><fmt:message key="jsp.register.edit-profile.pswd.field"/></strong></label></td> - <td class="standard"><input type="password" name="password" id="tpassword" /></td> - </tr> - <tr> - <%-- <td align="right" class="standard"><strong>Again to Confirm:</strong></td> --%> - <td align="right" class="standard"><label for="tpassword_confirm"><strong><fmt:message key="jsp.register.edit-profile.confirm.field"/></strong></label></td> - <td class="standard"><input type="password" name="password_confirm" id="tpassword_confirm" /></td> - </tr> - </table> - </td> - </tr> - </table> + <label class="col-md-offset-3 col-md-2 control-label" for="tpassword"><fmt:message key="jsp.register.edit-profile.pswd.field"/></label> + <div class="col-md-3"> + <input class="form-control" type="password" name="password" id="tpassword" /> + </div> + </div> + <div class="form-group"> + <%-- <td align="right" class="standard"><strong>Again to Confirm:</strong></td> --%> + <label class="col-md-offset-3 col-md-2 control-label" for="tpassword_confirm"><fmt:message key="jsp.register.edit-profile.confirm.field"/></label> + <div class="col-md-3"> + <input class="form-control" type="password" name="password_confirm" id="tpassword_confirm" /></td> + </div> + </div> <% } %> + <div class="col-md-offset-5"> <%-- <p align="center"><input type="submit" name="submit" value="Update Profile"></p> --%> - <p align="center"><input type="submit" name="submit" value="<fmt:message key="jsp.register.edit-profile.update.button"/>" /></p> + <input class="btn btn-success col-md-4" type="submit" name="submit" value="<fmt:message key="jsp.register.edit-profile.update.button"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/register/forgot-password.jsp b/dspace-jspui/src/main/webapp/register/forgot-password.jsp index 03c2aa96e02dbd2571cc001a6364fff662bece63..8067a6014a4965b582efb23f9152c4defd90422a 100644 --- a/dspace-jspui/src/main/webapp/register/forgot-password.jsp +++ b/dspace-jspui/src/main/webapp/register/forgot-password.jsp @@ -41,39 +41,31 @@ %> <%-- <p><strong>The e-mail address you entered was not recognized. Please try again.</strong></p> --%> - <p><strong><fmt:message key="jsp.register.forgot-password.info1"/></strong></p> + <p class="alert alert-warning"><fmt:message key="jsp.register.forgot-password.info1"/></p> <% } %> <%-- <p>Please enter your e-mail address in the box below and click "I Forgot My Password". You'll be sent an e-mail which will allow you to set a new password.</p> --%> - <p><fmt:message key="jsp.register.forgot-password.info2"/></p> + <p class="alert alert-info"><fmt:message key="jsp.register.forgot-password.info2"/></p> - <form action="<%= request.getContextPath() %>/forgot" method="post"> + <form class="form-horizontal" action="<%= request.getContextPath() %>/forgot" method="post"> <input type="hidden" name="step" value="<%= RegisterServlet.ENTER_EMAIL_PAGE %>"/> - <center> - <table class="miscTable"> - <tr> - <td class="oddRowEvenCol"> - <table border="0" cellpadding="5"> - <tr> - <%-- <td class="standard"><strong>E-mail Address:</strong></td> --%> - <td class="standard"><strong><label for="temail"><fmt:message key="jsp.register.forgot-password.email.field"/></strong></label></td> - <td class="standard"><input type="text" name="email" id="temail" /></td> - </tr> - <tr> - <td align="center" colspan="2"> - <%-- <input type="submit" name="submit" value="I Forgot My Password"> --%> - <input type="submit" name="submit" value="<fmt:message key="jsp.register.forgot-password.forgot.button"/>" /> - </td> - </tr> - </table> - </td> - </tr> - </table> - </center> + <%-- <td class="standard"><strong>E-mail Address:</strong></td> --%> + <div class="form-group"> + <label class="col-md-2 control-label" for="temail"><fmt:message key="jsp.register.forgot-password.email.field"/></label> + <div class="col-md-6"> + <input class="form-control" type="text" name="email" id="temail" /> + </div> + </div> + <div class="row"> + <div class="col-md-6"> + <%-- <input type="submit" name="submit" value="I Forgot My Password"> --%> + <input class="btn btn-success pull-right" type="submit" name="submit" value="<fmt:message key="jsp.register.forgot-password.forgot.button"/>" /> + </div> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/register/new-password.jsp b/dspace-jspui/src/main/webapp/register/new-password.jsp index 5ac119a4e0a68c5af1f4d2ba54717579a3bfec78..227bfb6d08d7b70ca4b1973b54b76b34ef1e440a 100644 --- a/dspace-jspui/src/main/webapp/register/new-password.jsp +++ b/dspace-jspui/src/main/webapp/register/new-password.jsp @@ -39,13 +39,13 @@ boolean passwordProblem = (attr != null && attr.booleanValue()); %> -<dspace:layout titlekey="jsp.register.new-password.title" nocache="true"> +<dspace:layout style="submission" titlekey="jsp.register.new-password.title" nocache="true"> <%-- <h1>Enter a New Password</h1> --%> <h1><fmt:message key="jsp.register.new-password.title"/></h1> <!-- <p>Hello <%= Utils.addEntities(eperson.getFullName()) %>,</p> --> - <p><fmt:message key="jsp.register.new-password.hello"> + <p class="alert"><fmt:message key="jsp.register.new-password.hello"> <fmt:param><%= Utils.addEntities(eperson.getFullName()) %></fmt:param> </fmt:message></p> @@ -55,7 +55,7 @@ %> <%-- <p><strong>The passwords you enter below must match, and need to be at least 6 characters long.</strong></p> --%> - <p><strong><fmt:message key="jsp.register.new-password.info1"/></strong></p> + <p class="alert alert-warning"><strong><fmt:message key="jsp.register.new-password.info1"/></strong></p> <% } %> @@ -64,33 +64,31 @@ again into the second box. It should be at least six characters long.</p> --%> <p><fmt:message key="jsp.register.new-password.info2"/></p> - <form action="<%= request.getContextPath() %>/forgot" method="post"> - <table class="misc" align="center"> - <tr> - <td class="oddRowEvenCol"> - <table border="0" cellpadding="5"> - <tr> + <form class="form-horizontal" action="<%= request.getContextPath() %>/forgot" method="post"> + + + + + <div class="form-group"> <%-- <td align="right" class="standard"><strong>New Password:</strong></td> --%> - <td align="right" class="standard"><label for="tpassword"><strong><fmt:message key="jsp.register.new-password.pswd.field"/></strong></label></td> - <td class="standard"><input type="password" name="password" id="tpassword" /></td> - </tr> - <tr> - <%-- <td align="right" class="standard"><strong>Again to Confirm:</strong></td> --%> - <td align="right" class="standard"><label for="tpassword_confirm"><strong><fmt:message key="jsp.register.new-password.confirm.field"/></strong></label></td> - <td class="standard"><input type="password" name="password_confirm" id="tpassword_confirm" /></td> - </tr> - <tr> - <td align="center" colspan="2"> - <%-- <input type="submit" name="submit" value="Set New Password"> --%> - <input type="submit" name="submit" value="<fmt:message key="jsp.register.new-password.set.button"/>" /> - </td> - </tr> - </table> - </td> - </tr> - </table> - - <input type="hidden" name="step" value="<%= RegisterServlet.NEW_PASSWORD_PAGE %>"/> + <label class="col-md-offset-3 col-md-2 control-label" for="tpassword"><fmt:message key="jsp.register.new-password.pswd.field"/></label> + <div class="col-md-3"> + <input class="form-control" type="password" name="password" id="tpassword" /> + </div> + </div> + <div class="form-group"> + <%-- <td align="right" class="standard"><strong>Again to Confirm:</strong></td> --%> + <label class="col-md-offset-3 col-md-2 control-label" for="tpassword_confirm"><fmt:message key="jsp.register.new-password.confirm.field"/></label> + <div class="col-md-3"> + <input class="form-control" type="password" name="password_confirm" id="tpassword_confirm" /></td> + </div> + </div> + <div class="col-md-offset-5"> + <%-- <p align="center"><input type="submit" name="submit" value="Update Profile"></p> --%> + <input class="btn btn-success col-md-4" type="submit" name="submit" value="<fmt:message key="jsp.register.new-password.set.button"/>" /> + </div> + + <input type="hidden" name="step" value="<%= RegisterServlet.NEW_PASSWORD_PAGE %>"/> <input type="hidden" name="token" value="<%= token %>"/> </form> diff --git a/dspace-jspui/src/main/webapp/register/new-user.jsp b/dspace-jspui/src/main/webapp/register/new-user.jsp index 2206ee2e3bfda7ce2b2f632367a3a06264ecc483..080e430adb9d4f8a86ca153ec0fce8e42f7b6377 100644 --- a/dspace-jspui/src/main/webapp/register/new-user.jsp +++ b/dspace-jspui/src/main/webapp/register/new-user.jsp @@ -30,7 +30,7 @@ boolean retry = (request.getAttribute("retry") != null); %> -<dspace:layout titlekey="jsp.register.new-user.title"> +<dspace:layout style="submission" titlekey="jsp.register.new-user.title"> <%-- <h1>User Registration</h1> --%> <h1><fmt:message key="jsp.register.new-user.title"/></h1> @@ -38,40 +38,32 @@ if (retry) { %> <%-- <p><strong>The e-mail address you entered was invalid.</strong> Please try again.</strong></p> --%> - <p><fmt:message key="jsp.register.new-user.info1"/></p> + <p class="alert alert-warning"><fmt:message key="jsp.register.new-user.info1"/></p> <% } %> <%-- <p>If you've never logged on to DSpace before, please enter your e-mail address in the box below and click "Register".</p> --%> - <p><fmt:message key="jsp.register.new-user.info2"/></p> + <p class="alert"><fmt:message key="jsp.register.new-user.info2"/></p> - <form action="<%= request.getContextPath() %>/register" method="post"> + <form class="form-horizontal" action="<%= request.getContextPath() %>/register" method="post"> <input type="hidden" name="step" value="<%= RegisterServlet.ENTER_EMAIL_PAGE %>"/> - <table class="miscTable" align="center"> - <tr> - <td class="oddRowEvenCol"> - <table border="0" cellpadding="5"> - <tr> + <%-- <td class="standard"><strong>E-mail Address:</strong></td> --%> - <td class="standard"><label for="temail"><strong><fmt:message key="jsp.register.new-user.email.field"/></strong></label></td> - <td class="standard"><input type="text" name="email" id="temail" /></td> - </tr> - <tr> - <td align="center" colspan="2"> + <div class="form-group"> + <label class="col-md-offset-3 col-md-2 control-label" for="temail"><fmt:message key="jsp.register.new-user.email.field"/></label> + <div class="col-md-3"><input class="form-control" type="text" name="email" id="temail" /></div> + </div> + <div class="row col-md-offset-5"> <%-- <input type="submit" name="submit" value="Register"> --%> - <input type="submit" name="submit" value="<fmt:message key="jsp.register.new-user.register.button"/>" /> - </td> - </tr> - </table> - </td> - </tr> - </table> + <input class="btn btn-default col-md-4" type="submit" name="submit" value="<fmt:message key="jsp.register.new-user.register.button"/>" /> + </div> </form> <%-- <p>If you or your department are interested in registering with DSpace, please contact the DSpace site administrators.</p> --%> - <p><fmt:message key="jsp.register.new-user.info3"/></p> + <br/> + <div class="alert alert-info"><fmt:message key="jsp.register.new-user.info3"/></div> <dspace:include page="/components/contact-info.jsp" /> diff --git a/dspace-jspui/src/main/webapp/register/profile-form.jsp b/dspace-jspui/src/main/webapp/register/profile-form.jsp index aac7b17f627df72072eac6949cf4da7210fde575..235e0887e463f9b4f6d6b473dfebedb5ec5a08c7 100644 --- a/dspace-jspui/src/main/webapp/register/profile-form.jsp +++ b/dspace-jspui/src/main/webapp/register/profile-form.jsp @@ -56,27 +56,23 @@ if (language == null) language = ""; } %> - -<table border="0" align="center" cellpadding="5"> - <tr> - <%-- <td align="right" class="standard"><strong>First name*:</strong></td> --%> - <td align="right" class="standard"><strong><fmt:message key="jsp.register.profile-form.fname.field"/></strong></td> - <td class="standard"><input type="text" name="first_name" id="tfirst_name" size="40" value="<%= Utils.addEntities(firstName) %>"/></td> - </tr> - <tr> + <div class="form-group"> + <label class="col-md-offset-3 col-md-2 control-label" for="first_name"><fmt:message key="jsp.register.profile-form.fname.field"/></label> + <div class="col-md-3"><input class="form-control" type="text" name="first_name" id="tfirst_name" size="40" value="<%= Utils.addEntities(firstName) %>"/></div> + </div> + <div class="form-group"> <%-- <td align="right" class="standard"><label for="tlast_name"><strong>Last name*:</strong></label></td> --%> - <td align="right" class="standard"><label for="tlast_name"><strong><fmt:message key="jsp.register.profile-form.lname.field"/></strong></label></td> - <td class="standard"><input type="text" name="last_name" id="tlast_name" size="40" value="<%= Utils.addEntities(lastName) %>" /></td> - </tr> - <tr> - <%-- <td align="right" class="standard"><strong>Contact telephone:</strong></td> --%> - <td align="right" class="standard"><label for="tphone"><strong><fmt:message key="jsp.register.profile-form.phone.field"/></strong></label></td> - <td class="standard"><input type="text" name="phone" id="tphone" size="40" maxlength="32" value="<%= Utils.addEntities(phone) %>"/></td> - </tr> - <tr> - <td align="right" class="standard"><label for="tlanguage"><strong><fmt:message key="jsp.register.profile-form.language.field"/></strong></label></td> - <td class="standard"> - <select name="language" id="tlanguage"> + <label class="col-md-offset-3 col-md-2 control-label" for="tlast_name"><fmt:message key="jsp.register.profile-form.lname.field"/></label> + <div class="col-md-3"><input class="form-control" type="text" name="last_name" id="tlast_name" size="40" value="<%= Utils.addEntities(lastName) %>" /></div> + </div> + <div class="form-group"> + <label class="col-md-offset-3 col-md-2 control-label" for="tphone"><fmt:message key="jsp.register.profile-form.phone.field"/></label> + <div class="col-md-3"><input class="form-control" type="text" name="phone" id="tphone" size="40" maxlength="32" value="<%= Utils.addEntities(phone) %>"/></div> + </div> + <div class="form-group"> + <label class="col-md-offset-3 col-md-2 control-label" for="tlanguage"><strong><fmt:message key="jsp.register.profile-form.language.field"/></strong></label> + <div class="col-md-3"> + <select class="form-control" name="language" id="tlanguage"> <% for (int i = supportedLocales.length-1; i >= 0; i--) { @@ -98,6 +94,5 @@ } %> </select> - </td> - </tr> -</table> + </div> + </div> diff --git a/dspace-jspui/src/main/webapp/register/profile-updated.jsp b/dspace-jspui/src/main/webapp/register/profile-updated.jsp index 9ceada83792203210a1a62080a75737876f94351..b316ce628604ede86dee555877ef633f99c3799f 100644 --- a/dspace-jspui/src/main/webapp/register/profile-updated.jsp +++ b/dspace-jspui/src/main/webapp/register/profile-updated.jsp @@ -35,7 +35,7 @@ <%-- <p>Thank you, your profile information <%= (passwordUpdated ? "and password have" : "has") %> been updated.</p> --%> - <p> + <p class="alert alert-info"> <% if(passwordUpdated) { %> <fmt:message key="jsp.register.profile-updated.info1"/> diff --git a/dspace-jspui/src/main/webapp/register/registration-form.jsp b/dspace-jspui/src/main/webapp/register/registration-form.jsp index f14c533266137d9da76cf6874bd5f44b1f54d533..17e76be6d9fe58312e5c81df3ff5213e547572cb 100644 --- a/dspace-jspui/src/main/webapp/register/registration-form.jsp +++ b/dspace-jspui/src/main/webapp/register/registration-form.jsp @@ -49,7 +49,7 @@ boolean setPassword = (attr != null && attr.booleanValue()); %> -<dspace:layout titlekey="jsp.register.registration-form.title" nocache="true"> +<dspace:layout style="submission" titlekey="jsp.register.registration-form.title" nocache="true"> <%-- <h1>Registration Information</h1> --%> <h1><fmt:message key="jsp.register.registration-form.title"/></h1> @@ -59,7 +59,7 @@ { %> <%-- <p><strong>Please fill out all of the required fields.</strong></p> --%> - <p><strong><fmt:message key="jsp.register.registration-form.instruct1"/></strong></p> + <p class="alert alert-warning"><strong><fmt:message key="jsp.register.registration-form.instruct1"/></strong></p> <% } @@ -68,15 +68,15 @@ %> <%-- <p><strong>The passwords you enter below must match, and need to be at least 6 characters long.</strong></p> --%> - <p><strong><fmt:message key="jsp.register.registration-form.instruct2"/></strong></p> + <p class="alert alert-warning"><strong><fmt:message key="jsp.register.registration-form.instruct2"/></strong></p> <% } %> <%-- <p>Please enter the following information. The fields marked with a * are required.</p> --%> - <p><fmt:message key="jsp.register.registration-form.instruct3"/></p> - <form action="<%= request.getContextPath() %>/register" method="post"> + <p class="alert"><fmt:message key="jsp.register.registration-form.instruct3"/></p> + <form class="form-horizontal" action="<%= request.getContextPath() %>/register" method="post"> <% if (netid!=null) { %> <input type="hidden" name="netid" value="<%= netid %>" /> <% } %> <% if (email!=null) { %> <input type="hidden" name="email" value="<%= email %>" /> <% } %> <dspace:include page="/register/profile-form.jsp" /> @@ -87,26 +87,23 @@ %> <%-- <p>Please choose a password and enter it into the box below, and confirm it by typing it again into the second box. It should be at least six characters long.</p> --%> - <p><fmt:message key="jsp.register.registration-form.instruct4"/></p> - - <table class="misc" align="center"> - <tr> - <td class="oddRowEvenCol"> - <table border="0" cellpadding="5"> - <tr> - <%-- <td align="right" class="standard"><strong>Password:</strong></td> --%> - <td align="right" class="standard"><label for="tpassword"><strong><fmt:message key="jsp.register.registration-form.pswd.field"/></strong></label></td> - <td class="standard"><input type="password" name="password" id="tpassword" /></td> - </tr> - <tr> - <%-- <td align="right" class="standard"><strong>Again to Confirm:</strong></td> --%> - <td align="right" class="standard"><label for="tpassword_confirm"><strong><fmt:message key="jsp.register.registration-form.confirm.field"/></strong></label></td> - <td class="standard"><input type="password" name="password_confirm" id="tpassword_confirm" /></td> - </tr> - </table> - </td> - </tr> - </table> + <p class="alert"><fmt:message key="jsp.register.registration-form.instruct4"/></p> + + <div class="form-group"> + <%-- <td align="right" class="standard"><strong>New Password:</strong></td> --%> + <label class="col-md-offset-3 col-md-2 control-label" for="tpassword"><fmt:message key="jsp.register.registration-form.pswd.field"/></label> + <div class="col-md-3"> + <input class="form-control" type="password" name="password" id="tpassword" /> + </div> + </div> + <div class="form-group"> + <%-- <td align="right" class="standard"><strong>Again to Confirm:</strong></td> --%> + <label class="col-md-offset-3 col-md-2 control-label" for="tpassword_confirm"><fmt:message key="jsp.register.registration-form.confirm.field"/></label> + <div class="col-md-3"> + <input class="form-control" type="password" name="password_confirm" id="tpassword_confirm" /></td> + </div> + </div> + <% } %> @@ -115,6 +112,9 @@ <input type="hidden" name="token" value="<%= token %>"/> <%-- <p align="center"><input type="submit" name="submit" value="Complete Registration"></p> --%> - <p align="center"><input type="submit" name="submit" value="<fmt:message key="jsp.register.registration-form.complete.button"/>" /></p> + <div class="col-md-offset-5"> + <input class="btn btn-success col-md-4" type="submit" name="submit" value="<fmt:message key="jsp.register.registration-form.complete.button"/>" /> + </div> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/register/registration-sent.jsp b/dspace-jspui/src/main/webapp/register/registration-sent.jsp index b95999f36bd8abacb1de91b6955960072e19da2c..06249e3f30df714c76302cc0a6b67bc942e11b57 100644 --- a/dspace-jspui/src/main/webapp/register/registration-sent.jsp +++ b/dspace-jspui/src/main/webapp/register/registration-sent.jsp @@ -26,6 +26,6 @@ <%-- <p>You have been sent an e-mail containing a special URL, or "token". When you visit this URL, you will need to fill out some simple information. After that, you'll be ready to log into DSpace!</p> --%> - <p><fmt:message key="jsp.register.registration-sent.info"/></p> + <p class="alert alert-info"><fmt:message key="jsp.register.registration-sent.info"/></p> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/search/discovery.jsp b/dspace-jspui/src/main/webapp/search/discovery.jsp index 44a136fab005b8f031a1cbe141a2dd1df2fee872..0078cc1c07144a60721b7245dec02b5eb7365d2f 100644 --- a/dspace-jspui/src/main/webapp/search/discovery.jsp +++ b/dspace-jspui/src/main/webapp/search/discovery.jsp @@ -24,6 +24,7 @@ - appliedFilters - The list of applied filters (user input or facet) - - search.error - a flag to say that an error has occurred + - spellcheck - the suggested spell check query (if any) - qResults - the discovery results - items - the results. An array of Items, most relevant first - communities - results, Community[] @@ -84,7 +85,7 @@ String ascSelected = (SortOption.ASCENDING.equalsIgnoreCase(order) ? "selected=\"selected\"" : ""); String descSelected = (SortOption.DESCENDING.equalsIgnoreCase(order) ? "selected=\"selected\"" : ""); String httpFilters =""; - + String spellCheckQuery = (String) request.getAttribute("spellcheck"); List<DiscoverySearchFilter> availableFilters = (List<DiscoverySearchFilter>) request.getAttribute("availableFilters"); List<String[]> appliedFilters = (List<String[]>) request.getAttribute("appliedFilters"); List<String> appliedFilterQueries = (List<String>) request.getAttribute("appliedFilterQueries"); @@ -113,6 +114,10 @@ <script type="text/javascript"> var jQ = jQuery.noConflict(); jQ(document).ready(function() { + jQ( "#spellCheckQuery").click(function(){ + jQ("#query").val(jQ(this).attr('data-spell')); + jQ("#main-query-submit").click(); + }); jQ( "#filterquery" ) .autocomplete({ source: function( request, response ) { @@ -151,11 +156,11 @@ <%-- <h1>Search Results</h1> --%> -<h1><fmt:message key="jsp.search.title"/></h1> +<h2><fmt:message key="jsp.search.title"/></h2> -<div class="discovery-search-form"> +<div class="discovery-search-form panel panel-default"> <%-- Controls for a repeat search --%> - <div class="discovery-query"> + <div class="discovery-query panel-heading"> <form action="simple-search" method="get"> <label for="tlocation"> <fmt:message key="jsp.search.results.searchin"/> @@ -184,8 +189,11 @@ } %> </select><br/> <label for="query"><fmt:message key="jsp.search.results.searchfor"/></label> - <input type="text" size="50" name="query" value="<%= (query==null ? "" : StringEscapeUtils.escapeHtml(query)) %>"/> - <input type="submit" value="<fmt:message key="jsp.general.go"/>" /> + <input type="text" size="50" id="query" name="query" value="<%= (query==null ? "" : StringEscapeUtils.escapeHtml(query)) %>"/> + <input type="submit" id="main-query-submit" class="btn btn-primary" value="<fmt:message key="jsp.general.go"/>" /> +<% if (StringUtils.isNotBlank(spellCheckQuery)) {%> + <p class="lead"><fmt:message key="jsp.search.didyoumean"><fmt:param><a id="spellCheckQuery" data-spell="<%= StringEscapeUtils.escapeHtml(spellCheckQuery) %>" href="#"><%= spellCheckQuery %></a></fmt:param></fmt:message></p> +<% } %> <input type="hidden" value="<%= rpp %>" name="rpp" /> <input type="hidden" value="<%= sortedBy %>" name="sort_by" /> <input type="hidden" value="<%= order %>" name="order" /> @@ -228,7 +236,7 @@ %> </select> <input type="text" id="filter_value_<%=idx %>" name="filter_value_<%=idx %>" value="<%= StringEscapeUtils.escapeHtml(filter[2]) %>" size="45"/> - <input type="submit" id="submit_filter_remove_<%=idx %>" name="submit_filter_remove_<%=idx %>" value="X" /> + <input class="btn btn-default" type="submit" id="submit_filter_remove_<%=idx %>" name="submit_filter_remove_<%=idx %>" value="X" /> <br/> <% idx++; @@ -236,11 +244,13 @@ %> </div> <% } %> -<a href="<%= request.getContextPath()+"/simple-search" %>"><fmt:message key="jsp.search.general.new-search" /></a> +<a class="btn btn-default" href="<%= request.getContextPath()+"/simple-search" %>"><fmt:message key="jsp.search.general.new-search" /></a> </form> </div> <% if (availableFilters.size() > 0) { %> - <div class="discovery-search-filters"> + <div class="discovery-search-filters panel-body"> + <h5><fmt:message key="jsp.search.filter.heading" /></h5> + <p class="discovery-search-filters-hint"><fmt:message key="jsp.search.filter.hint" /></p> <form action="simple-search" method="get"> <input type="hidden" value="<%= StringEscapeUtils.escapeHtml(searchScope) %>" name="location" /> <input type="hidden" value="<%= StringEscapeUtils.escapeHtml(query) %>" name="query" /> @@ -257,8 +267,6 @@ idx++; } } %> - <span class="discovery-search-filters-heading"><fmt:message key="jsp.search.filter.heading" /></span> - <span class="discovery-search-filters-hint"><fmt:message key="jsp.search.filter.hint" /></span> <select id="filtername" name="filtername"> <% for (DiscoverySearchFilter searchFilter : availableFilters) @@ -281,12 +289,12 @@ <input type="hidden" value="<%= rpp %>" name="rpp" /> <input type="hidden" value="<%= sortedBy %>" name="sort_by" /> <input type="hidden" value="<%= order %>" name="order" /> - <input type="submit" value="<fmt:message key="jsp.search.filter.add"/>" /> + <input class="btn btn-default" type="submit" value="<fmt:message key="jsp.search.filter.add"/>" /> </form> </div> <% } %> <%-- Include a component for modifying sort by, order, results per page, and et-al limit --%> - <div class="discovery-pagination-controls"> + <div class="discovery-pagination-controls panel-footer"> <form action="simple-search" method="get"> <input type="hidden" value="<%= StringEscapeUtils.escapeHtml(searchScope) %>" name="location" /> <input type="hidden" value="<%= StringEscapeUtils.escapeHtml(query) %>" name="query" /> @@ -382,12 +390,12 @@ } %> </select> - <input type="submit" name="submit_search" value="<fmt:message key="search.update" />" /> + <input class="btn btn-default" type="submit" name="submit_search" value="<fmt:message key="search.update" />" /> <% if (admin_button) { - %><input type="submit" name="submit_export_metadata" value="<fmt:message key="jsp.general.metadataexport.button"/>" /><% + %><input type="submit" class="btn btn-default" name="submit_export_metadata" value="<fmt:message key="jsp.general.metadataexport.button"/>" /><% } %> </form> @@ -424,7 +432,7 @@ else if( qResults != null) // create the URLs accessing the previous and next search result pages String baseURL = request.getContextPath() - + searchScope + + (searchScope != "" ? "/handle/" + searchScope : "") + "/simple-search?query=" + URLEncoder.encode(query,"UTF-8") + httpFilters @@ -450,107 +458,122 @@ else if( qResults != null) %> <hr/> -<div class="discovery-result-pagination"> +<div class="discovery-result-pagination row container"> <% long lastHint = qResults.getStart()+qResults.getMaxResults() <= qResults.getTotalSearchResults()? qResults.getStart()+qResults.getMaxResults():qResults.getTotalSearchResults(); %> <%-- <p align="center">Results <//%=qResults.getStart()+1%>-<//%=qResults.getStart()+qResults.getHitHandles().size()%> of --%> - <h2 class="info"><fmt:message key="jsp.search.results.results"> + <div class="alert alert-info"><fmt:message key="jsp.search.results.results"> <fmt:param><%=qResults.getStart()+1%></fmt:param> <fmt:param><%=lastHint%></fmt:param> <fmt:param><%=qResults.getTotalSearchResults()%></fmt:param> <fmt:param><%=(float) qResults.getSearchTime() / 1000%></fmt:param> - </fmt:message></h2> - <ul class="links"> -<% -if (pageFirst != pageCurrent) -{ - %><li><a href="<%= prevURL %>"><fmt:message key="jsp.search.general.previous" /></a></li><% -} - -if (pageFirst != 1) -{ - %><li><a href="<%= firstURL %>">1</a></li><li>...</li><% -} - -for( long q = pageFirst; q <= pageLast; q++ ) -{ - String myLink = "<li><a href=\"" - + baseURL; - - - if( q == pageCurrent ) - { - myLink = "<li class=\"current-page-link\">" + q + "</li>"; - } - else - { - myLink = myLink - + (q-1) * qResults.getMaxResults() - + "\">" - + q - + "</a></li>"; - } -%> - -<%= myLink %> - -<% -} + </fmt:message></div> + <ul class="pagination pull-right"> + <% + if (pageFirst != pageCurrent) + { + %><li><a href="<%= prevURL %>"><fmt:message key="jsp.search.general.previous" /></a></li><% + } + else + { + %><li class="disabled"><span><fmt:message key="jsp.search.general.previous" /></span></li><% + } + + if (pageFirst != 1) + { + %><li><a href="<%= firstURL %>">1</a></li><li>...</li><% + } + + for( long q = pageFirst; q <= pageLast; q++ ) + { + String myLink = "<li><a href=\"" + + baseURL; + + + if( q == pageCurrent ) + { + myLink = "<li class=\"active\"><span>" + q + "</span></li>"; + } + else + { + myLink = myLink + + (q-1) * qResults.getMaxResults() + + "\">" + + q + + "</a></li>"; + } + %> + + <%= myLink %> -if (pageTotal > pageLast) -{ - %><li>...</li><li><a href="<%= lastURL %>"><%= pageTotal %></a></li><% -} -if (pageTotal > pageCurrent) -{ - %><li><a href="<%= nextURL %>"><fmt:message key="jsp.search.general.next" /></a></li><% -} -%> -</ul> + <% + } + + if (pageTotal > pageLast) + { + %><li class="disabled"><span>...</span></li><li><a href="<%= lastURL %>"><%= pageTotal %></a></li><% + } + if (pageTotal > pageCurrent) + { + %><li><a href="<%= nextURL %>"><fmt:message key="jsp.search.general.next" /></a></li><% + } + else + { + %><li class="disabled"><span><fmt:message key="jsp.search.general.next" /></span></li><% + } + %> + </ul> <!-- give a content to the div --> </div> <div class="discovery-result-results"> <% if (communities.length > 0 ) { %> - <%-- <h3>Community Hits:</h3> --%> - <h3><fmt:message key="jsp.search.results.comhits"/></h3> + <div class="panel panel-info"> + <div class="panel-heading"><fmt:message key="jsp.search.results.comhits"/></div> <dspace:communitylist communities="<%= communities %>" /> + </div> <% } %> <% if (collections.length > 0 ) { %> - <%-- <h3>Collection hits:</h3> --%> - <h3><fmt:message key="jsp.search.results.colhits"/></h3> + <div class="panel panel-info"> + <div class="panel-heading"><fmt:message key="jsp.search.results.colhits"/></div> <dspace:collectionlist collections="<%= collections %>" /> + </div> <% } %> <% if (items.length > 0) { %> - <%-- <h3>Item hits:</h3> --%> - <h3><fmt:message key="jsp.search.results.itemhits"/></h3> + <div class="panel panel-info"> + <div class="panel-heading"><fmt:message key="jsp.search.results.itemhits"/></div> <dspace:itemlist items="<%= items %>" authorLimit="<%= etAl %>" /> + </div> <% } %> </div> <%-- if the result page is enought long... --%> <% if ((communities.length + collections.length + items.length) > 10) {%> <%-- show again the navigation info/links --%> -<div class="discovery-result-pagination"> +<div class="discovery-result-pagination row container"> <%-- <p align="center">Results <//%=qResults.getStart()+1%>-<//%=qResults.getStart()+qResults.getHitHandles().size()%> of --%> - <p class="info"><fmt:message key="jsp.search.results.results"> + <div class="alert alert-info"><fmt:message key="jsp.search.results.results"> <fmt:param><%=qResults.getStart()+1%></fmt:param> <fmt:param><%=lastHint%></fmt:param> <fmt:param><%=qResults.getTotalSearchResults()%></fmt:param> <fmt:param><%=(float) qResults.getSearchTime() / 1000 %></fmt:param> - </fmt:message></p> - <ul class="links"> + </fmt:message></div> + <ul class="pagination pull-right"> <% if (pageFirst != pageCurrent) { %><li><a href="<%= prevURL %>"><fmt:message key="jsp.search.general.previous" /></a></li><% } +else +{ + %><li class="disabled"><span><fmt:message key="jsp.search.general.previous" /></span></li><% +} if (pageFirst != 1) { - %><li><a href="<%= firstURL %>">1</a></li><li>...</li><% + %><li><a href="<%= firstURL %>">1</a></li><li class="disabled"><span>...<span></li><% } for( long q = pageFirst; q <= pageLast; q++ ) @@ -561,7 +584,7 @@ for( long q = pageFirst; q <= pageLast; q++ ) if( q == pageCurrent ) { - myLink = "<li class=\"current-page-link\">" + q + "</li>"; + myLink = "<li class=\"active\"><span>" + q + "</span></li>"; } else { @@ -580,18 +603,21 @@ for( long q = pageFirst; q <= pageLast; q++ ) if (pageTotal > pageLast) { - %><li>...</li><li><a href="<%= lastURL %>"><%= pageTotal %></a></li><% + %><li class="disabled"><span>...</span></li><li><a href="<%= lastURL %>"><%= pageTotal %></a></li><% } if (pageTotal > pageCurrent) { %><li><a href="<%= nextURL %>"><fmt:message key="jsp.search.general.next" /></a></li><% } +else +{ + %><li class="disabled"><span><fmt:message key="jsp.search.general.next" /></span></li><% +} %> </ul> <!-- give a content to the div --> </div> <% } %> -</div> <% } %> <dspace:sidebar> <% @@ -645,49 +671,20 @@ if (pageTotal > pageCurrent) int limit = facetConf.getFacetLimit()+1; String fkey = "jsp.search.facet.refine."+f; - %><div id="facet_<%= f %>" class="facet"> - <span class="facetName"><fmt:message key="<%= fkey %>" /></span> - <ul><% + %><div id="facet_<%= f %>" class="panel panel-success"> + <div class="panel-heading"><fmt:message key="<%= fkey %>" /></div> + <ul class="list-group"><% int idx = 1; int currFp = UIUtil.getIntParameter(request, f+"_page"); if (currFp < 0) { currFp = 0; } - if (currFp > 0) - { - %><li class="facet-previous"><a href="<%= request.getContextPath() - + (searchScope!=""?"/handle/"+searchScope:"") - + "/simple-search?query=" - + URLEncoder.encode(query,"UTF-8") - + "&sort_by=" + sortedBy - + "&order=" + order - + "&rpp=" + rpp - + httpFilters - + "&etal=" + etAl - + "&"+f+"_page="+(currFp-1) %>"><fmt:message key="jsp.search.facet.refine.previous" /></a></li> - <% - } for (FacetResult fvalue : facet) { - if (idx == limit) - { - %><li class="facet-next"><a href="<%= request.getContextPath() - + (searchScope!=""?"/handle/"+searchScope:"") - + "/simple-search?query=" - + URLEncoder.encode(query,"UTF-8") - + "&sort_by=" + sortedBy - + "&order=" + order - + "&rpp=" + rpp - + httpFilters - + "&etal=" + etAl - + "&"+f+"_page="+(currFp+1) %>"><fmt:message key="jsp.search.facet.refine.next" /></a></li> - <% - idx++; - } - else if(!appliedFilterQueries.contains(f+"::"+fvalue.getFilterType()+"::"+fvalue.getAsFilterQuery())) + if (idx != limit && !appliedFilterQueries.contains(f+"::"+fvalue.getFilterType()+"::"+fvalue.getAsFilterQuery())) { - %><li><a href="<%= request.getContextPath() + %><li class="list-group-item"><span class="badge"><%= fvalue.getCount() %></span> <a href="<%= request.getContextPath() + (searchScope!=""?"/handle/"+searchScope:"") + "/simple-search?query=" + URLEncoder.encode(query,"UTF-8") @@ -700,7 +697,7 @@ if (pageTotal > pageCurrent) + "&filterquery="+URLEncoder.encode(fvalue.getAsFilterQuery(),"UTF-8") + "&filtertype="+URLEncoder.encode(fvalue.getFilterType(),"UTF-8") %>" title="<fmt:message key="jsp.search.facet.narrow"><fmt:param><%=fvalue.getDisplayedValue() %></fmt:param></fmt:message>"> - <%= StringUtils.abbreviate(fvalue.getDisplayedValue(),32) + " (" + fvalue.getCount()+")" %></a></li><% + <%= StringUtils.abbreviate(fvalue.getDisplayedValue(),36) %></a></li><% idx++; } if (idx > limit) @@ -708,6 +705,36 @@ if (pageTotal > pageCurrent) break; } } + if (currFp > 0 || idx == limit) + { + %><li class="list-group-item"><span style="visibility: hidden;">.</span> + <% if (currFp > 0) { %> + <a class="pull-left" href="<%= request.getContextPath() + + (searchScope!=""?"/handle/"+searchScope:"") + + "/simple-search?query=" + + URLEncoder.encode(query,"UTF-8") + + "&sort_by=" + sortedBy + + "&order=" + order + + "&rpp=" + rpp + + httpFilters + + "&etal=" + etAl + + "&"+f+"_page="+(currFp-1) %>"><fmt:message key="jsp.search.facet.refine.previous" /></a> + <% } %> + <% if (idx == limit) { %> + <a href="<%= request.getContextPath() + + (searchScope!=""?"/handle/"+searchScope:"") + + "/simple-search?query=" + + URLEncoder.encode(query,"UTF-8") + + "&sort_by=" + sortedBy + + "&order=" + order + + "&rpp=" + rpp + + httpFilters + + "&etal=" + etAl + + "&"+f+"_page="+(currFp+1) %>"><span class="pull-right"><fmt:message key="jsp.search.facet.refine.next" /></span></a> + <% + } + %></li><% + } %></ul></div><% } diff --git a/dspace-jspui/src/main/webapp/statistics/no-report.jsp b/dspace-jspui/src/main/webapp/statistics/no-report.jsp index 487fc1f7439a9a6a1d68b16bffd3b8781a0945c3..43917d3d245c86411adbe567fa9f3eb847cfc05a 100644 --- a/dspace-jspui/src/main/webapp/statistics/no-report.jsp +++ b/dspace-jspui/src/main/webapp/statistics/no-report.jsp @@ -18,7 +18,7 @@ <% String navbar = (String) request.getAttribute("navbar"); %> -<dspace:layout navbar="<%= navbar %>" titlekey="jsp.statistics.no-report.title"> +<dspace:layout style="submission" navbar="<%= navbar %>" titlekey="jsp.statistics.no-report.title"> <p><fmt:message key="jsp.statistics.no-report.info1"/></p> diff --git a/dspace-jspui/src/main/webapp/statistics/report.jsp b/dspace-jspui/src/main/webapp/statistics/report.jsp index 932789280d6987f9db9ebc1e1f733b833bf9a75e..ebf15839ba97a2dd876f63427accde14407af6ad 100644 --- a/dspace-jspui/src/main/webapp/statistics/report.jsp +++ b/dspace-jspui/src/main/webapp/statistics/report.jsp @@ -30,7 +30,7 @@ SimpleDateFormat sdfLink = new SimpleDateFormat("yyyy'-'M"); %> -<dspace:layout navbar="<%= navbar %>" titlekey="jsp.statistics.report.title"> +<dspace:layout style="submission" navbar="<%= navbar %>" titlekey="jsp.statistics.report.title"> <p> <% diff --git a/dspace-jspui/src/main/webapp/styles.css b/dspace-jspui/src/main/webapp/styles.css index bbde83fe571f740417ad783aff7c35ac5fcf025c..e15fc306974d6faa154280af88001afec05aa780 100644 --- a/dspace-jspui/src/main/webapp/styles.css +++ b/dspace-jspui/src/main/webapp/styles.css @@ -702,3 +702,146 @@ input.ds-authority-lock.is-locked { background-image: url(image/lock24.png); } input.ds-authority-lock.is-unlocked { background-image: url(image/unlock24.png); } + +.standard10 { + margin-left: 10px; + margin-right: 10px; + font-family: "verdana", "Arial", "Helvetica", sans-serif; + font-size: 10pt; + padding-left: 10px; +} + +/* for alert messages */ +.notice { + width: 80%; + padding: 10px; + margin: 10px, 0; + border: 1px solid #bfc221; + background-color: #fffff2; +} + +.notice.success +{ + border-color: #21c221; + background-color: #f2fff2; +} + +.notice.failure +{ + border-color: #c22121; + background-color: #fff2f2; +} + +.curate +{ + padding: 20px 10px 0px 10px; + font-family: "verdana", "Arial", "Helvetica", sans-serif; + color: black; + font-size: 10pt; +} +.curate.heading +{ + font-weight: bold; + font-size: 12pt; + text-align: right; +} +.curate.field +{ + font-weight: normal; +} +.curate.help +{ + padding-top: 0px; + font-size: 9pt; + font-weight: normal; +} +.curate.button +{ + padding: 10px 0px; + font-size: 10pt; + text-align: center; +} + +textarea#reason { + font-size: 10pt; +} +.access-setting { + margin-left: 5%; +} +th.accessOdd { + width: 20%; + font-family: "verdana", "Arial", "Helvetica", sans-serif; + font-size: 12pt; + font-style: normal; + font-weight: normal; + color: #000000; + vertical-align: middle; + text-align: right; + text-decoration: none; + background: #eeeeee; +} +th.accessEven { + width: 20%; + font-family: "verdana", "Arial", "Helvetica", sans-serif; + font-size: 12pt; + font-style: normal; + font-weight: normal; + color: #000000; + vertical-align: middle; + text-align: right; + text-decoration: none; + background: #dddddd; +} +td.accessOdd{ + font-family: "verdana", "Arial", "Helvetica", sans-serif; + font-size: 12pt; + font-style: normal; + font-weight: normal; + color: #000000; + vertical-align: middle; + text-decoration: none; + background: #ffffff; +} +td.accessEven{ + font-family: "verdana", "Arial", "Helvetica", sans-serif; + font-size: 12pt; + font-style: normal; + font-weight: normal; + color: #000000; + vertical-align: middle; + text-decoration: none; + background: #eeeeee; +} +th.accessHeadOdd { + font-family: "verdana", "Arial", "Helvetica", sans-serif; + font-size: 12pt; + font-style: normal; + font-weight: normal; + color: #000000; + vertical-align: middle; + text-align: center; + text-decoration: none; + background: #eeeeee; +} +th.accessHeadEven { + font-family: "verdana", "Arial", "Helvetica", sans-serif; + font-size: 12pt; + font-style: normal; + font-weight: normal; + color: #000000; + vertical-align: middle; + text-align: center; + text-decoration: none; + background: #dddddd; +} + +.accessButton{ + font-family: "verdana", "Arial", "Helvetica", sans-serif; + font-size: 12pt; + font-style: normal; + font-weight: normal; + color: #000000; + vertical-align: middle; + text-decoration: none; + background: #ffffff; +} \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/submit/cancel.jsp b/dspace-jspui/src/main/webapp/submit/cancel.jsp index 5d9902aea7d6d23648c7c057c3103e547b4d8ad6..352674904ab8d221fbce61a142bb0bba1b904503 100644 --- a/dspace-jspui/src/main/webapp/submit/cancel.jsp +++ b/dspace-jspui/src/main/webapp/submit/cancel.jsp @@ -45,7 +45,8 @@ SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" + locbar="off" navbar="off" titlekey="jsp.submit.cancel.title" nocache="true"> @@ -54,7 +55,6 @@ <jsp:include page="/submit/progressbar.jsp"/> - <h1><fmt:message key="jsp.submit.cancel.title"/></h1> <p><fmt:message key="jsp.submit.cancel.info"/></p> @@ -62,21 +62,11 @@ <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> <input type="hidden" name="cancellation" value="true" /> - - <table align="center" border="0" width="90%"> - <tr> - <td align="left"> - <input type="submit" name="submit_back" value="<fmt:message key="jsp.submit.cancel.continue.button"/>" /> - </td> - <td align="center"> - <input type="submit" name="submit_remove" value="<fmt:message key="jsp.submit.cancel.remove.button"/>" /> - </td> - <td align="right"> - <input type="submit" name="submit_keep" value="<fmt:message key="jsp.submit.cancel.save.button"/>" /> - </td> - </tr> - </table> - + <div class="pull-right"> + <input class="btn btn-default" type="submit" name="submit_back" value="<fmt:message key="jsp.submit.cancel.continue.button"/>" /> + <input class="btn btn-danger" type="submit" name="submit_remove" value="<fmt:message key="jsp.submit.cancel.remove.button"/>" /> + <input class="btn btn-success" type="submit" name="submit_keep" value="<fmt:message key="jsp.submit.cancel.save.button"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/cc-license.jsp b/dspace-jspui/src/main/webapp/submit/cc-license.jsp index ff190facbfa3d7986b6a703ec316d331e0817e94..a549caa13b8af12009ac645c55121d17ec811fca 100644 --- a/dspace-jspui/src/main/webapp/submit/cc-license.jsp +++ b/dspace-jspui/src/main/webapp/submit/cc-license.jsp @@ -25,5 +25,5 @@ <script type="text/javascript"> the_form = parent.document.getElementById("license_form"); the_form.cc_license_url.value = "<%= cc_license_url %>"; -the_form.submit(); +parent.document.getElementById("submit_grant").click(); </script> diff --git a/dspace-jspui/src/main/webapp/submit/change-file-description.jsp b/dspace-jspui/src/main/webapp/submit/change-file-description.jsp index 376c41d5b59247eb9cb30da927ccb0ef07d97381..4298ce4b42c311151eff0978e1333945eccc6dbe 100644 --- a/dspace-jspui/src/main/webapp/submit/change-file-description.jsp +++ b/dspace-jspui/src/main/webapp/submit/change-file-description.jsp @@ -33,7 +33,7 @@ SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.change-file-description.title" nocache="true"> @@ -43,14 +43,14 @@ <jsp:include page="/submit/progressbar.jsp"/> <%-- <h1>Submit: Change File Description</h1> --%> - <h1><fmt:message key="jsp.submit.change-file-description.heading"/></h1> + <h1><fmt:message key="jsp.submit.change-file-description.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#filedescription\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> - <%-- <p>Here are the details of the file. - <dspace:popup page="/help/index.html#filedescription">(More Help...)</dspace:popup></p> --%> - <div><fmt:message key="jsp.submit.change-file-description.info1"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#filedescription\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <%-- <p>Here are the details of the file. </p> --%> + <div><fmt:message key="jsp.submit.change-file-description.info1"/></div> - <table class="miscTable" align="center" summary="Change file descripton details"> + <table class="table" align="center" summary="Change file descripton details"> <tr> <%-- <th class="oddRowOddCol">File</th> <th class="oddRowEvenCol">Size</th> @@ -66,7 +66,7 @@ </tr> </table> - <p><fmt:message key="jsp.submit.change-file-description.info2"/></p> + <p class="alert alert-info"><fmt:message key="jsp.submit.change-file-description.info2"/></p> <% String currentDesc = subInfo.getBitstream().getDescription(); if (currentDesc == null) @@ -74,19 +74,15 @@ currentDesc=""; } %> - <center> - <table> - <tr> - <td class="submitFormLabel"><label for="tdescription"><fmt:message key="jsp.submit.change-file-description.filedescr"/></label></td> - <td><input type="text" name="description" id="tdescription" size="50" value="<%= currentDesc %>" /></td> - </tr> - </table> - </center> + <div class="row"> + <label for="tdescription" class="col-md-2"><fmt:message key="jsp.submit.change-file-description.filedescr"/></label> + <span class="col-md-10"><input class="form-control" type="text" name="description" id="tdescription" size="50" value="<%= currentDesc %>" /></span> + </div><br/> <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> - <center><p><input type="submit" name="submit" value="<fmt:message key="jsp.submit.general.submit"/>" /></p></center> + <input class="btn btn-primary col-md-2 col-md-offset-5" type="submit" name="submit" value="<fmt:message key="jsp.submit.general.submit"/>" /> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/choose-file.jsp b/dspace-jspui/src/main/webapp/submit/choose-file.jsp index 0f4759f8ea40c52791b0ec823fda2de39b1efc60..cc701b13e01ba30fdd31b7f5293729ca56db861b 100644 --- a/dspace-jspui/src/main/webapp/submit/choose-file.jsp +++ b/dspace-jspui/src/main/webapp/submit/choose-file.jsp @@ -9,16 +9,22 @@ --%> <%@ page contentType="text/html;charset=UTF-8" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> + <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="java.util.List" %> <%@ page import="org.dspace.core.ConfigurationManager" %> <%@ page import="org.dspace.core.Context" %> <%@ page import="org.dspace.app.webui.servlet.SubmissionController" %> +<%@ page import="org.dspace.authorize.ResourcePolicy" %> <%@ page import="org.dspace.submit.AbstractProcessingStep" %> <%@ page import="org.dspace.submit.step.UploadStep" %> <%@ page import="org.dspace.app.util.DCInputSet" %> @@ -35,34 +41,309 @@ //get submission information object SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); - + + boolean withEmbargo = ((Boolean)request.getAttribute("with_embargo")).booleanValue(); + // Determine whether a file is REQUIRED to be uploaded (default to true) boolean fileRequired = ConfigurationManager.getBooleanProperty("webui.submit.upload.required", true); + boolean ajaxProgress = ConfigurationManager.getBooleanProperty("webui.submit.upload.ajax", true); + + Boolean sherpa = (Boolean) request.getAttribute("sherpa"); + boolean bSherpa = sherpa != null?sherpa:false; + + if (ajaxProgress || bSherpa) + { %> +<c:set var="dspace.layout.head.last" scope="request"> +<% + if (bSherpa) { %> + + <link rel="stylesheet" href="<%=request.getContextPath()%>/sherpa/css/sherpa.css" type="text/css" /> + <script type="text/javascript"> + jQuery(document).ready(function(html){ + jQuery.ajax({ + url: '<%= request.getContextPath() + "/tools/sherpaPolicy" %>', + data: {item_id: <%= subInfo.getSubmissionItem().getItem().getID() %>}}) + .done(function(html) { + jQuery('#sherpaContent').html(html); + }); + }); + </script> + <% } + if (ajaxProgress) { %> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/jquery.fileupload-ui.css"> + <!-- CSS adjustments for browsers with JavaScript disabled --> + <noscript><link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/jquery.fileupload-ui-noscript.css"></noscript> + <script type="text/javascript"> + var bootstrapButton = $.fn.button.noConflict(); // return $.fn.button to previously assigned value + $.fn.bootstrapBtn = bootstrapButton; // give $().bootstrapBtn the Bootstrap functionality + + function initProgressBar($){ + var progressbarArea = $("#progressBarArea"); + progressbarArea.show(); + } + + function updateProgressBar($, data){ + $('#uploadForm').find('input').attr('disabled','disabled'); + $('#spanFile').attr('disabled','disabled'); + $('#spanFileCancel').attr('disabled','disabled'); + var percent = parseInt(data.loaded / data.total * 100, 10); + var progressbarArea = $("#progressBarArea"); + var progressbar = $("#progressBar"); + progressbar.progressbar({ value: data.loaded, max: data.total}); + progressbarArea.find('p.progressBarInitMsg').hide(); + progressbarArea.find('p.progressBarProgressMsg').show(); + progressbarArea.find('p.progressBarCompleteMsg').hide(); + progressbarArea.find('span.bytesRead').html(data.loaded); + progressbarArea.find('span.bytesTotal').html(data.total); + progressbarArea.find('span.percent').html(percent); + } + + function completeProgressBar($, total){ + var progressbarArea = $("#progressBarArea"); + var progressbar = $("#progressBar"); + progressbar.progressbar({ value: total, max: total}); + progressbarArea.find('p.progressBarInitMsg').hide(); + progressbarArea.find('p.progressBarProgressMsg').hide(); + progressbarArea.find('p.progressBarCompleteMsg').show(); + progressbarArea.find('span.bytesTotal').html(total); + } + + function monitorProgressJSON($){ + $.ajax({ + cache: false, + url: '<%= request.getContextPath() %>/json/uploadProgress'}) + .done(function(progress) { + var data = {loaded: progress.readBytes, total: progress.totalBytes}; + updateProgressBar($, data); + setTimeout(function() { + monitorProgressJSON($); + }, 250); + }); + } + + function decorateFileInputChangeEvent($) { + if ($('#selectedFile').length > 0) { + $('#selectedFile').html($('#tfile').val().replace(/.*(\/|\\)/, '')).append(' '); + } + else { + $('<span id="selectedFile"> '+$('#tfile').val().replace(/.*(\/|\\)/, '')+'</span>').insertAfter($('#spanFile')).append(' '); + var span = $('<span id="spanFileCancel" class="btn btn-danger"><span class="glyphicon glyphicon-ban-circle"></span></span>'); + span.appendTo($('#selectedFile')); + span.click(function(e){ + var parent = $('#spanFile').parent(); + $('#spanFile').remove(); + $('#selectedFile').remove(); + $('<input type="file" name="file" id="tfile">').appendTo(parent); + $('#tfile').wrap('<span id="spanFile" class="fileinput-button btn btn-success col-md-2"></span>'); + $('#spanFile').prepend(' <fmt:message key="jsp.submit.choose-file.upload-ajax.button.select-file"/>'); + $('#spanFile').prepend('<span class="glyphicon glyphicon-folder-open"></span>'); + $('#tfile').on('change', function(){ + decorateFileInputChangeEvent($); + }); + }); + } + } + + function setupAjaxUpload($, data){ + var progressbarArea = $("#progressBarArea"); + var progressbar = $("#progressBar"); + progressbar.progressbar({ value: false}); + progressbarArea.find('p.progressBarInitMsg').show(); + progressbarArea.find('p.progressBarProgressMsg').hide(); + progressbarArea.find('p.progressBarCompleteMsg').hide(); + progressbarArea.hide(); + + $('#tfile').wrap('<span id="spanFile" class="fileinput-button btn btn-success col-md-2"></span>'); + $('#spanFile').prepend(' <fmt:message key="jsp.submit.choose-file.upload-ajax.button.select-file"/>'); + $('#spanFile').prepend('<span class="glyphicon glyphicon-folder-open"></span>'); + $('#tfile').on('change', function(){ + decorateFileInputChangeEvent($); + }); + // the skip button should not send any files + $('input[name="<%=UploadStep.SUBMIT_SKIP_BUTTON%>"]').on('click', function(){ + $('#tfile').val(''); + }); + $('#uploadForm').append('<input type="hidden" id="ajaxUpload" name="ajaxUpload" value="true" />'); + // track the upload progress for all the submit buttons other than the skip + $('input[type="submit"]').not(":disabled") + .on('click', function(e){ + if ($('#tfile').val() != null && $('#tfile').val() != '') { + $('#uploadForm').attr('target','uploadFormIFrame'); + initProgressBar($); + setTimeout(function() { + monitorProgressJSON($); + }, 100); + } + else + { + $('#ajaxUpload').val(false); + } + $('#uploadFormIFrame').on('load',function(){ + var resultFile = null; + try { + var jsonResult = $.parseJSON($('#uploadFormIFrame').contents().find('body').text()); + if (jsonResult.fileSizeLimitExceeded) { + $('#actualSize').html(jsonResult.fileSizeLimitExceeded.actualSize); + $('#limitSize').html(jsonResult.fileSizeLimitExceeded.permittedSize); + $('#fileSizeLimitExceeded').dialog("open"); + return true; + } + resultFile = jsonResult.files[0]; + } catch (err) { + // a file has been upload, the answer is html isntead of json because + // come from a different step. Just ignore the target step and reload + // the upload list screen. We need to let the user known that the file + // has been uploaded + resultFile = new Object(); + resultFile.status = null; + } + + if (resultFile.status == null || resultFile.status == <%= UploadStep.STATUS_COMPLETE %> || + resultFile.status == <%= UploadStep.STATUS_UNKNOWN_FORMAT %>) + { + completeProgressBar($, resultFile.size); + if (resultFile.status == null || + resultFile.status == <%= UploadStep.STATUS_COMPLETE %>) + { + $('#uploadFormPostAjax').removeAttr('enctype') + .append('<input type="hidden" name="<%= UploadStep.SUBMIT_UPLOAD_BUTTON %>" value="1">'); + } + else + { + $('#uploadFormPostAjax') + .append('<input type="hidden" name="submit_format_'+resultFile.bitstreamID+'" value="1">') + .append('<input type="hidden" name="bitstream_id" value="'+resultFile.bitstreamID+'">'); + } + + $('#uploadFormPostAjax').submit(); + } + else { + if (resultFile.status == <%= UploadStep.STATUS_NO_FILES_ERROR %>) { + $('#fileRequired').dialog("open"); + } + else if (resultFile.status == <%= UploadStep.STATUS_VIRUS_CHECKER_UNAVAILABLE %>) { + completeProgressBar($, resultFile.size); + $('#virusCheckNA').dialog("open"); + } + else if (resultFile.status == <%= UploadStep.STATUS_CONTAINS_VIRUS %>) { + completeProgressBar($, resultFile.size); + $('#virusFound').dialog("open"); + } + else { + $('#uploadError').dialog("open"); + } + } + }); + }); + } + + + jQuery(document).ready(function($){ + setupAjaxUpload($); -<dspace:layout locbar="off" + $('#uploadError').dialog({modal: true, autoOpen: false, width: 600, buttons: { + '<fmt:message key="jsp.submit.choose-file.upload-ajax.dialog.close"/>': function() { + $(this).dialog("close"); + $('#uploadFormPostAjax') + .append('<input type="hidden" name="<%= UploadStep.SUBMIT_MORE_BUTTON %>" value="1">'); + $('#uploadFormPostAjax').submit(); + } + }}); + + $('#fileRequired').dialog({modal: true, autoOpen: false, width: 600, buttons: { + '<fmt:message key="jsp.submit.choose-file.upload-ajax.dialog.close"/>': function() { + $(this).dialog("close"); + $('#uploadFormPostAjax') + .append('<input type="hidden" name="<%= UploadStep.SUBMIT_MORE_BUTTON %>" value="1">'); + $('#uploadFormPostAjax').submit(); + } + }}); + + $('#fileSizeLimitExceeded').dialog({modal: true, autoOpen: false, width: 600, buttons: { + '<fmt:message key="jsp.submit.choose-file.upload-ajax.dialog.close"/>': function() { + $(this).dialog("close"); + $('#uploadFormPostAjax') + .append('<input type="hidden" name="<%= UploadStep.SUBMIT_MORE_BUTTON %>" value="1">'); + $('#uploadFormPostAjax').submit(); + } + }}); + + $('#virusFound').dialog({modal: true, autoOpen: false, width: 600, buttons: { + '<fmt:message key="jsp.submit.choose-file.upload-ajax.dialog.close"/>': function() { + $('#uploadFormPostAjax') + .append('<input type="hidden" name="<%= UploadStep.SUBMIT_MORE_BUTTON %>" value="1">'); + $('#uploadFormPostAjax').submit(); + $(this).dialog("close"); + } + }}); + + $('#virusCheckNA').dialog({modal: true, autoOpen:false, width: 600, buttons: { + '<fmt:message key="jsp.submit.choose-file.upload-ajax.dialog.close"/>': function() { + $('#uploadFormPostAjax') + .append('<input type="hidden" name="<%= UploadStep.SUBMIT_MORE_BUTTON %>" value="1">'); + $('#uploadFormPostAjax').submit(); + $(this).dialog("close"); + } + }}); + }); + </script> + <% } %> +</c:set> +<% } %> + +<dspace:layout style="submission" + locbar="off" navbar="off" titlekey="jsp.submit.choose-file.title" nocache="true"> +<% if (ajaxProgress) { %> + <div style="display:none;" id="uploadError" title="<fmt:message key="jsp.submit.upload-error.title" />"> + <p><fmt:message key="jsp.submit.upload-error.info" /></p> + </div> + <div style="display:none;" id="fileRequired" title="<fmt:message key="jsp.submit.choose-file.upload-ajax.fileRequired.title" />"> + <p><fmt:message key="jsp.submit.choose-file.upload-ajax.fileRequired.info" /></p> + </div> + <div style="display:none;" id="fileSizeLimitExceeded" title="<fmt:message key="jsp.error.exceeded-size.title" />"> + <p><fmt:message key="jsp.error.exceeded-size.text1"> + <fmt:param><span id="actualSize"> </span></fmt:param> + <fmt:param><span id="limitSize"> </span></fmt:param> + </fmt:message></p> + </div> + <div style="display:none;" id="virusFound" title="<fmt:message key="jsp.submit.upload-error.title" />"> + <p><fmt:message key="jsp.submit.virus-error.info" /></p> + </div> + <div style="display:none;" id="virusCheckNA" title="<fmt:message key="jsp.submit.upload-error.title" />"> + <p><fmt:message key="jsp.submit.virus-checker-error.info" /></p> + </div> + <form style="display:none;" id="uploadFormPostAjax" method="post" action="<%= request.getContextPath() %>/submit" + enctype="multipart/form-data" onkeydown="return disableEnterKey(event);"> + <%= SubmissionController.getSubmissionParameters(context, request) %> + </form> + <iframe id="uploadFormIFrame" name="uploadFormIFrame" style="display: none"> </iframe> +<% } %> + <form id="uploadForm" <%= bSherpa?"class=\"sherpa col-md-8\"":"" %> method="post" + action="<%= request.getContextPath() %>/submit" enctype="multipart/form-data" + onkeydown="return disableEnterKey(event);"> - <form method="post" action="<%= request.getContextPath() %>/submit" enctype="multipart/form-data" onkeydown="return disableEnterKey(event);"> - <jsp:include page="/submit/progressbar.jsp"/> + <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> <%-- <h1>Submit: Upload a File</h1> --%> - <h1><fmt:message key="jsp.submit.choose-file.heading"/></h1> + <h1><fmt:message key="jsp.submit.choose-file.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#upload\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p>Please enter the name of <%= (si.submission.hasMultipleFiles() ? "one of the files" : "the file" ) %> on your local hard drive corresponding to your item. If you click "Browse...", a new window will appear in which you can locate and select the file on your - local hard drive. <object><dspace:popup page="/help/index.html#upload">(More Help...)</dspace:popup></object></p> --%> + local hard drive.</p> --%> - <p><fmt:message key="jsp.submit.choose-file.info1"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#upload\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></p> + <p><fmt:message key="jsp.submit.choose-file.info1"/></p> <%-- FIXME: Collection-specific stuff should go here? --%> <%-- <p class="submitFormHelp">Please also note that the DSpace system is @@ -74,79 +355,110 @@ <div class="submitFormHelp"><fmt:message key="jsp.submit.choose-file.info6"/> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.formats\")%>"><fmt:message key="jsp.submit.choose-file.info7"/></dspace:popup> </div> - - <table border="0" align="center"> - <tr> - <td class="submitFormLabel"> + <br/> + <div class="row container"> + <div class="row"> <%-- Document File: --%> - <label for="tfile"><fmt:message key="jsp.submit.choose-file.document"/></label> - </td> - <td> + <label class="col-md-<%= bSherpa?"3":"2" %>" for="tfile"><fmt:message key="jsp.submit.choose-file.document"/></label> <input type="file" size="40" name="file" id="tfile" /> - </td> - </tr> + </div><br/> +<% if (ajaxProgress) +{ +%> + <div id="progressBarArea" class="row"> + <div id="progressBar"></div> + <p class="progressBarInitMsg"> + <fmt:message key="jsp.submit.choose-file.upload-ajax.uploadInit"/> + </p> + <p class="progressBarProgressMsg" style="display: none;"> + <fmt:message key="jsp.submit.choose-file.upload-ajax.uploadInProgress"> + <fmt:param><span class="percent"> </span></fmt:param> + <fmt:param><span class="bytesRead"> </span></fmt:param> + <fmt:param><span class="bytesTotal"> </span></fmt:param> + </fmt:message></p> + <p class="progressBarCompleteMsg" style="display: none;"> + <fmt:message key="jsp.submit.choose-file.upload-ajax.uploadCompleted"> + <fmt:param><span class="bytesTotal"> </span></fmt:param> + </fmt:message></p> + </div><br/> +<% } %> + <% if (subInfo.getSubmissionItem().hasMultipleFiles()) { %> - <tr> - <td colspan="2"> </td> - </tr> - <tr> - <td class="submitFormHelp" colspan="2"> <%-- Please give a brief description of the contents of this file, for example "Main article", or "Experiment data readings." --%> - <fmt:message key="jsp.submit.choose-file.info9"/> - </td> - </tr> - <tr> + <div class="help-block"><fmt:message key="jsp.submit.choose-file.info9"/></div> <%-- <td class="submitFormLabel">File Description:</td> --%> - <td class="submitFormLabel"><label for="tdescription"><fmt:message key="jsp.submit.choose-file.filedescr"/></label></td> - <td><input type="text" name="description" id="tdescription" size="40"/></td> - </tr> + <div class="row"> + <label for="tdescription" class="col-md-<%= bSherpa?"3":"2" %>"><fmt:message key="jsp.submit.choose-file.filedescr"/></label> + <span class="col-md-<%= bSherpa?"9":"10" %> row"><input class="form-control" type="text" name="description" id="tdescription" size="40"/></span> + </div> <% } %> - </table> - + +<% + if (withEmbargo) + { +%> + <br/> + <dspace:access-setting subInfo="<%= subInfo %>" dso="<%= subInfo.getSubmissionItem().getItem() %>" hidden="true" /> + <br/> +<% + } +%></div> + <br/> <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> - - <p> </p> - - <center> - <table border="0" width="80%"> - <tr> - <td width="100%"> </td> + <% + int col = 0; + if(!SubmissionController.isFirstStep(request, subInfo)) + { + col++; + } + if (!fileRequired || subInfo.getSubmissionItem().getItem().hasUploadedFiles()) + { + col++; + } + %> + <div class="pull-right btn-group col-md-<%= (bSherpa?2:1) * col*2 + 4 %>"> <% //if not first step, show "Previous" button if(!SubmissionController.isFirstStep(request, subInfo)) { %> - <td> - <input type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.general.previous"/>" /> - </td> + <input class="btn btn-default col-md-<%= 12 / (col + 2) %>" type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.general.previous"/>" /> <% } %> - <td> - <input type="submit" name="<%=UploadStep.SUBMIT_UPLOAD_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> - </td> + <input class="btn btn-default col-md-<%= 12 / (col + 2) %>" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> <% //if upload is set to optional, or user returned to this page after pressing "Add Another File" button - if (!fileRequired || UIUtil.getSubmitButton(request, "").equals(UploadStep.SUBMIT_MORE_BUTTON)) + if (!fileRequired || subInfo.getSubmissionItem().getItem().hasUploadedFiles()) { %> - <td> - <input type="submit" name="<%=UploadStep.SUBMIT_SKIP_BUTTON%>" value="<fmt:message key="jsp.submit.choose-file.skip"/>" /> - </td> + <input class="btn btn-warning col-md-<%= 12 / (col + 2) %>" type="submit" name="<%=UploadStep.SUBMIT_SKIP_BUTTON%>" value="<fmt:message key="jsp.submit.choose-file.skip"/>" /> <% } %> - - <td> </td> - <td align="right"> - <input type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-primary col-md-<%= 12 / (col + 2) %>" type="submit" name="<%=UploadStep.SUBMIT_UPLOAD_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> + </div> </form> - +<% + if (bSherpa) + { +%> +<div class="col-md-4"> + <div id="sherpaBox" class="panel panel-info"> + <div class="panel-heading"> + <span id="ui-id-1"><fmt:message key="jsp.sherpa.title" /></span> + </div> + <div id="sherpaContent" class="panel-body"> + <fmt:message key="jsp.sherpa.loading"> + <fmt:param value="<%=request.getContextPath()%>" /> + </fmt:message> + </div> + </div> +</div> +<% + } +%> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/complete.jsp b/dspace-jspui/src/main/webapp/submit/complete.jsp index 1f89d9c7459de50c1cbee0437b88ee2afc890194..5ae9c8ba36d9d9512a5a551d19563915db76f442 100644 --- a/dspace-jspui/src/main/webapp/submit/complete.jsp +++ b/dspace-jspui/src/main/webapp/submit/complete.jsp @@ -39,7 +39,7 @@ Collection collection = subInfo.getSubmissionItem().getCollection(); %> -<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.complete.title"> +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.complete.title"> <jsp:include page="/submit/progressbar.jsp"/> @@ -52,14 +52,14 @@ 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.</p> --%> - <p><fmt:message key="jsp.submit.complete.info"/></p> + <p class="alert alert-info"><fmt:message key="jsp.submit.complete.info"/></p> <p><a href="<%= request.getContextPath() %>/mydspace"><fmt:message key="jsp.submit.complete.link"/></a></p> <p><a href="<%= request.getContextPath() %>/community-list"><fmt:message key="jsp.community-list.title"/></a></p> <form action="<%= request.getContextPath() %>/submit" method="post" onkeydown="return disableEnterKey(event);"> <input type="hidden" name="collection" value="<%= collection.getID() %>"/> - <input type="submit" name="submit" value="<fmt:message key="jsp.submit.complete.again"/>"/> + <input class="btn btn-success pull-right" type="submit" name="submit" value="<fmt:message key="jsp.submit.complete.again"/>"/> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/creative-commons.jsp b/dspace-jspui/src/main/webapp/submit/creative-commons.jsp index 4b65d0a054ae523597a811b23f115aa965a23419..8893489e223b96b4af894c0d2395c670da3afd72 100644 --- a/dspace-jspui/src/main/webapp/submit/creative-commons.jsp +++ b/dspace-jspui/src/main/webapp/submit/creative-commons.jsp @@ -62,7 +62,8 @@ licenseURL = CreativeCommons.getLicenseURL(subInfo.getSubmissionItem().getItem()); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" + locbar="off" navbar="off" titlekey="jsp.submit.creative-commons.title" nocache="true"> @@ -73,7 +74,6 @@ <%-- <h1>Submit: Use a Creative Commons License</h1> --%> <h1><fmt:message key="jsp.submit.creative-commons.heading"/></h1> -<br /> <% if (licenseExists) @@ -81,13 +81,13 @@ %> <%-- <p>You have already chosen a Creative Commons license and added it to this item. You may:</p> --%> - <p><fmt:message key="jsp.submit.creative-commons.info1"/></p> + <p class="help-block"><fmt:message key="jsp.submit.creative-commons.info1"/></p> <%-- <ul> <li>Press the 'Next' button below to <em>keep</em> the license previously chosen.</li> <li>Press the 'Skip Creative Commons' button below to <em>remove</em> the current choice, and forego a Creative Commons license.</li> <li>Complete the selection process below to <em>replace</em> the current choice.</li> </ul> --%> - <ul> + <ul class="alert alert-info"> <li><fmt:message key="jsp.submit.creative-commons.choice1"/></li> <li><fmt:message key="jsp.submit.creative-commons.choice2"/></li> <li><fmt:message key="jsp.submit.creative-commons.choice3"/></li> @@ -106,44 +106,35 @@ <%-- <iframe src="http://creativecommons.org/license/?partner=dspace&stylesheet=<%= java.net.URLEncoder.encode(ssURL) %>&exit_url=<%= java.net.URLEncoder.encode(exitURL) %>" width="100%" height="540">Your browser must support IFrames to use this feature </iframe> --%> - <iframe src="http://creativecommons.org/license/?partner=dspace&stylesheet=<%= java.net.URLEncoder.encode(ssURL) %>&exit_url=<%= java.net.URLEncoder.encode(exitURL) %><%= jurisdiction %>" width="100%" height="540"><fmt:message key="jsp.submit.creative-commons.info3"/> + <iframe src="http://creativecommons.org/license/?partner=dspace&stylesheet=<%= java.net.URLEncoder.encode(ssURL, "UTF-8") %>&exit_url=<%= java.net.URLEncoder.encode(exitURL, "UTF-8") %><%= jurisdiction %>" width="100%" height="540"><fmt:message key="jsp.submit.creative-commons.info3"/> </iframe> <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> <input type="hidden" name="cc_license_url" value="<%=licenseURL %>" /> - <input type="hidden" name="submit_grant" value="I Grant the License" /> - <center> - <table border="0" width="80%"> - <tr> - <td width="100%"> </td> + <input type="submit" id="submit_grant" name="submit_grant" value="submit_grant" style="display: none;" /> + <% + int numButton = 2 + (!SubmissionController.isFirstStep(request, subInfo)?1:0) + (licenseExists?1:0); + + %> + <div class="row col-md-<%= 2*numButton %> pull-right btn-group"> <% //if not first step, show "Previous" button if(!SubmissionController.isFirstStep(request, subInfo)) { %> - <td> - <input type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.general.previous"/>" /> - </td> + <input class="btn btn-default col-md-<%= 12 / numButton %>" type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.general.previous"/>" /> <% } %> + + <input class="btn btn-default col-md-<%= 12 / numButton %>" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>"/> + <input class="btn btn-warning col-md-<%= 12 / numButton %>" type="submit" name="submit_no_cc" value="<fmt:message key="jsp.submit.creative-commons.skip.button"/>"/> <% if (licenseExists) { %> - <td> - <input type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> - </td> + <input class="btn btn-primary col-md-<%= 12 / numButton %>" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> <% } %> - <td> - <input type="submit" name="submit_no_cc" value="<fmt:message key="jsp.submit.creative-commons.skip.button"/>"/> - </td> - <td> </td> - <td align="right"> - <input type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>"/> - </td> - </tr> - </table> - </center> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/edit-metadata.jsp b/dspace-jspui/src/main/webapp/submit/edit-metadata.jsp index 3f543eaa2048823ab1bcf0b2114f15b165666398..aac949f7ac7ad2c92755065859614557856c4fba 100644 --- a/dspace-jspui/src/main/webapp/submit/edit-metadata.jsp +++ b/dspace-jspui/src/main/webapp/submit/edit-metadata.jsp @@ -82,7 +82,7 @@ { fieldName = fieldName.substring(0, fieldName.length() - 2); } - link = "<br/>" + + link = "<a href='javascript:void(null);' onclick='javascript:popUp(\"" + contextPath + "/controlledvocabulary/controlledvocabulary.jsp?ID=" + fieldName + "&vocabulary=" + vocabulary + "\")'>" + @@ -116,6 +116,20 @@ "select".equals(cam.getPresentation(fieldKey))); } + // Get the presentation type of the authority if any, null otherwise + String getAuthorityType(PageContext pageContext, String fieldName, int collectionID) + { + MetadataAuthorityManager mam = MetadataAuthorityManager.getManager(); + ChoiceAuthorityManager cam = ChoiceAuthorityManager.getManager(); + StringBuffer sb = new StringBuffer(); + + if (cam.isChoicesConfigured(fieldName)) + { + return cam.getPresentation(fieldName); + } + return null; + } + // Render the choice/authority controlled entry, or, if not indicated, // returns the given default inputBlock StringBuffer doAuthority(PageContext pageContext, String fieldName, @@ -145,21 +159,26 @@ String confidenceSymbol = confidenceValue == unknownConfidence ? "blank" : Choices.getConfidenceText(confidenceValue).toLowerCase(); String confIndID = fieldInput+"_confidence_indicator_id"; + if (authority) - { + { sb.append(" <img id=\""+confIndID+"\" title=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.authority.confidence.description."+confidenceSymbol)) - .append("\" class=\"ds-authority-confidence cf-") + .append("\" class=\"pull-left ds-authority-confidence cf-") // set confidence to cf-blank if authority is empty .append(authorityValue==null||authorityValue.length()==0 ? "blank" : confidenceSymbol) - .append(" \" src=\"").append(contextPath).append("/image/confidence/invisible.gif\" />") - .append("<input type=\"text\" value=\"").append(authorityValue!=null?authorityValue:"") + .append(" \" src=\"").append(contextPath).append("/image/confidence/invisible.gif\" />"); + + + sb.append("<input type=\"text\" value=\"").append(authorityValue!=null?authorityValue:"") .append("\" id=\"").append(authorityName) - .append("\" name=\"").append(authorityName).append("\" class=\"ds-authority-value\"/>") + .append("\" name=\"").append(authorityName).append("\" class=\"ds-authority-value form-control\"/>") .append("<input type=\"hidden\" value=\"").append(confidenceSymbol) .append("\" id=\"").append(confidenceName) .append("\" name=\"").append(confidenceName) .append("\" class=\"ds-authority-confidence-input\"/>"); + + } // suggest is not supported for name input type @@ -186,7 +205,7 @@ // put up a SELECT element containing all choices else if (isSelect) { - sb.append("<select id=\"").append(fieldInput) + sb.append("<select class=\"form-control\" id=\"").append(fieldInput) .append("_id\" name=\"").append(fieldInput) .append("\" size=\"").append(String.valueOf(repeatable ? 6 : 1)) .append(repeatable ? "\" multiple>\n" :"\">\n"); @@ -216,7 +235,7 @@ { if (inputBlock != null) sb.insert(0, inputBlock); - sb.append("<input type=\"image\" name=\"").append(fieldInput).append("_lookup\" ") + sb.append("<button class=\"btn btn-default col-md-1\" name=\"").append(fieldInput).append("_lookup\" ") .append("onclick=\"javascript: return DSpaceChoiceLookup('") .append(contextPath).append("/tools/lookup.jsp','") .append(fieldName).append("','edit_metadata','") @@ -226,8 +245,9 @@ .append(String.valueOf(isName)).append(",false);\"") .append(" title=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.tools.lookup.lookup")) - .append("\" width=\"16px\" height=\"16px\" src=\""+contextPath+"/image/authority/zoom.png\" />"); + .append("\"><span class=\"glyphicon glyphicon-search\"></span></button>"); } + } else if (inputBlock != null) sb = inputBlock; @@ -235,11 +255,12 @@ } void doPersonalName(javax.servlet.jsp.JspWriter out, Item item, - String fieldName, String schema, String element, String qualifier, boolean repeatable, + String fieldName, String schema, String element, String qualifier, boolean repeatable, boolean required, boolean readonly, int fieldCountIncr, String label, PageContext pageContext, int collectionID) throws java.io.IOException { - + String authorityType = getAuthorityType(pageContext, fieldName, collectionID); + DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY); int fieldCount = defaults.length + fieldCountIncr; StringBuffer headers = new StringBuffer(); @@ -254,23 +275,15 @@ if (fieldCount == 0) fieldCount = 1; - //Width hints used here to affect whole table - headers.append("<tr><td width=\"40%\"> </td>") - .append("<td class=\"submitFormDateLabel\" width=\"5%\">") -// .append("Last name<br>e.g. <strong>Smith</strong></td>") - .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.lastname")) - .append("</td>") - .append("<td class=\"submitFormDateLabel\" width=\"5%\">") -// .append("First name(s) + \"Jr\"<br> e.g. <strong>Donald Jr</strong></td>") - .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.firstname")) - .append("</td>") - .append("<td width=\"40%\"> </td>") - .append("</tr>"); - out.write(headers.toString()); - - + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">").append(label).append("</label>"); + sb.append("<div class=\"col-md-10\">"); for (int i = 0; i < fieldCount; i++) { + sb.append("<div class=\"row col-md-12\">"); + if ("lookup".equalsIgnoreCase(authorityType)) + { + sb.append("<div class=\"row col-md-10\">"); + } first.setLength(0); first.append(fieldName).append("_first"); if (repeatable && i != fieldCount-1) @@ -280,13 +293,6 @@ last.append(fieldName).append("_last"); if (repeatable && i != fieldCount-1) last.append('_').append(i+1); - - if (i == 0) - sb.append("<tr><td class=\"submitFormLabel\">") - .append(label) - .append("</td>"); - else - sb.append("<tr><td> </td>"); if (i < defaults.length) { @@ -301,7 +307,9 @@ conf = unknownConfidence; } - sb.append("<td><input type=\"text\" name=\"") + sb.append("<span class=\"col-md-5\"><input placeholder=\"") + .append(Utils.addEntities(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.lastname"))) + .append("\" class=\"form-control\" type=\"text\" name=\"") .append(last.toString()) .append("\" size=\"23\" "); if (readonly) @@ -310,7 +318,9 @@ } sb.append("value=\"") .append(dpn.getLastName().replaceAll("\"", """)) // Encode " - .append("\"/></td>\n<td nowrap=\"nowrap\"><input type=\"text\" name=\"") + .append("\"/></span><span class=\"col-md-5\"><input placeholder=\"") + .append(Utils.addEntities(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.firstname"))) + .append("\" class=\"form-control\" type=\"text\" name=\"") .append(first.toString()) .append("\" size=\"23\" "); if (readonly) @@ -318,10 +328,15 @@ sb.append("disabled=\"disabled\" "); } sb.append("value=\"") - .append(dpn.getFirstNames()).append("\"/>") - .append(doAuthority(pageContext, fieldName, i, fieldCount, fieldName, - auth, conf, true, repeatable, defaults, null, collectionID)) - .append("</td>\n"); + .append(dpn.getFirstNames()).append("\"/></span>"); + + if ("lookup".equalsIgnoreCase(authorityType)) + { + sb.append(doAuthority(pageContext, fieldName, i, fieldCount, fieldName, + auth, conf, true, repeatable, defaults, null, collectionID)); + sb.append("</div>"); + } + if (repeatable && !readonly && i < defaults.length) { @@ -330,37 +345,31 @@ .append(' ') .append(Utils.addEntities(dpn.getFirstNames())); // put a remove button next to filled in values - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-danger pull-right col-md-2\" name=\"submit_") .append(fieldName) .append("_remove_") .append(i) -// .append("\" value=\"Remove This Entry\"/> </td></tr>") - .append("\" value=\"") - .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")) - .append("\"/> </td></tr>"); + .append("\" value=\"") + .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")) + .append("\"><span class=\"glyphicon glyphicon-trash\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>"); } else if (repeatable && !readonly && i == fieldCount - 1) { // put a 'more' button next to the last space - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-default pull-right col-md-2\" name=\"submit_") .append(fieldName) -// .append("_add\" value=\"Add More\"/> </td></tr>"); .append("_add\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")) - .append("\"/> </td></tr>"); - } - else - { - // put a blank if nothing else - sb.append("<td> </td></tr>"); - } + .append("\"><span class=\"glyphicon glyphicon-plus\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")+"</button>"); + } + sb.append("</div>"); } - + sb.append("</div></div><br/>"); out.write(sb.toString()); } void doDate(javax.servlet.jsp.JspWriter out, Item item, - String fieldName, String schema, String element, String qualifier, boolean repeatable, + String fieldName, String schema, String element, String qualifier, boolean repeatable, boolean required, boolean readonly, int fieldCountIncr, String label, PageContext pageContext, HttpServletRequest request) throws java.io.IOException { @@ -373,24 +382,21 @@ if (fieldCount == 0) fieldCount = 1; + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">") + .append(label) + .append("</label><div class=\"col-md-10\">"); + for (int i = 0; i < fieldCount; i++) { - if (i == 0) - sb.append("<tr><td class=\"submitFormLabel\">") - .append(label) - .append("</td>"); - else - sb.append("<tr><td> </td>"); - if (i < defaults.length) dateIssued = new org.dspace.content.DCDate(defaults[i].value); else dateIssued = new org.dspace.content.DCDate(""); - sb.append("<td colspan=\"2\" nowrap=\"nowrap\" class=\"submitFormDateLabel\">") -// .append("Month:<select name=\"") - .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.month")) - .append("<select name=\"") + sb.append("<div class=\"row col-md-12\"><div class=\"input-group col-md-10\"><div class=\"row\">") + .append("<span class=\"input-group col-md-6\"><span class=\"input-group-addon\">") + .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.month")) + .append("</span><select class=\"form-control\" name=\"") .append(fieldName) .append("_month"); if (repeatable && i>0) @@ -418,10 +424,10 @@ .append("</option>"); } - sb.append("</select>") -// .append("Day:<input type=text name=\"") + sb.append("</select></span>") + .append("<span class=\"input-group col-md-2\"><span class=\"input-group-addon\">") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.day")) - .append("<input type=\"text\" name=\"") + .append("</span><input class=\"form-control\" type=\"text\" name=\"") .append(fieldName) .append("_day"); if (repeatable && i>0) @@ -433,10 +439,9 @@ sb.append("\" size=\"2\" maxlength=\"2\" value=\"") .append((dateIssued.getDay() > 0 ? String.valueOf(dateIssued.getDay()) : "" )) -// .append("\"/>Year:<input type=text name=\"") - .append("\"/>") + .append("\"/></span><span class=\"input-group col-md-4\"><span class=\"input-group-addon\">") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.year")) - .append("<input type=\"text\" name=\"") + .append("</span><input class=\"form-control\" type=\"text\" name=\"") .append(fieldName) .append("_year"); if (repeatable && i>0) @@ -448,43 +453,38 @@ sb.append("\" size=\"4\" maxlength=\"4\" value=\"") .append((dateIssued.getYear() > 0 ? String.valueOf(dateIssued.getYear()) : "" )) - .append("\"/></td>\n"); + .append("\"/></span></div></div>\n"); if (repeatable && !readonly && i < defaults.length) { // put a remove button next to filled in values - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-danger col-md-2\" name=\"submit_") .append(fieldName) .append("_remove_") .append(i) -// .append("\" value=\"Remove This Entry\"/> </td></tr>"); - .append("\" value=\"") - .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")) - .append("\"/> </td></tr>"); + .append("\" value=\"") + .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")) + .append("\"><span class=\"glyphicon glyphicon-trash\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>"); } else if (repeatable && !readonly && i == fieldCount - 1) { // put a 'more' button next to the last space - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-default col-md-2\" name=\"submit_") .append(fieldName) -// .append("_add\" value=\"Add More\"/> </td></tr>"); .append("_add\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")) - .append("\"/> </td></tr>"); - } - else - { - // put a blank if nothing else - sb.append("<td> </td></tr>"); + .append("\"><span class=\"glyphicon glyphicon-plus\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")+"</button>"); } + // put a blank if nothing else + sb.append("</div>"); } - + sb.append("</div></div><br/>"); out.write(sb.toString()); } void doSeriesNumber(javax.servlet.jsp.JspWriter out, Item item, String fieldName, String schema, String element, String qualifier, boolean repeatable, - boolean readonly, int fieldCountIncr, String label, PageContext pageContext) + boolean required, boolean readonly, int fieldCountIncr, String label, PageContext pageContext) throws java.io.IOException { @@ -494,39 +494,21 @@ org.dspace.content.DCSeriesNumber sn; StringBuffer headers = new StringBuffer(); - //Width hints used here to affect whole table - headers.append("<tr><td width=\"40%\"> </td>") - .append("<td class=\"submitFormDateLabel\" width=\"5%\">") -// .append("Series Name</td>") - .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.seriesname")) - .append("</td>") - .append("<td class=\"submitFormDateLabel\" width=\"5%\">") -// .append("Report or Paper No.</td>") - .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.paperno")) - .append("</td>") - .append("<td width=\"40%\"> </td>") - .append("</tr>"); - out.write(headers.toString()); - - if (fieldCount == 0) fieldCount = 1; + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">") + .append(label) + .append("</label><div class=\"col-md-10\">"); + for (int i = 0; i < fieldCount; i++) { - if (i == 0) - sb.append("<tr><td class=\"submitFormLabel\">") - .append(label) - .append("</td>"); - else - sb.append("<tr><td> </td>"); - if (i < defaults.length) sn = new org.dspace.content.DCSeriesNumber(defaults[i].value); else sn = new org.dspace.content.DCSeriesNumber(); - sb.append("<td><input type=\"text\" name=\"") + sb.append("<div class=\"row col-md-12\"><span class=\"col-md-5\"><input class=\"form-control\" type=\"text\" name=\"") .append(fieldName) .append("_series"); if (repeatable && i!= fieldCount) @@ -535,9 +517,11 @@ { sb.append("\" disabled=\"disabled"); } + sb.append("\" placeholder=\"") + .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.seriesname").replaceAll("\"", """)); sb.append("\" size=\"23\" value=\"") .append(sn.getSeries().replaceAll("\"", """)) - .append("\"/></td>\n<td><input type=\"text\" name=\"") + .append("\"/></span><span class=\"col-md-5\"><input class=\"form-control\" type=\"text\" name=\"") .append(fieldName) .append("_number"); if (repeatable && i!= fieldCount) @@ -546,48 +530,47 @@ { sb.append("\" disabled=\"disabled"); } + sb.append("\" placeholder=\"") + .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.paperno").replaceAll("\"", """)); sb.append("\" size=\"23\" value=\"") .append(sn.getNumber().replaceAll("\"", """)) - .append("\"/></td>\n"); + .append("\"/></span>\n"); if (repeatable && !readonly && i < defaults.length) { // put a remove button next to filled in values - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-danger col-md-2\" name=\"submit_") .append(fieldName) .append("_remove_") .append(i) -// .append("\" value=\"Remove This Entry\"/> </td></tr>"); .append("\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")) - .append("\"/> </td></tr>"); + .append("\"><span class=\"glyphicon glyphicon-trash\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>"); } else if (repeatable && !readonly && i == fieldCount - 1) { // put a 'more' button next to the last space - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-default col-md-2\" name=\"submit_") .append(fieldName) -// .append("_add\" value=\"Add More\"/> </td></tr>"); .append("_add\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")) - .append("\"/> </td></tr>"); - } - else - { - // put a blank if nothing else - sb.append("<td> </td></tr>"); + .append("\"><span class=\"glyphicon glyphicon-plus\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")+"</button>"); } - } + // put a blank if nothing else + sb.append("</div>"); + } + sb.append("</div></div><br/>"); + out.write(sb.toString()); } void doTextArea(javax.servlet.jsp.JspWriter out, Item item, - String fieldName, String schema, String element, String qualifier, boolean repeatable, boolean readonly, + String fieldName, String schema, String element, String qualifier, boolean repeatable, boolean required, boolean readonly, int fieldCountIncr, String label, PageContext pageContext, String vocabulary, boolean closedVocabulary, int collectionID) throws java.io.IOException { - + String authorityType = getAuthorityType(pageContext, fieldName, collectionID); DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY); int fieldCount = defaults.length + fieldCountIncr; StringBuffer sb = new StringBuffer(); @@ -597,15 +580,12 @@ if (fieldCount == 0) fieldCount = 1; + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">") + .append(label) + .append("</label><div class=\"col-md-10\">"); + for (int i = 0; i < fieldCount; i++) { - if (i == 0) - sb.append("<tr><td class=\"submitFormLabel\">") - .append(label) - .append("</td>"); - else - sb.append("<tr><td> </td>"); - if (i < defaults.length) { val = defaults[i].value; @@ -617,59 +597,68 @@ val = ""; auth = ""; } - sb.append("<td colspan=\"2\">\n"); + sb.append("<div class=\"row col-md-12\">\n"); String fieldNameIdx = fieldName + ((repeatable && i != fieldCount-1)?"_" + (i+1):""); - StringBuffer inputBlock = new StringBuffer().append("<textarea name=\"").append(fieldNameIdx) + sb.append("<div class=\"col-md-10\">"); + if (authorityType != null) + { + sb.append("<div class=\"col-md-10\">"); + } + sb.append("<textarea class=\"form-control\" name=\"").append(fieldNameIdx) .append("\" rows=\"4\" cols=\"45\" id=\"") .append(fieldNameIdx).append("_id\" ") .append((hasVocabulary(vocabulary)&&closedVocabulary)||readonly?" disabled=\"disabled\" ":"") .append(">") .append(val) - .append("</textarea>\n") + .append("</textarea>") .append(doControlledVocabulary(fieldNameIdx, pageContext, vocabulary, readonly)); - sb.append(doAuthority(pageContext, fieldName, i, fieldCount, fieldName, + if (authorityType != null) + { + sb.append("</div><div class=\"col-md-2\">"); + sb.append(doAuthority(pageContext, fieldName, i, fieldCount, fieldName, auth, conf, false, repeatable, - defaults, inputBlock, collectionID)) - .append("</td>\n"); + defaults, null, collectionID)); + sb.append("</div>"); + } + sb.append("</div>"); + + if (repeatable && !readonly && i < defaults.length) { // put a remove button next to filled in values - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-danger col-md-2\" name=\"submit_") .append(fieldName) .append("_remove_") .append(i) -// .append("\" value=\"Remove This Entry\"/> </td></tr>"); .append("\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")) - .append("\"/> </td></tr>"); + .append("\"><span class=\"glyphicon glyphicon-trash\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>"); } else if (repeatable && !readonly && i == fieldCount - 1) { // put a 'more' button next to the last space - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-default col-md-2\" name=\"submit_") .append(fieldName) -// .append("_add\" value=\"Add More\"/> </td></tr>"); .append("_add\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")) - .append("\"/> </td></tr>"); + .append("\"><span class=\"glyphicon glyphicon-plus\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")+"</button>"); } - else - { - // put a blank if nothing else - sb.append("<td> </td></tr>"); - } - } + // put a blank if nothing else + sb.append("</div>"); + } + sb.append("</div></div><br/>"); + out.write(sb.toString()); } void doOneBox(javax.servlet.jsp.JspWriter out, Item item, - String fieldName, String schema, String element, String qualifier, boolean repeatable, boolean readonly, + String fieldName, String schema, String element, String qualifier, boolean repeatable, boolean required, boolean readonly, int fieldCountIncr, String label, PageContext pageContext, String vocabulary, boolean closedVocabulary, int collectionID) throws java.io.IOException { - + String authorityType = getAuthorityType(pageContext, fieldName, collectionID); DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY); int fieldCount = defaults.length + fieldCountIncr; StringBuffer sb = new StringBuffer(); @@ -679,15 +668,12 @@ if (fieldCount == 0) fieldCount = 1; - for (int i = 0; i < fieldCount; i++) - { - if (i == 0) - sb.append("<tr><td class=\"submitFormLabel\">") - .append(label) - .append("</td>"); - else - sb.append("<tr><td> </td>"); - + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">") + .append(label) + .append("</label>"); + sb.append("<div class=\"col-md-10\">"); + for (int i = 0; i < fieldCount; i++) + { if (i < defaults.length) { val = defaults[i].value.replaceAll("\"", """); @@ -701,56 +687,64 @@ conf= unknownConfidence; } - sb.append("<td colspan=\"2\">"); + sb.append("<div class=\"row col-md-12\">"); String fieldNameIdx = fieldName + ((repeatable && i != fieldCount-1)?"_" + (i+1):""); - StringBuffer inputBlock = new StringBuffer("<input type=\"text\" name=\"") + + sb.append("<div class=\"col-md-10\">"); + if (authorityType != null) + { + sb.append("<div class=\"row col-md-10\">"); + } + sb.append("<input class=\"form-control\" type=\"text\" name=\"") .append(fieldNameIdx) .append("\" id=\"") .append(fieldNameIdx).append("\" size=\"50\" value=\"") .append(val +"\"") .append((hasVocabulary(vocabulary)&&closedVocabulary) || readonly?" disabled=\"disabled\" ":"") .append("/>") - .append(doControlledVocabulary(fieldNameIdx, pageContext, vocabulary, readonly)) - .append("\n"); - sb.append(doAuthority(pageContext, fieldName, i, fieldCount, + .append(doControlledVocabulary(fieldNameIdx, pageContext, vocabulary, readonly)) + .append("</div>"); + + if (authorityType != null) + { + sb.append("<div class=\"col-md-2\">"); + sb.append(doAuthority(pageContext, fieldName, i, fieldCount, fieldName, auth, conf, false, repeatable, - defaults, inputBlock, collectionID)) - .append("</td>\n"); + defaults, null, collectionID)); + sb.append("</div></div>"); + } if (repeatable && !readonly && i < defaults.length) { // put a remove button next to filled in values - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-danger col-md-2\" name=\"submit_") .append(fieldName) .append("_remove_") .append(i) -// .append("\" value=\"Remove This Entry\"/> </td></tr>"); .append("\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")) - .append("\"/> </td></tr>"); + .append("\"><span class=\"glyphicon glyphicon-trash\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>"); } else if (repeatable && !readonly && i == fieldCount - 1) { // put a 'more' button next to the last space - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-default col-md-2\" name=\"submit_") .append(fieldName) -// .append("_add\" value=\"Add More\"/> </td></tr>"); .append("_add\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")) - .append("\"/> </td></tr>"); + .append("\"><span class=\"glyphicon glyphicon-plus\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")+"</button>"); } - else - { - // put a blank if nothing else - sb.append("<td> </td></tr>"); - } - } + sb.append("</div>"); + } + sb.append("</div>"); + sb.append("</div><br/>"); + out.write(sb.toString()); } void doTwoBox(javax.servlet.jsp.JspWriter out, Item item, - String fieldName, String schema, String element, String qualifier, boolean repeatable, boolean readonly, + String fieldName, String schema, String element, String qualifier, boolean repeatable, boolean required, boolean readonly, int fieldCountIncr, String label, PageContext pageContext, String vocabulary, boolean closedVocabulary) throws java.io.IOException { @@ -760,83 +754,66 @@ StringBuffer headers = new StringBuffer(); String fieldParam = ""; - - if (element.equals("relation") && qualifier.equals("ispartofseries")) - { - //Width hints used here to affect whole table - headers.append("<tr><td width=\"40%\"> </td>") - .append("<td class=\"submitFormDateLabel\" width=\"5%\">") -// .append("Series Name</td>") - .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.seriesname")) - .append("</td>") - .append("<td class=\"submitFormDateLabel\" width=\"5%\">") -// .append("Report or Paper No.</td>") - .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.paperno")) - .append("</td>") - .append("<td width=\"40%\"> </td>") - .append("</tr>"); - out.write(headers.toString()); - } if (fieldCount == 0) fieldCount = 1; + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">") + .append(label) + .append("</label>"); + sb.append("<div class=\"col-md-10\">"); for (int i = 0; i < fieldCount; i++) { - if (i == 0) - { - sb.append("<tr><td class=\"submitFormLabel\">") - .append(label) - .append("</td>"); - } - else - { - sb.append("<tr><td> </td>"); - } - - if(i != fieldCount) - { - //param is field name and index, starting from 1 (e.g. myfield_2) - fieldParam = fieldName + "_" + (i+1); - } - else - { - //param is just the field name - fieldParam = fieldName; - } + sb.append("<div class=\"row col-md-12\">"); + + if(i != fieldCount) + { + //param is field name and index, starting from 1 (e.g. myfield_2) + fieldParam = fieldName + "_" + (i+1); + } + else + { + //param is just the field name + fieldParam = fieldName; + } if (i < defaults.length) { - sb.append("<td align=\"left\"><input type=\"text\" name=\"") + sb.append("<span class=\"col-md-4\"><input class=\"form-control\" type=\"text\" name=\"") .append(fieldParam) .append("\" size=\"15\" value=\"") .append(defaults[i].value.replaceAll("\"", """)) .append("\"") .append((hasVocabulary(vocabulary)&&closedVocabulary) || readonly?" disabled=\"disabled\" ":"") - .append("/>"); + .append("\" />"); + + sb.append(doControlledVocabulary(fieldParam, pageContext, vocabulary, readonly)); + sb.append("</span>"); if (!readonly) { - sb.append(" <input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-danger col-md-2\" name=\"submit_") .append(fieldName) .append("_remove_") .append(i) .append("\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove2")) - .append("\"/>"); + .append("\"><span class=\"glyphicon glyphicon-trash\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>"); + } + else { + sb.append("<span class=\"col-md-2\"> </span>"); } - sb.append(doControlledVocabulary(fieldParam, pageContext, vocabulary, readonly)) - .append("</td>\n"); } else - { - sb.append("<td align=\"left\"><input type=\"text\" name=\"") + { + sb.append("<span class=\"col-md-4\"><input class=\"form-control\" type=\"text\" name=\"") .append(fieldParam) .append("\" size=\"15\"") .append((hasVocabulary(vocabulary)&&closedVocabulary) || readonly?" disabled=\"disabled\" ":"") .append("/>") .append(doControlledVocabulary(fieldParam, pageContext, vocabulary, readonly)) - .append("</td>\n"); - } + .append("</span>\n") + .append("<span class=\"col-md-2\"> </span>"); + } i++; @@ -853,80 +830,76 @@ if (i < defaults.length) { - sb.append("<td align=\"left\"><input type=\"text\" name=\"") + sb.append("<span class=\"col-md-4\"><input class=\"form-control\" type=\"text\" name=\"") .append(fieldParam) .append("\" size=\"15\" value=\"") .append(defaults[i].value.replaceAll("\"", """)) .append("\"") .append((hasVocabulary(vocabulary)&&closedVocabulary) || readonly?" disabled=\"disabled\" ":"") .append("/>"); + sb.append(doControlledVocabulary(fieldParam, pageContext, vocabulary, readonly)); + sb.append("</span>"); if (!readonly) { - sb.append(" <input type=\"submit\" name=\"submit_") + sb.append(" <button class=\"btn btn-danger col-md-2\" name=\"submit_") .append(fieldName) .append("_remove_") .append(i) .append("\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove2")) - .append("\"/>"); + .append("\"><span class=\"glyphicon glyphicon-trash\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>"); } - - sb.append(doControlledVocabulary(fieldParam, pageContext, vocabulary, readonly)) - .append("</td></tr>\n"); + else { + sb.append("<span class=\"col-md-2\"> </span>"); + } } else { - sb.append("<td align=\"left\"><input type=\"text\" name=\"") + sb.append("<span class=\"col-md-4\"><input class=\"form-control\" type=\"text\" name=\"") .append(fieldParam) - //.append("\" size=\"15\"/></td>"); .append("\" size=\"15\"") .append((hasVocabulary(vocabulary)&&closedVocabulary)||readonly?" disabled=\"disabled\" ":"") .append("/>") .append(doControlledVocabulary(fieldParam, pageContext, vocabulary, readonly)) - .append("</td>\n"); - + .append("</span>\n"); if (i+1 >= fieldCount && !readonly) { - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append(" <button class=\"btn btn-default col-md-2\" name=\"submit_") .append(fieldName) .append("_add\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")) - .append("\"/></td>\n"); + .append("\"><span class=\"glyphicon glyphicon-plus\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")+"</button>\n"); } - else - { - sb.append("</td>"); - } - sb.append("<td> </td></tr>"); } + sb.append("</div>"); } - + sb.append("</div></div><br/>"); out.write(sb.toString()); } void doQualdropValue(javax.servlet.jsp.JspWriter out, Item item, - String fieldName, String schema, String element, DCInputSet inputs, boolean repeatable, + String fieldName, String schema, String element, DCInputSet inputs, boolean repeatable, boolean required, boolean readonly, int fieldCountIncr, List qualMap, String label, PageContext pageContext) throws java.io.IOException { - DCValue[] unfiltered = item.getMetadata(schema, element, Item.ANY, Item.ANY); - // filter out both unqualified and qualified values occurring elsewhere in inputs - List<DCValue> filtered = new ArrayList<DCValue>(); - for (int i = 0; i < unfiltered.length; i++) - { - String unfilteredFieldName = unfiltered[i].element; - if(unfiltered[i].qualifier != null && unfiltered[i].qualifier.length()>0) - unfilteredFieldName += "." + unfiltered[i].qualifier; - - if ( ! inputs.isFieldPresent(unfilteredFieldName) ) - { - filtered.add( unfiltered[i] ); - } - } - DCValue[] defaults = filtered.toArray(new DCValue[0]); - //DCValue[] defaults = item.getMetadata(element, Item.ANY, Item.ANY); + DCValue[] unfiltered = item.getMetadata(schema, element, Item.ANY, Item.ANY); + // filter out both unqualified and qualified values occurring elsewhere in inputs + List<DCValue> filtered = new ArrayList<DCValue>(); + for (int i = 0; i < unfiltered.length; i++) + { + String unfilteredFieldName = unfiltered[i].element; + if(unfiltered[i].qualifier != null && unfiltered[i].qualifier.length()>0) + unfilteredFieldName += "." + unfiltered[i].qualifier; + + if ( ! inputs.isFieldPresent(unfilteredFieldName) ) + { + filtered.add( unfiltered[i] ); + } + } + DCValue[] defaults = filtered.toArray(new DCValue[0]); + int fieldCount = defaults.length + fieldCountIncr; StringBuffer sb = new StringBuffer(); String q, v, currentQual, currentVal; @@ -934,6 +907,10 @@ if (fieldCount == 0) fieldCount = 1; + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">") + .append(label) + .append("</label>"); + sb.append("<div class=\"col-md-10\">"); for (int j = 0; j < fieldCount; j++) { @@ -949,15 +926,8 @@ currentVal = ""; } - if (j == 0) - sb.append("<tr><td class=\"submitFormLabel\">") - .append(label) - .append("</td>"); - else - sb.append("<tr><td> </td>"); - // do the dropdown box - sb.append("<td colspan=\"2\"><select name=\"") + sb.append("<div class=\"row col-md-12\"><span class=\"input-group col-md-10\"><span class=\"input-group-addon\"><select name=\"") .append(fieldName) .append("_qualifier"); if (repeatable && j!= fieldCount-1) @@ -981,7 +951,7 @@ } // do the input box - sb.append("</select> <input type=\"text\" name=\"") + sb.append("</select></span><input class=\"form-control\" type=\"text\" name=\"") .append(fieldName) .append("_value"); if (repeatable && j!= fieldCount-1) @@ -992,43 +962,40 @@ } sb.append("\" size=\"34\" value=\"") .append(currentVal.replaceAll("\"", """)) - .append("\"/></td>\n"); + .append("\"/></span>\n"); if (repeatable && !readonly && j < defaults.length) { // put a remove button next to filled in values - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-danger col-md-2\" name=\"submit_") .append(fieldName) .append("_remove_") .append(j) -// .append("\" value=\"Remove This Entry\"/> </td></tr>"); .append("\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")) - .append("\"/> </td></tr>"); + .append("\"><span class=\"glyphicon glyphicon-trash\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.remove")+"</button>"); } else if (repeatable && !readonly && j == fieldCount - 1) { // put a 'more' button next to the last space - sb.append("<td><input type=\"submit\" name=\"submit_") + sb.append("<button class=\"btn btn-default col-md-2\" name=\"submit_") .append(fieldName) // .append("_add\" value=\"Add More\"/> </td></tr>"); .append("_add\" value=\"") .append(LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")) - .append("\"/> </td></tr>"); - } - else - { - // put a blank if nothing else - sb.append("<td> </td></tr>"); + .append("\"><span class=\"glyphicon glyphicon-plus\"></span> "+LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.edit-metadata.button.add")+"</button>"); } - } + // put a blank if nothing else + sb.append("</div>"); + } + sb.append("</div></div><br/>"); out.write(sb.toString()); } void doDropDown(javax.servlet.jsp.JspWriter out, Item item, String fieldName, String schema, String element, String qualifier, boolean repeatable, - boolean readonly, List valueList, String label) + boolean required, boolean readonly, List valueList, String label) throws java.io.IOException { DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY); @@ -1037,12 +1004,12 @@ String display, value; int j; - sb.append("<tr><td class=\"submitFormLabel\">") + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">") .append(label) - .append("</td>"); + .append("</label>"); - sb.append("<td colspan=\"2\">") - .append("<select name=\"") + sb.append("<span class=\"col-md-8\">") + .append("<select class=\"form-control\" name=\"") .append(fieldName) .append("\""); if (repeatable) @@ -1071,27 +1038,28 @@ .append("</option>"); } - sb.append("</select></td></tr>"); + sb.append("</select></span></div><br/>"); out.write(sb.toString()); } void doChoiceSelect(javax.servlet.jsp.JspWriter out, PageContext pageContext, Item item, - String fieldName, String schema, String element, String qualifier, boolean repeatable, + String fieldName, String schema, String element, String qualifier, boolean repeatable, boolean required, boolean readonly, List valueList, String label, int collectionID) throws java.io.IOException { DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY); StringBuffer sb = new StringBuffer(); - sb.append("<tr><td class=\"submitFormLabel\">") - .append(label) - .append("</td>"); - sb.append("<td colspan=\"2\">") + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">") + .append(label) + .append("</label>"); + + sb.append("<span class=\"col-md-8\">") .append(doAuthority(pageContext, fieldName, 0, defaults.length, fieldName, null, Choices.CF_UNSET, false, repeatable, defaults, null, collectionID)) - .append("</td></tr>"); + .append("</span></div><br/>"); out.write(sb.toString()); } @@ -1100,7 +1068,7 @@ /** Display Checkboxes or Radio buttons, depending on if repeatable! **/ void doList(javax.servlet.jsp.JspWriter out, Item item, String fieldName, String schema, String element, String qualifier, boolean repeatable, - boolean readonly, List valueList, String label) + boolean required,boolean readonly, List valueList, String label) throws java.io.IOException { DCValue[] defaults = item.getMetadata(schema, element, qualifier, Item.ANY); @@ -1116,34 +1084,41 @@ numColumns = 2; //print out the field label - sb.append("<tr><td class=\"submitFormLabel\">") - .append(label) - .append("</td>"); - + sb.append("<div class=\"row\"><label class=\"col-md-2"+ (required?" label-required":"") +"\">") + .append(label) + .append("</label>"); + + sb.append("<div class=\"col-md-10\">"); + if(numColumns > 1) - sb.append("<td valign=\"top\">"); + sb.append("<div class=\"row col-md-"+(12 / numColumns)+"\">"); else - sb.append("<td valign=\"top\" colspan=\"3\">"); - + sb.append("<div class=\"row col-md-12\">"); + //flag that lets us know when we are in Column2 boolean inColumn2 = false; //loop through all values for (int i = 0; i < valueList.size(); i += 2) { - //get display value and actual value - display = (String)valueList.get(i); + //get display value and actual value + display = (String)valueList.get(i); value = (String)valueList.get(i+1); + boolean checked = false; //check if this value has been selected previously for (j = 0; j < defaults.length; j++) { if (value.equals(defaults[j].value)) - break; - } + { + checked = true; + break; + } + } - // print input field - sb.append("<input type=\""); + // print input field + sb.append("<div class=\"input-group\"><span class=\"input-group-addon\">"); + sb.append("<input type=\""); //if repeatable, print a Checkbox, otherwise print Radio buttons if(repeatable) @@ -1161,25 +1136,26 @@ .append(" value=\"") .append(value.replaceAll("\"", """)) .append("\">"); + sb.append("</span>"); //print display name immediately after input - sb.append(" ") + sb.append("<span class=\"form-control\">") .append(display) - .append("<br/>"); + .append("</span></div>"); // if we are writing values in two columns, // then start column 2 after half of the values if((numColumns == 2) && (i+2 >= (valueList.size()/2)) && !inColumn2) { //end first column, start second column - sb.append("</td>"); - sb.append("<td colspan=\"2\" valign=\"top\">"); + sb.append("</div>"); + sb.append("<div class=\"row col-md-"+(12 / numColumns)+"\">"); inColumn2 = true; } }//end for each value - sb.append("</td></tr>"); + sb.append("</div></div></div><br/>"); out.write(sb.toString()); }//end doList @@ -1218,7 +1194,13 @@ } %> -<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.edit-metadata.title"> +<c:set var="dspace.layout.head.last" scope="request"> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/prototype.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/effects.js"></script> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/controls.js"></script> +</c:set> +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.edit-metadata.title"> <% contextPath = request.getContextPath(); @@ -1230,33 +1212,41 @@ <jsp:include page="/submit/progressbar.jsp"></jsp:include> - <h1><fmt:message key="jsp.submit.edit-metadata.heading"/></h1> - + <h1><fmt:message key="jsp.submit.edit-metadata.heading"/> <% //figure out which help page to display if (pageNum <= 1) { %> - <div><fmt:message key="jsp.submit.edit-metadata.info1"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#describe2\"%>"><fmt:message key="jsp.submit.edit-metadata.help"/></dspace:popup></div> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#describe2\"%>"><fmt:message key="jsp.submit.edit-metadata.help"/></dspace:popup> <% } else { %> - <div><fmt:message key="jsp.submit.edit-metadata.info2"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#describe3\"%>"><fmt:message key="jsp.submit.edit-metadata.help"/></dspace:popup></div> - + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#describe3\"%>"><fmt:message key="jsp.submit.edit-metadata.help"/></dspace:popup> <% } %> + </h1> - <%-- HACK: a <center> tag seems to be the only way to convince certain --%> - <%-- browsers to center the table. --%> - <center> - <table> <% - int pageIdx = pageNum - 1; + //figure out which help page to display + if (pageNum <= 1) + { +%> + <p><fmt:message key="jsp.submit.edit-metadata.info1"/></p> +<% + } + else + { +%> + <p><fmt:message key="jsp.submit.edit-metadata.info2"/></p> + +<% + } + + int pageIdx = pageNum - 1; DCInput[] inputs = inputSet.getPageRows(pageIdx, si.getSubmissionItem().hasMultipleTitles(), si.getSubmissionItem().isPublishedBefore() ); for (int z = 0; z < inputs.length; z++) @@ -1289,9 +1279,10 @@ int fieldCountIncr; boolean repeatable; String vocabulary; - + boolean required; + vocabulary = inputs[z].getVocabulary(); - + required = inputs[z].isRequired(); if (dcQualifier != null && !dcQualifier.equals("*")) fieldName = dcSchema + "_" + dcElement + '_' + dcQualifier; @@ -1306,23 +1297,33 @@ if(si.getJumpToField()==null || si.getJumpToField().length()==0) si.setJumpToField(fieldName); - String req = "<tr><td colspan=\"4\" class=\"submitFormWarn\">" + + String req = "<div class=\"alert alert-warning\">" + inputs[z].getWarning() + - "<a name=\""+fieldName+"\"></a></td></tr>"; + "<a name=\""+fieldName+"\"></a></div>"; out.write(req); - } + } } else { //print out hints, if not null if(inputs[z].getHints() != null) { - String hints = "<tr><td colspan=\"4\" class=\"submitFormHelp\">" + - inputs[z].getHints() + - "</td></tr>"; - - out.write(hints); - } + %> + <div class="help-block"> + <%= inputs[z].getHints() %> + <% + if (hasVocabulary(vocabulary) && !readonly) + { + %> + <span class="pull-right"> + <dspace:popup page="/help/index.html#controlledvocabulary"><fmt:message key="jsp.controlledvocabulary.controlledvocabulary.help-link"/></dspace:popup> + </span> + <% + } + %> + </div> + <% + } } repeatable = inputs[z].getRepeatable(); @@ -1343,111 +1344,77 @@ if (inputType.equals("name")) { doPersonalName(out, item, fieldName, dcSchema, dcElement, dcQualifier, - repeatable, readonly, fieldCountIncr, label, pageContext, collectionID); + repeatable, required, readonly, fieldCountIncr, label, pageContext, collectionID); } else if (isSelectable(fieldName)) { doChoiceSelect(out, pageContext, item, fieldName, dcSchema, dcElement, dcQualifier, - repeatable, readonly, inputs[z].getPairs(), label, collectionID); + repeatable, required, readonly, inputs[z].getPairs(), label, collectionID); } else if (inputType.equals("date")) { doDate(out, item, fieldName, dcSchema, dcElement, dcQualifier, - repeatable, readonly, fieldCountIncr, label, pageContext, request); + repeatable, required, readonly, fieldCountIncr, label, pageContext, request); } else if (inputType.equals("series")) { doSeriesNumber(out, item, fieldName, dcSchema, dcElement, dcQualifier, - repeatable, readonly, fieldCountIncr, label, pageContext); + repeatable, required, readonly, fieldCountIncr, label, pageContext); } else if (inputType.equals("qualdrop_value")) { - doQualdropValue(out, item, fieldName, dcSchema, dcElement, inputSet, repeatable, + doQualdropValue(out, item, fieldName, dcSchema, dcElement, inputSet, repeatable, required, readonly, fieldCountIncr, inputs[z].getPairs(), label, pageContext); } else if (inputType.equals("textarea")) { doTextArea(out, item, fieldName, dcSchema, dcElement, dcQualifier, - repeatable, readonly, fieldCountIncr, label, pageContext, vocabulary, + repeatable, required, readonly, fieldCountIncr, label, pageContext, vocabulary, closedVocabulary, collectionID); } else if (inputType.equals("dropdown")) { doDropDown(out, item, fieldName, dcSchema, dcElement, dcQualifier, - repeatable, readonly, inputs[z].getPairs(), label); + repeatable, required, readonly, inputs[z].getPairs(), label); } else if (inputType.equals("twobox")) { doTwoBox(out, item, fieldName, dcSchema, dcElement, dcQualifier, - repeatable, readonly, fieldCountIncr, label, pageContext, vocabulary, - closedVocabulary); + repeatable, required, readonly, fieldCountIncr, label, pageContext, + vocabulary, closedVocabulary); } else if (inputType.equals("list")) { doList(out, item, fieldName, dcSchema, dcElement, dcQualifier, - repeatable, readonly, inputs[z].getPairs(), label); + repeatable, required, readonly, inputs[z].getPairs(), label); } else { doOneBox(out, item, fieldName, dcSchema, dcElement, dcQualifier, - repeatable, readonly, fieldCountIncr, label, pageContext, vocabulary, + repeatable, required, readonly, fieldCountIncr, label, pageContext, vocabulary, closedVocabulary, collectionID); } - if (hasVocabulary(vocabulary) && !readonly) - { -%> - - <tr> - <td> </td> - <td colspan="3" class="submitFormHelpControlledVocabularies"> - <dspace:popup page="/help/index.html#controlledvocabulary"><fmt:message key="jsp.controlledvocabulary.controlledvocabulary.help-link"/></dspace:popup> - </td> - </tr> - -<% - } -%> -<%-- HACK: Using this line to give the browser hints as to the widths of cells --%> - <tr> - <td width="40%"> </td> - <td colspan="2" width="5%"> </td> - <td width="40%"> </td> - </tr> - -<% } // end of 'for rows' %> - </table> - </center> -<%-- HACK: Need a space - is there a nicer way to do this than <BR> or a --%> -<%-- blank <P>? --%> - <p> </p> - <%-- Hidden fields needed for SubmissionController servlet to know which item to deal with --%> <%= SubmissionController.getSubmissionParameters(context, request) %> - <center> - <table border="0" width="80%"> - <tr> - <td width="100%"> </td> - <% //if not first page & step, show "Previous" button - if(!(SubmissionController.isFirstStep(request, si) && pageNum<=1)) - { %> - <td> - <input type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.edit-metadata.previous"/>" /> - </td> - <% } %> - <td> - <input type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.edit-metadata.next"/>"/> - </td> - <td> </td> - <td align="right"> - <input type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.edit-metadata.cancelsave"/>"/> - </td> - </tr> - </table> - </center> +<div class="row"> +<% //if not first page & step, show "Previous" button + if(!(SubmissionController.isFirstStep(request, si) && pageNum<=1)) + { %> + <div class="col-md-6 pull-right btn-group"> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.edit-metadata.previous"/>" /> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.edit-metadata.cancelsave"/>"/> + <input class="btn btn-primary col-md-4" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.edit-metadata.next"/>"/> + <% } else { %> + <div class="col-md-4 pull-right btn-group"> + <input class="btn btn-default col-md-6" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.edit-metadata.cancelsave"/>"/> + <input class="btn btn-primary col-md-6" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.edit-metadata.next"/>"/> + <% } %> + </div><br/> +</div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/get-file-format.jsp b/dspace-jspui/src/main/webapp/submit/get-file-format.jsp index 80923b305cdda365387e10577e36e9aa2a9292ec..2ac301a514ced716bde518148dde94f97c0dc062 100644 --- a/dspace-jspui/src/main/webapp/submit/get-file-format.jsp +++ b/dspace-jspui/src/main/webapp/submit/get-file-format.jsp @@ -53,14 +53,16 @@ Item item = subInfo.getSubmissionItem().getItem(); %> -<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.get-file-format.title" nocache="true"> +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.get-file-format.title" nocache="true"> <form action="<%= request.getContextPath() %>/submit" method="post" onkeydown="return disableEnterKey(event);"> <jsp:include page="/submit/progressbar.jsp"/> <%-- <h1>Submit: Select File Format</h1> --%> - <h1><fmt:message key="jsp.submit.get-file-format.heading"/></h1> + <h1><fmt:message key="jsp.submit.get-file-format.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#formats\" %>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p>Uploaded file: <code><%= si.bitstream.getName() %></code> (<%= si.bitstream.getSize() %> bytes)</p> --%> <p><fmt:message key="jsp.submit.get-file-format.info1"> @@ -73,7 +75,7 @@ { %> <%-- <p>DSpace could not identify the format of this file.</p> --%> - <p><fmt:message key="jsp.submit.get-file-format.info2"/></p> + <p class="alert alert-info"><fmt:message key="jsp.submit.get-file-format.info2"/></p> <% } else @@ -81,7 +83,7 @@ %> <%-- <p>DSpace recognized the file format as <%= guess.getShortDescription() %>. <strong>Please be sure before you change this!</strong></p> --%> - <p><fmt:message key="jsp.submit.get-file-format.info3"> + <p class="alert alert-info"><fmt:message key="jsp.submit.get-file-format.info3"> <fmt:param><%= guess.getShortDescription() %></fmt:param> </fmt:message></p> <input type="hidden" name="format" value="<%= guess.getID() %>" /> @@ -90,7 +92,7 @@ <%= SubmissionController.getSubmissionParameters(context, request) %> <%-- <p align="center"><input type="submit" name="submit" value="Choose automatically-recognized type"></p> --%> - <p align="center"><input type="submit" name="submit" value="<fmt:message key="jsp.submit.get-file-format.choose.button"/>" /></p> + <p align="center"><input class="btn btn-default" type="submit" name="submit" value="<fmt:message key="jsp.submit.get-file-format.choose.button"/>" /></p> </form> <%-- Option list put in a separate form --%> @@ -101,14 +103,12 @@ <%-- <p>Select the format of the file from the list below, for example "Adobe PDF" or "Microsoft Word", <strong>OR</strong> if the format is not in the list, please describe - the format file in the input box below the list. - <dspace:popup page="/help/index.html#formats">(More Help...)</dspace:popup></p> --%> - - <div><fmt:message key="jsp.submit.get-file-format.info5"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#formats\" %>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> - - <center> - <select name="format" size="8"> + the format file in the input box below the list.</p> --%> + + <div><fmt:message key="jsp.submit.get-file-format.info5"/></div> + <div class="row"> + <span class="col-md-6"> + <select class="form-control" name="format" size="8"> <option value="-1" <%= subInfo.getBitstream().getFormat().getShortDescription().equals("Unknown") ? "selected=\"selected\"" : "" %>> <%-- Format Not in List --%> <fmt:message key="jsp.submit.get-file-format.info6"/> @@ -134,21 +134,16 @@ } %> </select> - </center> - + </span> <%-- <p class=submitFormHelp><strong>If the format is not in the above list</strong>, describe it in the format below. Enter the name of the application you used to create the file, and the version number of the application (for example, "ACMESoft SuperApp version 1.5").</p> --%> - <p class="submitFormHelp"><fmt:message key="jsp.submit.get-file-format.info7"/></p> + <div class="col-md-6"><p class="submitFormHelp alert alert-warning"><fmt:message key="jsp.submit.get-file-format.info7"/></p> - <table border="0" align="center"> - <tr> - <td class="submitFormLabel"> + <%-- File Format: --%> - <label for="tformat_description"><fmt:message key="jsp.submit.get-file-format.format"/></label> - </td> - <td> + <label for="tformat_description" class="col-md-3"><fmt:message key="jsp.submit.get-file-format.format"/></label> <% String desc = subInfo.getBitstream().getUserFormatDescription(); if (desc == null) @@ -156,15 +151,13 @@ desc = ""; } %> - <input type="text" name="format_description" id="tformat_description" size="40" value="<%= desc %>" /> - </td> - </tr> - </table> - + <span class="col-md-9"><input class="form-control" type="text" name="format_description" id="tformat_description" size="40" value="<%= desc %>" /></span> + </div> + </div><br/> <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> <%-- <center><p><input type="submit" name="submit" value="Set File Format"></p></center> --%> - <center><p><input type="submit" name="submit" value="<fmt:message key="jsp.submit.general.submit"/>" /></p></center> + <input class="btn btn-primary col-md-2 col-md-offset-5" type="submit" name="submit" value="<fmt:message key="jsp.submit.general.submit"/>" /> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/initial-questions.jsp b/dspace-jspui/src/main/webapp/submit/initial-questions.jsp index 080cddee35c25c6b7ab668564caed677ff90532f..55f3bc4f349edcef6c5947d547e5947b84cbc651 100644 --- a/dspace-jspui/src/main/webapp/submit/initial-questions.jsp +++ b/dspace-jspui/src/main/webapp/submit/initial-questions.jsp @@ -45,7 +45,8 @@ SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" + locbar="off" navbar="off" titlekey="jsp.submit.initial-questions.title" nocache="true"> @@ -55,114 +56,91 @@ <jsp:include page="/submit/progressbar.jsp" /> <%-- <h1>Submit: Describe Your Item</h1> --%> - <h1><fmt:message key="jsp.submit.initial-questions.heading"/></h1> + <h1><fmt:message key="jsp.submit.initial-questions.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#describe1\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p>Please check the boxes next to the statements that apply to your submission. <object><dspace:popup page="/help/index.html#describe1">(More Help...)</dspace:popup></object></p> --%> - <div><fmt:message key="jsp.submit.initial-questions.info" /> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#describe1\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <p><fmt:message key="jsp.submit.initial-questions.info" /></p> - <center> - <table class="miscTable"> <% // Don't display MultipleTitles if no such form box defined if (inputSet.isDefinedMultTitles()) { -%> - <tr class="oddRowOddCol"> - <td class="oddRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"><input type="checkbox" name="multiple_titles" value="true" <%= (subInfo.getSubmissionItem().hasMultipleTitles() ? "checked='checked'" : "") %> /></td> - <%-- <td class="submitFormLabel" nowrap>The item has more than one title, e.g. a translated title</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.submit.initial-questions.elem1"/></td> - </tr> - </table> - </td> - </tr> +%> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" name="multiple_titles" value="true" <%= (subInfo.getSubmissionItem().hasMultipleTitles() ? "checked='checked'" : "") %> /></td> + </span> + <label class="form-control" for="multiple_titles"><fmt:message key="jsp.submit.initial-questions.elem1"/></label> + </div> <% } // Don't display PublishedBefore if no form boxes defined if (inputSet.isDefinedPubBefore()) { %> - <tr class="evenRowOddCol"> - <td class="evenRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"><input type="checkbox" name="published_before" value="true" <%= (subInfo.getSubmissionItem().isPublishedBefore() ? "checked='checked'" : "") %> /></td> - <%-- <td class="submitFormLabel" nowrap>The item has been published or publicly distributed before</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.submit.initial-questions.elem2"/></td> - </tr> - </table> - </td> - </tr> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" type="checkbox" name="published_before" value="true" <%= (subInfo.getSubmissionItem().isPublishedBefore() ? "checked='checked'" : "") %> /></td> + </span> + <label class="form-control" for="published_before"><fmt:message key="jsp.submit.initial-questions.elem2"/></label> + </div> <% } // Don't display file or thesis questions in workflow mode if (!subInfo.isInWorkflow()) { %> - <tr class="oddRowOddCol"> - <td class="oddRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"><input type="checkbox" name="multiple_files" value="true" <%= (subInfo.getSubmissionItem().hasMultipleFiles() ? "checked='checked'" : "") %> /></td> - <%-- <td class="submitFormLabel" nowrap>The item consists of <em>more than one</em> file</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.submit.initial-questions.elem3"/></td> - </tr> - </table> - </td> - </tr> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" name="multiple_files" value="true" <%= (subInfo.getSubmissionItem().hasMultipleFiles() ? "checked='checked'" : "") %> /> + </span> + <label class="form-control" for="multiple_files"> + <fmt:message key="jsp.submit.initial-questions.elem3"/> + </label> + </div> <% if (ConfigurationManager.getBooleanProperty("webui.submit.blocktheses")) { %> - <tr class="evenRowOddCol"> - <td class="evenRowOddCol" align="left"> - <table border="0"> - <tr> - <td valign="top"><input type="checkbox" name="is_thesis" value="true"></td> - <%-- <td class="submitFormLabel" nowrap>The item is a thesis</td> --%> - <td class="submitFormLabel" nowrap="nowrap"><fmt:message key="jsp.submit.initial-questions.elem4"/></td> - </tr> - </table> - </td> - </tr> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" name="is_thesis" value="true"> + </span> + <label class="form-control" for="is_thesis"> + <fmt:message key="jsp.submit.initial-questions.elem4"/> + </label> + </div> <% } } %> - </table> - </center> - - <p> </p> - +<br/> <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> - <center> - <table border="0" width="80%"> - <tr> - <td width="100%"> </td> <% //if not first step, show "Previous" button if(!SubmissionController.isFirstStep(request, subInfo)) { %> - <td> - <input type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.general.previous"/>" /> - </td> - <% } %> - <td> - <input type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> - </td> - <td> </td> - <td align="right"> - <input type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> - </td> - </tr> - </table> - </center> + <div class="row"> + <div class="col-md-6 pull-right btn-group"> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.general.previous"/>" /> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> + <input class="btn btn-primary col-md-4" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> + </div> + </div> + + <% } else { %> + <div class="row"> + <div class="col-md-4 pull-right btn-group"> + <input class="btn btn-default col-md-6" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> + </div> + </div> + <% } %> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/license-rejected.jsp b/dspace-jspui/src/main/webapp/submit/license-rejected.jsp index 3f1812b44d9469b3bb01ef665ee9aed9eacb0e92..d0a7f5e2a06a7ec80e340b860c335b1ed0b605a2 100644 --- a/dspace-jspui/src/main/webapp/submit/license-rejected.jsp +++ b/dspace-jspui/src/main/webapp/submit/license-rejected.jsp @@ -20,7 +20,7 @@ <% request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.submit.license-rejected.title"> +<dspace:layout style="submission" navbar="off" locbar="off" titlekey="jsp.submit.license-rejected.title"> <%-- <h1>Submit: License Rejected</h1> --%> <h1><fmt:message key="jsp.submit.license-rejected.heading"/></h1> diff --git a/dspace-jspui/src/main/webapp/submit/progressbar.jsp b/dspace-jspui/src/main/webapp/submit/progressbar.jsp index 47388eb0feb53e20e10d927c790c5f1742789a31..f888856ceaca4bf26fe174d71a0222c8df06116d 100644 --- a/dspace-jspui/src/main/webapp/submit/progressbar.jsp +++ b/dspace-jspui/src/main/webapp/submit/progressbar.jsp @@ -68,9 +68,7 @@ %> <!--Progress Bar--> -<center> - <table class="submitProgressTable" border="0" cellspacing="0" cellpadding="0"> - <tr> +<div class="row container btn-group"> <% //get progress bar info, used to build progress bar HashMap progressBarInfo = (HashMap) subInfo.getProgressBarInfo(); @@ -110,14 +108,14 @@ { // Show "Complete" step as the current step %> - <td><input class="submitProgressButtonCurrent" disabled="disabled" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /></td> + <input class="submitProgressButtonCurrent btn btn-primary" disabled="disabled" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /> <% } else { // submission is completed, so cannot jump back to any steps %> - <td><input class="submitProgressButtonDone" disabled="disabled" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /></td> + <input class="submitProgressButtonDone btn btn-success" disabled="disabled" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /> <% } } @@ -125,32 +123,30 @@ else if((stepNum == currentStepConfig.getStepNumber()) && (pageNum == currentPage)) { %> - <td><input class="submitProgressButtonCurrent" disabled="disabled" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /></td> + <input class="submitProgressButtonCurrent btn btn-primary" disabled="disabled" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /> <% } else if(workflowMode) //if in workflow mode, can jump to any step/page { %> - <td><input class="submitProgressButtonDone" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /></td> + <input class="submitProgressButtonDone btn btn-success" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /> <% } //else if this step & page has been completed else if( (stepNum < stepReached) || ((stepNum == stepReached) && (pageNum <= pageReached)) ) { %> - <td><input class="submitProgressButtonDone" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /></td> + <input class="submitProgressButtonDone btn btn-info" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /> <% } else //else this is a step that has not been done, yet { // Stage hasn't been completed yet (can't be jumped to) %> - <td><input class="submitProgressButtonNotDone" disabled="disabled" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /></td> + <input class="submitProgressButtonNotDone btn btn-default" disabled="disabled" type="submit" name="<%=AbstractProcessingStep.PROGRESS_BAR_PREFIX + stepAndPage%>" value="<%=heading%>" /> <% } }//end while } %> - </tr> - </table> -</center> + </div> diff --git a/dspace-jspui/src/main/webapp/submit/review-init.jsp b/dspace-jspui/src/main/webapp/submit/review-init.jsp index 80a1ef46947ebcb13b42ea3bb267a2b25199d687..2d71da43b0ffe1a344d2778113c76bfc7caf3dcc 100644 --- a/dspace-jspui/src/main/webapp/submit/review-init.jsp +++ b/dspace-jspui/src/main/webapp/submit/review-init.jsp @@ -41,28 +41,20 @@ <%-- ====================================================== --%> <%-- INITIAL QUESTIONS --%> <%-- ====================================================== --%> - - <table> - <tr> - <td width="100%"> - <table> - <tr> - <td class="metadataFieldLabel"><fmt:message key="jsp.submit.review.init-question1"/></td> - <td class="metadataFieldValue"><%= (si.hasMultipleTitles() ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state1") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state2")) %></td> - </tr> - <tr> - <td class="metadataFieldLabel"><fmt:message key="jsp.submit.review.init-question2"/></td> - <td class="metadataFieldValue"><%= (si.isPublishedBefore() ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state1") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state2")) %></td> - </tr> - <tr> - <td class="metadataFieldLabel"><fmt:message key="jsp.submit.review.init-question3"/></td> - <td class="metadataFieldValue"><%= (si.hasMultipleFiles() ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state1") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state2")) %></td> - </tr> - </table> - </td> - <td valign="middle"> - <input type="submit" name="submit_jump_<%=stepJump%>" value="<fmt:message key="jsp.submit.review.button.correct"/>" /> - </td> - </tr> - </table> - + <div class="col-md-10"> + <div class="row"> + <span class="metadataFieldLabel col-md-4"><fmt:message key="jsp.submit.review.init-question1"/></span> + <span class="metadataFieldValue col-md-8"><%= (si.hasMultipleTitles() ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state1") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state2")) %></span> + </div> + <div class="row"> + <span class="metadataFieldLabel col-md-4"><fmt:message key="jsp.submit.review.init-question2"/></span> + <span class="metadataFieldValue col-md-8"><%= (si.isPublishedBefore() ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state1") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state2")) %></span> + </div> + <div class="row"> + <span class="metadataFieldLabel col-md-4"><fmt:message key="jsp.submit.review.init-question3"/></span> + <span class="metadataFieldValue col-md-8"><%= (si.hasMultipleFiles() ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state1") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.state2")) %></span> + </div> + </div> + <div class="col-md-2"> + <input class="btn btn-default" type="submit" name="submit_jump_<%=stepJump%>" value="<fmt:message key="jsp.submit.review.button.correct"/>" /> + </div> diff --git a/dspace-jspui/src/main/webapp/submit/review-metadata.jsp b/dspace-jspui/src/main/webapp/submit/review-metadata.jsp index 12b28975a19f53c38357416670e074d10a9a6d14..4f9e69a29cac86101c1d8789a611b9c5be9dd7a7 100644 --- a/dspace-jspui/src/main/webapp/submit/review-metadata.jsp +++ b/dspace-jspui/src/main/webapp/submit/review-metadata.jsp @@ -116,11 +116,11 @@ DCValue[] values; StringBuffer row = new StringBuffer(); - row.append("<tr>"); - row.append("<td width=\"40%\" class=\"metadataFieldLabel\">"); + row.append("<div class=\"row\">"); + row.append("<span class=\"metadataFieldLabel col-md-4 \">"); row.append(inputs[z].getLabel()); - row.append("</td>"); - row.append("<td width=\"60%\" class=\"metadataFieldValue\">"); + row.append("</span>"); + row.append("<span class=\"metadataFieldValue col-md-8\">"); if (inputType.equals("qualdrop_value")) { @@ -200,8 +200,8 @@ } } } - row.append("</td>"); - row.append("</tr>"); + row.append("</span>"); + row.append("</div>"); out.write(row.toString()); } @@ -212,18 +212,13 @@ <%-- DESCRIBE ITEM ELEMENTS --%> <%-- ====================================================== --%> -<%@page import="org.dspace.workflow.WorkflowItem"%><table width="100%"> - <tr> - <td width="100%"> - <table width="700px"> +<%@page import="org.dspace.workflow.WorkflowItem"%> +<div class="col-md-10"> <% layoutSection(request, out, inputSet, subInfo, item, pageNum, pageContext); %> - </table> - </td> - <td valign="middle"> - <input type="submit" name="submit_jump_<%=stepJump%>" value="<fmt:message key="jsp.submit.review.button.correct"/>" /> - </td> - </tr> - </table> +</div> +<div class="col-md-2"> + <input class="btn btn-default" type="submit" name="submit_jump_<%=stepJump%>" value="<fmt:message key="jsp.submit.review.button.correct"/>" /> +</div> diff --git a/dspace-jspui/src/main/webapp/submit/review-upload.jsp b/dspace-jspui/src/main/webapp/submit/review-upload.jsp index 4143b934568f1daf4ba03798dd6de59c14b48498..224ee64bde492ffd6f3e03afb362cb58a0c3943e 100644 --- a/dspace-jspui/src/main/webapp/submit/review-upload.jsp +++ b/dspace-jspui/src/main/webapp/submit/review-upload.jsp @@ -13,9 +13,12 @@ - Parameters to pass in to this page (from review.jsp) - submission.jump - the step and page number (e.g. stepNum.pageNum) to create a "jump-to" link --%> - <%@ page contentType="text/html;charset=UTF-8" %> +<%@page import="org.dspace.core.ConfigurationManager"%> +<%@page import="org.dspace.authorize.AuthorizeManager"%> +<%@page import="org.dspace.authorize.ResourcePolicy"%> +<%@page import="java.util.List"%> <%@ page import="org.dspace.app.webui.servlet.SubmissionController" %> <%@ page import="org.dspace.app.util.SubmissionInfo" %> <%@ page import="org.dspace.app.webui.util.UIUtil" %> @@ -40,24 +43,30 @@ //get submission information object SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); + + boolean advanced = ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); //get the step number (for jump-to link) String stepJump = (String) request.getParameter("submission.jump"); Item item = subInfo.getSubmissionItem().getItem(); + + //is advanced upload embargo step? + Object isUploadWithEmbargoB = request.getAttribute("submission.step.uploadwithembargo"); + boolean isUploadWithEmbargo = false; + if(isUploadWithEmbargoB!=null) { + isUploadWithEmbargo = (Boolean)isUploadWithEmbargoB; + } %> <%-- ====================================================== --%> <%-- UPLOADED_FILES --%> <%-- ====================================================== --%> - <table width="100%"> - <tr> - <td width="100%"> - <table> - <tr> - <td class="metadataFieldLabel"><%= (subInfo.getSubmissionItem().hasMultipleFiles() ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.upload1") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.upload2")) %></td> - <td class="metadataFieldValue"> +<div class="col-md-10"> + <div class="row"> + <span class="metadataFieldLabel col-md-4"><%= (subInfo.getSubmissionItem().hasMultipleFiles() ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.upload1") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.upload2")) %></span> + <span class="metadataFieldValue col-md-8"> <% Bitstream[] bitstreams = item.getNonInternalBitstreams(); @@ -87,8 +96,40 @@ case 2: %><fmt:message key="jsp.submit.review.supported"/><% } -%> - <br /> +%> +<% +if(isUploadWithEmbargo) { +List<ResourcePolicy> rpolicies = AuthorizeManager.findPoliciesByDSOAndType(context, bitstreams[i], ResourcePolicy.TYPE_CUSTOM); %> +<% if(rpolicies!=null && !rpolicies.isEmpty()) { %> + <% int countPolicies = 0; + //show information about policies setting only in the case of advanced embargo form + if(advanced) { + countPolicies = rpolicies.size(); + %> + <% if(countPolicies>0) { %> + <i class="label label-info"><fmt:message key="jsp.submit.review.policies.founded"><fmt:param><%= countPolicies %></fmt:param></fmt:message></i> + <% } %> + <% } else { %> + <% for(ResourcePolicy rpolicy : rpolicies) { + if(rpolicy.getStartDate()!=null) { + %> + <i class="label label-info"><fmt:message key="jsp.submit.review.policies.embargoed"><fmt:param><%= rpolicy.getStartDate() %></fmt:param></fmt:message></i> + <% + } + else { + %> + <i class="label label-success"><fmt:message key="jsp.submit.review.policies.openaccess"/></i> + <% + } + } + %> + + + <% } %> +<% } +} +%> +<br /> <% } } @@ -98,17 +139,16 @@ <% } %> - </td> - </tr> - </table> - </td> - <td valign="middle" align="right"> + </span> + </div> + </div> + <div class="col-md-2"> <% // Can't edit files in workflow mode if(!subInfo.isInWorkflow()) { %> - <input type="submit" name="submit_jump_<%=stepJump%>" + <input class="btn btn-default" type="submit" name="submit_jump_<%=stepJump%>" value="<%= (subInfo.getSubmissionItem().hasMultipleFiles() ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.button.upload1") : LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.review.button.upload2")) %>" /> <% } @@ -116,12 +156,9 @@ { %> - <input type="submit" name="submit_jump_<%=stepJump%>" + <input class="btn btn-default" type="submit" name="submit_jump_<%=stepJump%>" value="<fmt:message key="jsp.submit.review.button.edit"/>" /> <% } %> - </td> - </tr> - </table> - + </div> \ No newline at end of file diff --git a/dspace-jspui/src/main/webapp/submit/review.jsp b/dspace-jspui/src/main/webapp/submit/review.jsp index 2480b1bba1bafc5bf581522cc5f373a12409e9e8..ed2edcade756313760fe3972904bf11a8ab96df6 100644 --- a/dspace-jspui/src/main/webapp/submit/review.jsp +++ b/dspace-jspui/src/main/webapp/submit/review.jsp @@ -52,24 +52,24 @@ Iterator reviewIterator = reviewJSPs.keySet().iterator(); %> -<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.review.title" nocache="true"> +<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.review.title" style="submission" nocache="true"> <form action="<%= request.getContextPath() %>/submit" method="post" onkeydown="return disableEnterKey(event);"> <jsp:include page="/submit/progressbar.jsp" /> - <h1><fmt:message key="jsp.submit.review.heading"/></h1> + <h1><fmt:message key="jsp.submit.review.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#verify\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <p><fmt:message key="jsp.submit.review.info1"/></p> - <div><fmt:message key="jsp.submit.review.info2"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#verify\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <div class="alert alert-info"><fmt:message key="jsp.submit.review.info2"/></div> <p><fmt:message key="jsp.submit.review.info3"/></p> <p><fmt:message key="jsp.submit.review.info4"/></p> - - <table align="center" class="miscTable" width="80%"> + <div class="container"> <% //loop through the list of review JSPs while(reviewIterator.hasNext()) @@ -81,43 +81,26 @@ //finally get the path to the review JSP (the value) String reviewJSP = (String) reviewJSPs.get(stepAndPage); %> - <tr> - <td class="evenRowOddCol"> + <div class="well row"> <%--Load the review JSP and pass it step & page info--%> <jsp:include page="<%=reviewJSP%>"> <jsp:param name="submission.jump" value="<%=stepAndPage%>" /> </jsp:include> - </td> - </tr> + </div> <% } %> - </table> - + </div> <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> - <p> </p> - <center> - <table border="0" width="80%"> - <tr> - <td width="100%"> </td> - <td> - <input type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.review.button.previous"/>" /> - </td> - <td> - <input type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.review.button.next"/>" /> - </td> - <td> </td> - - <td align="right"> - <input type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.review.button.cancelsave"/>" /> - </td> - </tr> - </table> - </center> + <div class="col-md-6 pull-right btn-group"> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.review.button.previous"/>" /> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.review.button.cancelsave"/>" /> + <input class="btn btn-primary col-md-4" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.review.button.next"/>" /> + </div> </form> diff --git a/dspace-jspui/src/main/webapp/submit/saved.jsp b/dspace-jspui/src/main/webapp/submit/saved.jsp index 0dcde4aebd65dd3df378554adb8e324ed2b84af3..380fca47dc4d319dfd10f225d4c8136a01715a01 100644 --- a/dspace-jspui/src/main/webapp/submit/saved.jsp +++ b/dspace-jspui/src/main/webapp/submit/saved.jsp @@ -21,7 +21,7 @@ <% request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.saved.title"> +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.saved.title"> <%-- <h1>Submission Saved</h1> --%> <h1><fmt:message key="jsp.submit.saved.title"/></h1> @@ -29,7 +29,7 @@ <%-- <p>Your submission has been saved for you to finish later. You can continue the submission by going to your "My DSpace" page and clicking on the relevant "Resume" button.</p> --%> - <p><fmt:message key="jsp.submit.saved.info"/></p> + <p class="alert alert-info"><fmt:message key="jsp.submit.saved.info"/></p> <%-- <p><a href="<%= request.getContextPath() %>/mydspace">Go to My DSpace</a></p> --%> <p><a href="<%= request.getContextPath() %>/mydspace"><fmt:message key="jsp.mydspace.general.goto-mydspace"/></a></p> diff --git a/dspace-jspui/src/main/webapp/submit/select-collection.jsp b/dspace-jspui/src/main/webapp/submit/select-collection.jsp index 4806e897c82bc8923306a5e7a454f325dc9b4163..5b75fb4fbe3ad3e4c15f7615322965fbe5a3cbe2 100644 --- a/dspace-jspui/src/main/webapp/submit/select-collection.jsp +++ b/dspace-jspui/src/main/webapp/submit/select-collection.jsp @@ -43,44 +43,37 @@ Context context = UIUtil.obtainContext(request); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.select-collection.title" nocache="true"> - <h1><fmt:message key="jsp.submit.select-collection.heading"/></h1> + <h1><fmt:message key="jsp.submit.select-collection.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#choosecollection\"%>"><fmt:message key="jsp.morehelp"/> </dspace:popup></h1> <% if (collections.length > 0) { %> - <div><fmt:message key="jsp.submit.select-collection.info1"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#choosecollection\"%>"><fmt:message key="jsp.morehelp"/> </dspace:popup> - </div> + <p><fmt:message key="jsp.submit.select-collection.info1"/></p> <form action="<%= request.getContextPath() %>/submit" method="post" onkeydown="return disableEnterKey(event);"> -<%-- HACK: a <center> tag seems to be the only way to convince certain --%> -<%-- browsers to center the table. --%> - <center> - <table summary="Select collection table"> <% //if no collection was selected, display an error if((noCollection != null) && (noCollection.booleanValue()==true)) { %> - <tr> - <td colspan="2" class="submitFormWarn"><fmt:message key="jsp.submit.select-collection.no-collection"/></td> - </tr> + <div class="alert alert-warning"><fmt:message key="jsp.submit.select-collection.no-collection"/></div> <% } %> - <tr> - <%-- <td class="submitFormLabel"><label for="tcollection">Collection</label></td> --%> - <td class="submitFormLabel"><label for="tcollection"><fmt:message key="jsp.submit.select-collection.collection"/></label></td> - <td> - <select name="collection" id="tcollection"> - <option value="-1"></option> + <div class="input-group"> + <label for="tcollection" class="input-group-addon"> + <fmt:message key="jsp.submit.select-collection.collection"/> + </label> + <select class="form-control" name="collection" id="tcollection"> + <option value="-1"></option> <% for (int i = 0; i < collections.length; i++) { @@ -90,31 +83,19 @@ } %> </select> - </td> - </tr> - </table> + </div><br/> <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> - <br /> - - <table border="0" width="80%"> - <tr> - <td width="100%"> </td> - <td> - <%-- <input type="submit" name="submit_next" value="Next >"> --%> - <input type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> - </td> - <td> </td> - <td align="right"> - <%-- <input type="submit" name="submit_cancel" value="Cancel/Save"> --%> - <input type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.select-collection.cancel"/>" /> - </td> - </tr> - </table> - </center> + + <div class="row"> + <div class="col-md-4 pull-right btn-group"> + <input class="btn btn-default col-md-6" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.select-collection.cancel"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> + </div> + </div> </form> <% } else { %> - <p class="submitFormWarn"><fmt:message key="jsp.submit.select-collection.none-authorized"/></p> + <p class="alert alert-warning"><fmt:message key="jsp.submit.select-collection.none-authorized"/></p> <% } %> <p><fmt:message key="jsp.general.goto"/><br /> <a href="<%= request.getContextPath() %>"><fmt:message key="jsp.general.home"/></a><br /> diff --git a/dspace-jspui/src/main/webapp/submit/show-license.jsp b/dspace-jspui/src/main/webapp/submit/show-license.jsp index 19ac9b4a01a91a5aff2f6e7574206cb04ffd3783..04b83ab99f5f0a2af633cc0c071995377b28871d 100644 --- a/dspace-jspui/src/main/webapp/submit/show-license.jsp +++ b/dspace-jspui/src/main/webapp/submit/show-license.jsp @@ -40,7 +40,8 @@ String license = (String) request.getAttribute("license"); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" + locbar="off" navbar="off" titlekey="jsp.submit.show-license.title" nocache="true"> @@ -49,8 +50,9 @@ <jsp:include page="/submit/progressbar.jsp"/> - <div><fmt:message key="jsp.submit.show-license.info1"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") +\"#license\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <h1><fmt:message key="jsp.submit.show-license.title" /> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") +\"#license\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></h1> + <div class="alert alert-info"><fmt:message key="jsp.submit.show-license.info1"/></div> <%-- <p><strong>Not granting the license will not delete your submission.</strong> Your item will remain in your "My DSpace" page. You can then either remove @@ -58,20 +60,14 @@ queries you might have are resolved.</p> --%> <p><fmt:message key="jsp.submit.show-license.info2"/></p> - <table class="miscTable" align="center"> - <tr> - <td class="oddRowEvenCol"> - <pre><%= license %></pre> - </td> - </tr> - </table> + <pre class="panel panel-primary col-md-10 col-md-offset-1"><%= license %></pre> <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> - <center> - <p><input type="submit" name="submit_grant" value="<fmt:message key="jsp.submit.show-license.grant.button"/>" /></p> - <p><input type="submit" name="submit_reject" value="<fmt:message key="jsp.submit.show-license.notgrant.button"/>" /></p> - </center> + <div class="btn-group col-md-6 col-md-offset-3"> + <input class="btn btn-warning col-md-6" type="submit" name="submit_reject" value="<fmt:message key="jsp.submit.show-license.notgrant.button"/>" /> + <input class="btn btn-success col-md-6" type="submit" name="submit_grant" value="<fmt:message key="jsp.submit.show-license.grant.button"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/show-uploaded-file.jsp b/dspace-jspui/src/main/webapp/submit/show-uploaded-file.jsp index af49daafde1b1164e128297e52a792d3b8ce6598..67ac4849c1587216aa0eb43807495f2b5727ca18 100644 --- a/dspace-jspui/src/main/webapp/submit/show-uploaded-file.jsp +++ b/dspace-jspui/src/main/webapp/submit/show-uploaded-file.jsp @@ -26,13 +26,19 @@ <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="java.util.List" %> +<%@ page import="org.apache.commons.lang.time.DateFormatUtils" %> +<%@ page import="org.dspace.content.Bitstream" %> <%@ page import="org.dspace.core.Context" %> <%@ page import="org.dspace.app.webui.servlet.SubmissionController" %> +<%@ page import="org.dspace.authorize.AuthorizeManager" %> +<%@ page import="org.dspace.authorize.ResourcePolicy" %> <%@ page import="org.dspace.submit.AbstractProcessingStep" %> <%@ page import="org.dspace.app.util.SubmissionInfo" %> <%@ page import="org.dspace.app.webui.util.UIUtil" %> <%@ page import="org.dspace.content.Bitstream" %> <%@ page import="org.dspace.content.BitstreamFormat" %> +<%@ page import="org.dspace.content.Item" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> @@ -52,10 +58,13 @@ Bitstream[] all = subInfo.getSubmissionItem().getItem().getNonInternalBitstreams(); Bitstream bitstream = all[0]; BitstreamFormat format = bitstream.getFormat(); + + boolean withEmbargo = ((Boolean)request.getAttribute("with_embargo")).booleanValue(); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" + locbar="off" navbar="off" titlekey="jsp.submit.show-uploaded-file.title" nocache="true"> @@ -69,17 +78,20 @@ { %> <%-- <h1>Submit: File Uploaded Successfully</h1> --%> - <h1><fmt:message key="jsp.submit.show-uploaded-file.heading1"/></h1> + <h1><fmt:message key="jsp.submit.show-uploaded-file.heading1"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\")+ \"#uploadedfile\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></h1> <%-- <p><strong>Your file was successfully uploaded.</strong></p> --%> - <p><strong><fmt:message key="jsp.submit.show-uploaded-file.info1"/></strong></p> + <div class="alert aler-info"><fmt:message key="jsp.submit.show-uploaded-file.info1"/></div> <% } else { %> <%-- <h1>Submit: Uploaded File</h1> --%> - <h1><fmt:message key="jsp.submit.show-uploaded-file.heading2"/></h1> + <h1><fmt:message key="jsp.submit.show-uploaded-file.heading2"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\")+ \"#uploadedfile\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <% } %> @@ -87,10 +99,9 @@ details before going to the next step. <dspace:popup page="/help/index.html#uploadedfile">(More Help...)</dspace:popup></p> --%> - <div><fmt:message key="jsp.submit.show-uploaded-file.info2"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\")+ \"#uploadedfile\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <div><fmt:message key="jsp.submit.show-uploaded-file.info2"/></div> - <table class="miscTable" align="center"> + <table class="table"> <tr> <%-- <th class="oddRowOddCol">File</th> <th class="oddRowEvenCol">Size</th> @@ -111,7 +122,11 @@ %> </tr> <tr> - <td headers="t1" class="evenRowOddCol"><a href="<%= request.getContextPath() %>/retrieve/<%= bitstream.getID() %>/<%= org.dspace.app.webui.util.UIUtil.encodeBitstreamName(bitstream.getName()) %>" target="_blank"><%= bitstream.getName() %></a></td> + <td headers="t1" class="evenRowOddCol"> + <a href="<%= request.getContextPath() %>/retrieve/<%= bitstream.getID() %>/<%= org.dspace.app.webui.util.UIUtil.encodeBitstreamName(bitstream.getName()) %>" target="_blank"><%= bitstream.getName() %></a> + <%-- <input type="submit" name="submit_remove_<%= bitstream.getID() %>" value="Click here if this is the wrong file"> --%> + <input class="btn btn-danger pull-right" type="submit" name="submit_remove_<%= bitstream.getID() %>" value="<fmt:message key="jsp.submit.show-uploaded-file.click2.button"/>" /> + </td> <td headers="t2" class="evenRowEvenCol"><fmt:message key="jsp.submit.show-uploaded-file.size-in-bytes"> <fmt:param><fmt:formatNumber><%= bitstream.getSize() %></fmt:formatNumber></fmt:param> </fmt:message></td> @@ -130,6 +145,9 @@ { %> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.formats\") +\"#supported\"%>">(<fmt:message key="jsp.submit.show-uploaded-file.supported"/>)</dspace:popup> <% } %> + <%-- <input type="submit" name="submit_format_<%= bitstream.getID() %>" value="Click here if this is the wrong format" /> --%> + <input class="btn btn-default pull-right" type="submit" name="submit_format_<%= bitstream.getID() %>" value="<fmt:message key="jsp.submit.show-uploaded-file.click1.button"/>" /> + </td> <% if (showChecksums) @@ -144,21 +162,16 @@ </tr> </table> - <center> - - <p> - <%-- <input type="submit" name="submit_format_<%= bitstream.getID() %>" value="Click here if this is the wrong format" /> --%> - <input type="submit" name="submit_format_<%= bitstream.getID() %>" value="<fmt:message key="jsp.submit.show-uploaded-file.click1.button"/>" /> - </p> - </center> - - <center> - <p> - <%-- <input type="submit" name="submit_remove_<%= bitstream.getID() %>" value="Click here if this is the wrong file"> --%> - <input type="submit" name="submit_remove_<%= bitstream.getID() %>" value="<fmt:message key="jsp.submit.show-uploaded-file.click2.button"/>" /> - </p> - </center> - +<% + if (withEmbargo) + { +%> + <div class="row"> + <input class="btn btn-primary col-md-2 col-offset-5" type="submit" name="submit_editPolicy_<%= bitstream.getID() %>" value="<fmt:message key="jsp.submit.show-uploaded-file.click3.button"/>" /> + </div> +<% + } +%> <br/> <p class="uploadHelp"><fmt:message key="jsp.submit.show-uploaded-file.info3"/></p> @@ -176,7 +189,8 @@ { %> <li class="uploadHelp"><fmt:message key="jsp.submit.show-uploaded-file.info7"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#checksum\"%>"><fmt:message key="jsp.submit.show-uploaded-file.info8"/></dspace:popup><input type="submit" name="submit_show_checksums" value="<fmt:message key="jsp.submit.show-uploaded-file.show.button"/>" /></li> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#checksum\"%>"><fmt:message key="jsp.submit.show-uploaded-file.info8"/></dspace:popup> + <input class="btn btn-info" type="submit" name="submit_show_checksums" value="<fmt:message key="jsp.submit.show-uploaded-file.show.button"/>" /></li> <% } %> @@ -187,30 +201,21 @@ <%= SubmissionController.getSubmissionParameters(context, request) %> <%-- HACK: Center used to align table; CSS and align="center" ignored by some browsers --%> - <center> - <table border="0" width="80%"> - <tr> - <td width="100%"> </td> + <% //if not first step, show "Previous" button if(!SubmissionController.isFirstStep(request, subInfo)) { %> - <td> - <%-- <input type="submit" name="submit_prev" value="< Previous"> --%> - <input type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.general.previous"/>" /> - </td> - <% } %> - <td> - <%-- <input type="submit" name="submit_next value="Next >"> --%> - <input type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> - </td> - <td> </td> - <td align="right"> - <%-- <input type="submit" name="submit_cancel" value="Cancel/Save"> --%> - <input type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> - </td> - </tr> - </table> - </center> + <div class="col-md-6 pull-right btn-group"> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.general.previous"/>" /> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> + <input class="btn btn-primary col-md-4" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> + + <% } else { %> + <div class="col-md-4 pull-right btn-group"> + <input class="btn btn-default col-md-6" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> + <% } %> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/upload-error.jsp b/dspace-jspui/src/main/webapp/submit/upload-error.jsp index af001bac7015143f298f938a874b03fd41d8e8b5..4fde427b61e2ed64b6f31b1a801b9e4f0306c6de 100644 --- a/dspace-jspui/src/main/webapp/submit/upload-error.jsp +++ b/dspace-jspui/src/main/webapp/submit/upload-error.jsp @@ -42,7 +42,7 @@ SubmissionInfo subInfo = SubmissionController.getSubmissionInfo(context, request); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.upload-error.title" nocache="true"> @@ -57,17 +57,15 @@ <%-- <p>There was a problem uploading your file. Either the filename you entered was incorrect, or there was a network problem which prevented the file from reaching us correctly. Please try again.</p> --%> - <p><fmt:message key="jsp.submit.upload-error.info"/></p> + <p class="alert alert-warning"><fmt:message key="jsp.submit.upload-error.info"/></p> <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> <%-- HACK: <center> tag needed for broken Netscape 4.78 behaviour --%> - <center> - <p> - <input type="submit" name="submit_retry" value="<fmt:message key="jsp.submit.upload-error.retry.button"/>" /> - </p> - </center> + + <input class="btn btn-primary col-md-offset-5" type="submit" name="submit_retry" value="<fmt:message key="jsp.submit.upload-error.retry.button"/>" /> + </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/submit/upload-file-list.jsp b/dspace-jspui/src/main/webapp/submit/upload-file-list.jsp index 0f8ec335e38826ef67ac314be6cde892e006311f..69f04d60ec1d32ddadbf990acbc023db989bd66d 100644 --- a/dspace-jspui/src/main/webapp/submit/upload-file-list.jsp +++ b/dspace-jspui/src/main/webapp/submit/upload-file-list.jsp @@ -23,11 +23,15 @@ <%@ page import="javax.servlet.jsp.jstl.fmt.LocaleSupport" %> +<%@ page import="java.util.List" %> +<%@ page import="org.apache.commons.lang.time.DateFormatUtils" %> <%@ page import="org.dspace.core.Context" %> <%@ page import="org.dspace.app.webui.servlet.SubmissionController" %> +<%@ page import="org.dspace.authorize.AuthorizeManager" %> <%@ page import="org.dspace.submit.AbstractProcessingStep" %> <%@ page import="org.dspace.app.util.SubmissionInfo" %> <%@ page import="org.dspace.app.webui.util.UIUtil" %> +<%@ page import="org.dspace.authorize.ResourcePolicy" %> <%@ page import="org.dspace.content.Bitstream" %> <%@ page import="org.dspace.content.BitstreamFormat" %> <%@ page import="org.dspace.content.Bundle" %> @@ -48,9 +52,31 @@ request.setAttribute("LanguageSwitch", "hide"); boolean allowFileEditing = !subInfo.isInWorkflow() || ConfigurationManager.getBooleanProperty("workflow", "reviewer.file-edit"); + + boolean withEmbargo = ((Boolean)request.getAttribute("with_embargo")).booleanValue(); + + List<ResourcePolicy> policies = null; + String startDate = ""; + String globalReason = ""; + if (withEmbargo) + { + // Policies List + policies = AuthorizeManager.findPoliciesByDSOAndType(context, subInfo.getSubmissionItem().getItem(), ResourcePolicy.TYPE_CUSTOM); + + startDate = ""; + globalReason = ""; + if (policies.size() > 0) + { + startDate = (policies.get(0).getStartDate() != null ? DateFormatUtils.format(policies.get(0).getStartDate(), "yyyy-MM-dd") : ""); + globalReason = policies.get(0).getRpDescription(); + } + } + + boolean isAdvancedForm = ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); + %> -<dspace:layout locbar="off" navbar="off" titlekey="jsp.submit.upload-file-list.title"> +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.upload-file-list.title"> <form action="<%= request.getContextPath() %>/submit" method="post" onkeydown="return disableEnterKey(event);"> @@ -62,20 +88,24 @@ if (justUploaded) { %> - <h1><fmt:message key="jsp.submit.upload-file-list.heading1"/></h1> + <h1><fmt:message key="jsp.submit.upload-file-list.heading1"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#uploadedfile\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <p><fmt:message key="jsp.submit.upload-file-list.info1"/></p> <% } else { %> - <h1><fmt:message key="jsp.submit.upload-file-list.heading2"/></h1> + <h1><fmt:message key="jsp.submit.upload-file-list.heading2"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#uploadedfile\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <% } %> - <div><fmt:message key="jsp.submit.upload-file-list.info2"/> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#uploadedfile\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <div><fmt:message key="jsp.submit.upload-file-list.info2"/></div> - <table class="miscTable" align="center" summary="Table dispalying your submitted files"> + <table class="table" align="center" summary="Table dispalying your submitted files"> <tr> <th id="t1" class="oddRowEvenCol"><fmt:message key="jsp.submit.upload-file-list.tableheading1"/></th> <th id="t2" class="oddRowOddCol"><fmt:message key="jsp.submit.upload-file-list.tableheading2"/></th> @@ -83,23 +113,27 @@ <th id="t4" class="oddRowOddCol"><fmt:message key="jsp.submit.upload-file-list.tableheading4"/></th> <th id="t5" class="oddRowEvenCol"><fmt:message key="jsp.submit.upload-file-list.tableheading5"/></th> <% + String headerClass = "oddRowEvenCol"; + if (showChecksums) { + headerClass = (headerClass == "oddRowEvenCol" ? "oddRowOddCol" : "oddRowEvenCol"); %> - <th id="t6" class="oddRowOddCol"><fmt:message key="jsp.submit.upload-file-list.tableheading6"/></th> + <th id="t6" class="<%= headerClass %>"><fmt:message key="jsp.submit.upload-file-list.tableheading6"/></th> <% } - - // Don't display last column ("Remove") in workflow mode - if (allowFileEditing) + + if (withEmbargo) { - // Whether it's an odd or even column depends on whether we're showing checksums - String column = (showChecksums ? "Even" : "Odd"); + // Access Setting + headerClass = (headerClass == "oddRowEvenCol" ? "oddRowOddCol" : "oddRowEvenCol"); %> - <th id="t7" class="oddRow<%= column %>Col"> </th> + <th id="t7" class="<%= headerClass %>"><fmt:message key="jsp.submit.upload-file-list.tableheading7"/></th> + <% } + %> </tr> @@ -134,24 +168,39 @@ %> <tr> <td headers="t1" class="<%= row %>RowEvenCol" align="center"> - <input type="radio" name="primary_bitstream_id" value="<%= bitstreams[i].getID() %>" + <input class="form-control" type="radio" name="primary_bitstream_id" value="<%= bitstreams[i].getID() %>" <% if (bundles[0] != null) { if (bundles[0].getPrimaryBitstreamID() == bitstreams[i].getID()) { %> <%="checked='checked'" %> <% } } %> /> </td> - <td headers="t2" class="<%= row %>RowOddCol"><a href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[i].getID() %>/<%= org.dspace.app.webui.util.UIUtil.encodeBitstreamName(bitstreams[i].getName()) %>" target="_blank"><%= bitstreams[i].getName() %></a></td> + <td headers="t2" class="<%= row %>RowOddCol"> + <a href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[i].getID() %>/<%= org.dspace.app.webui.util.UIUtil.encodeBitstreamName(bitstreams[i].getName()) %>" target="_blank"><%= bitstreams[i].getName() %></a> + <% // Don't display "remove" button in workflow mode + if (allowFileEditing) + { + %> + <button class="btn btn-danger pull-right" type="submit" name="submit_remove_<%= bitstreams[i].getID() %>" value="<fmt:message key="jsp.submit.upload-file-list.button2"/>"> + <span class="glyphicon glyphicon-trash"></span> <fmt:message key="jsp.submit.upload-file-list.button2"/> + </button> + <% + } %> + </td> <td headers="t3" class="<%= row %>RowEvenCol"><%= bitstreams[i].getSize() %> bytes</td> <td headers="t4" class="<%= row %>RowOddCol"> <%= (bitstreams[i].getDescription() == null || bitstreams[i].getDescription().equals("") ? LocaleSupport.getLocalizedMessage(pageContext, "jsp.submit.upload-file-list.empty1") : bitstreams[i].getDescription()) %> - <input type="submit" name="submit_describe_<%= bitstreams[i].getID() %>" value="<fmt:message key="jsp.submit.upload-file-list.button1"/>" /> + <button type="submit" class="btn btn-default pull-right" name="submit_describe_<%= bitstreams[i].getID() %>" value="<fmt:message key="jsp.submit.upload-file-list.button1"/>"> + <span class="glyphicon glyphicon-pencil"></span> <fmt:message key="jsp.submit.upload-file-list.button1"/> + </button> </td> <td headers="t5" class="<%= row %>RowEvenCol"> <%= description %> <dspace:popup page="<%= supportLevelLink %>">(<%= supportLevel %>)</dspace:popup> - <input type="submit" name="submit_format_<%= bitstreams[i].getID() %>" value="<fmt:message key="jsp.submit.upload-file-list.button1"/>" /> + <button type="submit" class="btn btn-default pull-right" name="submit_format_<%= bitstreams[i].getID() %>" value="<fmt:message key="jsp.submit.upload-file-list.button1"/>"> + <span class="glyphicon glyphicon-file"></span> <fmt:message key="jsp.submit.upload-file-list.button1"/> + </button> </td> <% // Checksum @@ -164,14 +213,15 @@ <% } - // Don't display "remove" button in workflow mode - if (allowFileEditing) + String column = ""; + if (withEmbargo) { - // Whether it's an odd or even column depends on whether we're showing checksums - String column = (showChecksums ? "Even" : "Odd"); + column = (showChecksums ? "Even" : "Odd"); %> - <td headers="t7" class="<%= row %>Row<%= column %>Col"> - <input type="submit" name="submit_remove_<%= bitstreams[i].getID() %>" value="<fmt:message key="jsp.submit.upload-file-list.button2"/>" /> + <td headers="t6" class="<%= row %>Row<%= column %>Col" style="text-align:center"> + <button class="btn btn-default pull-left" type="submit" name="submit_editPolicy_<%= bitstreams[i].getID() %>" value="<fmt:message key="jsp.submit.upload-file-list.button1"/>"> + <span class="glyphicon glyphicon-lock"></span> <fmt:message key="jsp.submit.upload-file-list.button1"/> + </button> </td> <% } @@ -183,10 +233,16 @@ %> </table> -<%-- HACK: Need a space - is there a nicer way to do this than <br> or a --%> -<%-- blank <p>? --%> - <br /> - +<% + // Don't allow files to be added in workflow mode + if (allowFileEditing) + { +%> + <div class="row"><input class="btn btn-success col-md-2 col-md-offset-5" type="submit" name="submit_more" value="<fmt:message key="jsp.submit.upload-file-list.button4"/>" /></div> +<% + } +%> +<br/> <%-- Show information about how to verify correct upload, but not in workflow mode! --%> <% @@ -208,7 +264,8 @@ { %> <li class="uploadHelp"><fmt:message key="jsp.submit.upload-file-list.info6"/> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#checksum\"%>"><fmt:message key="jsp.submit.upload-file-list.help2"/></dspace:popup> <input type="submit" name="submit_show_checksums" value="<fmt:message key="jsp.submit.upload-file-list.button3"/>" /></li> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#checksum\"%>"><fmt:message key="jsp.submit.upload-file-list.help2"/></dspace:popup> + <input class="btn btn-info" type="submit" name="submit_show_checksums" value="<fmt:message key="jsp.submit.upload-file-list.button3"/>" /></li> <% } %> @@ -221,38 +278,21 @@ <%-- Hidden fields needed for SubmissionController servlet to know which step is next--%> <%= SubmissionController.getSubmissionParameters(context, request) %> -<%-- HACK: Center used to align table; CSS and align="center" ignored by some browsers --%> - <center> -<% - // Don't allow files to be added in workflow mode - if (allowFileEditing) - { -%> - <p><input type="submit" name="submit_more" value="<fmt:message key="jsp.submit.upload-file-list.button4"/>" /></p> -<% - } -%> - <table border="0" width="80%"> - <tr> - <td width="100%"> </td> - <% //if not first step, show "Previous" button - if(!SubmissionController.isFirstStep(request, subInfo)) - { %> - <td> - <%-- <input type="submit" name="submit_prev" value="< Previous"> --%> - <input type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.upload-file-list.button5"/>" /> - </td> - <% } %> - <td> - <input type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.upload-file-list.button6"/>" /> - </td> - <td> </td> - <td align="right"> - <input type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.upload-file-list.button7"/>" /> - </td> - </tr> - </table> - </center> + + <% //if not first step, show "Previous" button + if(!SubmissionController.isFirstStep(request, subInfo)) + { %> + <div class="col-md-6 pull-right btn-group"> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.PREVIOUS_BUTTON%>" value="<fmt:message key="jsp.submit.general.previous"/>" /> + <input class="btn btn-default col-md-4" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> + <input class="btn btn-primary col-md-4" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> + + <% } else { %> + <div class="col-md-4 pull-right btn-group"> + <input class="btn btn-default col-md-6" type="submit" name="<%=AbstractProcessingStep.CANCEL_BUTTON%>" value="<fmt:message key="jsp.submit.general.cancel-or-save.button"/>" /> + <input class="btn btn-primary col-md-6" type="submit" name="<%=AbstractProcessingStep.NEXT_BUTTON%>" value="<fmt:message key="jsp.submit.general.next"/>" /> + <% } %> + </div> </form> diff --git a/dspace-jspui/src/main/webapp/submit/verify-prune.jsp b/dspace-jspui/src/main/webapp/submit/verify-prune.jsp index 182a1bf700aad79425afa2271d96aabea29e8610..28fdbf22fb3c7c021466ff7e87248df0836070cb 100644 --- a/dspace-jspui/src/main/webapp/submit/verify-prune.jsp +++ b/dspace-jspui/src/main/webapp/submit/verify-prune.jsp @@ -50,7 +50,7 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout locbar="off" +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.submit.verify-prune.title" nocache="true"> @@ -119,17 +119,8 @@ <%-- Note: These submit buttons' names don't start with "submit", so the -- Previously passed in button will be picked up --%> - <center> - <table border="0" width="70%"> - <tr> - <td align="left"> - <input type="submit" name="prune" value="<fmt:message key="jsp.submit.verify-prune.proceed.button"/>" /> - </td> - <td align="right"> - <input type="submit" name="do_not_prune" value="<fmt:message key="jsp.submit.verify-prune.notproceed.button"/>" /> - </td> - </tr> - </table> - </center> + + <input class="btn btn-warning col-md-6" type="submit" name="prune" value="<fmt:message key="jsp.submit.verify-prune.proceed.button"/>" /> + <input class="btn btn-default col-md-6" type="submit" name="do_not_prune" value="<fmt:message key="jsp.submit.verify-prune.notproceed.button"/>" /> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/suggest/suggest.jsp b/dspace-jspui/src/main/webapp/suggest/suggest.jsp index d9ae75b2e681fe5f3addca1400ba4ec1672ffee5..999dc5d9487c2aa58f12d1797c4bcbe190a73fba 100644 --- a/dspace-jspui/src/main/webapp/suggest/suggest.jsp +++ b/dspace-jspui/src/main/webapp/suggest/suggest.jsp @@ -78,55 +78,52 @@ } %> -<dspace:layout locbar="off" navbar="off" titlekey="jsp.suggest.title"> +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.suggest.title"> <br/> <h1><fmt:message key="jsp.suggest.heading"/> <a href="<%= request.getContextPath() %>/handle/<%= handle %>"><%= title %></a> </h1> -<p><fmt:message key="jsp.suggest.invitation"/></p> +<p class="alert alert-info"><fmt:message key="jsp.suggest.invitation"/></p> <form name="form1" method="post" action=""> - <center> - <table> + <% if (problem) { %> - <tr> - <td class="submitFormWarn"><fmt:message key="jsp.suggest.warning"/></td> - </tr> + + <span class="alert alert-warning"><fmt:message key="jsp.suggest.warning"/></span> + <% } %> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.suggest.recipname"/></td> - <td><input type="text" name="recip_name" size="50" value="<%=StringEscapeUtils.escapeHtml(recip_name)%>" /></td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.suggest.recipemail"/></td> - <td><input type="text" name="recip_email" size="50" value="<%=StringEscapeUtils.escapeHtml(recip_email)%>"/></td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.suggest.sendername"/></td> - <td><input type="text" name="sender_name" size="50" value="<%=StringEscapeUtils.escapeHtml(sender_name)%>"/></td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.suggest.senderemail"/></td> - <td><input type="text" name="sender_email" size="50" value="<%=StringEscapeUtils.escapeHtml(sender_email)%>"/></td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.suggest.message"/></td> - <td><textarea name="message" rows="6" cols="46"><%=StringEscapeUtils.escapeHtml(message)%></textarea></td> - </tr> - - <tr> - <td colspan="2" align="center"> + <div class="form-group"><div class="input-group-addon"> + <span class="col-md-2"><label for="recip_name"><fmt:message key="jsp.suggest.recipname"/></label></span> + <span class="col-md-5"><input class="form-control" type="text" name="recip_name" size="50" value="<%=StringEscapeUtils.escapeHtml(recip_name)%>" /></span> + </div></div> + <div class="form-group"><div class="input-group-addon"> + <span class="col-md-2"><label for="recip_email"><fmt:message key="jsp.suggest.recipemail"/></label></span> + <span class="col-md-5"><input class="form-control" type="text" name="recip_email" size="50" value="<%=StringEscapeUtils.escapeHtml(recip_email)%>"/></span> + </div></div> + <div class="form-group"><div class="input-group-addon"> + <span class="col-md-2"><label for="sender_name"><fmt:message key="jsp.suggest.sendername"/></label></span> + <span class="col-md-5"><input class="form-control" type="text" name="sender_name" size="50" value="<%=StringEscapeUtils.escapeHtml(sender_name)%>"/></span> + </div></div> + <div class="form-group"><div class="input-group-addon"> + <span class="col-md-2"><label for="sender_email"><fmt:message key="jsp.suggest.senderemail"/></label></span> + <span class="col-md-5"><input class="form-control" type="text" name="sender_email" size="50" value="<%=StringEscapeUtils.escapeHtml(sender_email)%>"/></span> + </div></div> + <div class="form-group"><div class="input-group-addon"> + <span class="col-md-2"><label for="message"><fmt:message key="jsp.suggest.message"/></label></span> + <span class="col-md-5"><textarea class="form-control" name="message" rows="6" cols="46"><%=StringEscapeUtils.escapeHtml(message)%></textarea></span> + </div></div> + + <div class="btn-group"> <input type="hidden" name="handle" value='<%= handle %>'/> - <input type="submit" name="submit" value="<fmt:message key="jsp.suggest.button.send"/>" /> - <input type="button" name="cancel" onclick="window.close();" value="<fmt:message key="jsp.suggest.button.cancel"/>" /> - </td> - </tr> + <input class="btn btn-primary" type="submit" name="submit" value="<fmt:message key="jsp.suggest.button.send"/>" /> + <input class="btn btn-default" type="button" name="cancel" onclick="window.close();" value="<fmt:message key="jsp.suggest.button.cancel"/>" /> + </div> </table> </center> </form> diff --git a/dspace-jspui/src/main/webapp/suggest/suggest_ok.jsp b/dspace-jspui/src/main/webapp/suggest/suggest_ok.jsp index 2794733cd79b6b6f29c947756a86066a9b146673..5724306c179e1c63472c37d3fceb6fbfe301a381 100644 --- a/dspace-jspui/src/main/webapp/suggest/suggest_ok.jsp +++ b/dspace-jspui/src/main/webapp/suggest/suggest_ok.jsp @@ -16,12 +16,12 @@ <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> -<dspace:layout locbar="off" navbar="off" titlekey="jsp.suggestok.title"> +<dspace:layout style="submission" locbar="off" navbar="off" titlekey="jsp.suggestok.title"> <h1><fmt:message key="jsp.suggestok.heading"/></h1> <form action=""> - <input type="button" name="close" onclick="window.close();" value="<fmt:message key="jsp.suggestok.button.close"/>" /> + <input class="btn btn-primary" type="button" name="close" onclick="window.close();" value="<fmt:message key="jsp.suggestok.button.close"/>" /> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/confirm-delete-collection.jsp b/dspace-jspui/src/main/webapp/tools/confirm-delete-collection.jsp index b3006d3ae9e149681f6d4942731839ab3f0f3eb1..e486f08d3e1514fab438c4f525280a4c7275aa61 100644 --- a/dspace-jspui/src/main/webapp/tools/confirm-delete-collection.jsp +++ b/dspace-jspui/src/main/webapp/tools/confirm-delete-collection.jsp @@ -29,7 +29,7 @@ %> <dspace:layout titlekey="jsp.tools.confirm-delete-collection.title" - navbar="admin" + style="submission" navbar="admin" locbar="link" parentlink="/tools" parenttitlekey="jsp.administer"> @@ -56,17 +56,7 @@ <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="action" value="<%= EditCommunitiesServlet.CONFIRM_DELETE_COLLECTION %>" /> - <center> - <table width="70%"> - <tr> - <td align="left"> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.general.delete"/>"/> - </td> - <td align="right"> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.general.cancel"/>"/> - </td> - </tr> - </table> - </center> + <input class="btn btn-default col-md-2" type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.general.cancel"/>"/> + <input class="btn btn-danger col-md-2 pull-right" type="submit" name="submit" value="<fmt:message key="jsp.tools.general.delete"/>"/> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/confirm-delete-community.jsp b/dspace-jspui/src/main/webapp/tools/confirm-delete-community.jsp index b14e0e5dfb3e0a0bb66a0be78cef0f88fe77ddfd..b197c1b9aa9b40d00df0cb4e8c36c6ce45064663 100644 --- a/dspace-jspui/src/main/webapp/tools/confirm-delete-community.jsp +++ b/dspace-jspui/src/main/webapp/tools/confirm-delete-community.jsp @@ -26,7 +26,7 @@ Community community = (Community) request.getAttribute("community"); %> -<dspace:layout titlekey="jsp.tools.confirm-delete-community.title" +<dspace:layout style="submission" titlekey="jsp.tools.confirm-delete-community.title" navbar="admin" locbar="link" parentlink="/tools" @@ -53,17 +53,8 @@ <form method="post" action=""> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="action" value="<%= EditCommunitiesServlet.CONFIRM_DELETE_COMMUNITY %>" /> - <center> - <table width="70%"> - <tr> - <td align="left"> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.general.delete"/>"/> - </td> - <td align="right"> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.general.cancel"/>"/> - </td> - </tr> - </table> - </center> + + <input class="btn btn-default col-md-2" type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.general.cancel"/>"/> + <input class="btn btn-danger col-md-2 pull-right" type="submit" name="submit" value="<fmt:message key="jsp.tools.general.delete"/>"/> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/creative-commons-edit.jsp b/dspace-jspui/src/main/webapp/tools/creative-commons-edit.jsp index d49c8cba6a764dd5170cabda7b0f52456e1f9f19..7601c6c238ce20a5c720bb62cebb42b85a9160fb 100644 --- a/dspace-jspui/src/main/webapp/tools/creative-commons-edit.jsp +++ b/dspace-jspui/src/main/webapp/tools/creative-commons-edit.jsp @@ -56,7 +56,7 @@ <td> <h1><fmt:message key="jsp.tools.creative-commons-edit.heading1"/></h1> <form name="ccform" id="license_form" action="" method="get"> - <iframe src="http://creativecommons.org/license/?partner=dspace&stylesheet=<%= java.net.URLEncoder.encode(ssURL) %>&exit_url=<%= java.net.URLEncoder.encode(exitURL) %><%= jurisdiction %>" width="100%" height="540">Your browser must support IFrames to use this feature + <iframe src="http://creativecommons.org/license/?partner=dspace&stylesheet=<%= java.net.URLEncoder.encode(ssURL, "UTF-8") %>&exit_url=<%= java.net.URLEncoder.encode(exitURL, "UTF-8") %><%= jurisdiction %>" width="100%" height="540">Your browser must support IFrames to use this feature </iframe> <input type="hidden" name="item_id" value='<%=request.getParameter("item_id")%>' /> diff --git a/dspace-jspui/src/main/webapp/tools/edit-collection.jsp b/dspace-jspui/src/main/webapp/tools/edit-collection.jsp index 9f464c828aa14ac4cf81be81bfa03a96362af5e4..47964071ed17b8e6c1cb1a0ba21c3f34fd72e0b1 100644 --- a/dspace-jspui/src/main/webapp/tools/edit-collection.jsp +++ b/dspace-jspui/src/main/webapp/tools/edit-collection.jsp @@ -132,121 +132,114 @@ } %> -<dspace:layout titlekey="jsp.tools.edit-collection.title" +<dspace:layout style="submission" titlekey="jsp.tools.edit-collection.title" navbar="admin" locbar="link" parentlink="/dspace-admin" parenttitlekey="jsp.administer" nocache="true"> - +<div class="row"> +<h3 class="col-md-8"> <% if (collection == null) { %> - <h1><fmt:message key="jsp.tools.edit-collection.heading1"/></h1> + <fmt:message key="jsp.tools.edit-collection.heading1"/> <% } else { %> - <h1><fmt:message key="jsp.tools.edit-collection.heading2"> + <fmt:message key="jsp.tools.edit-collection.heading2"> <fmt:param><%= collection.getHandle() %></fmt:param> - </fmt:message> - </h1> - - <center> - <table width="70%"> - <tr> - <td class="standard"> + </fmt:message> +<% } %> + <span> + <dspace:popup page="/help/site-admin.html#editcollection"><fmt:message key="jsp.help"/></dspace:popup> + </span> + </h3> <% if(bDeleteButton) { %> - <form method="post" action=""> + <form class="col-md-4" method="post" action=""> <input type="hidden" name="action" value="<%= EditCommunitiesServlet.START_DELETE_COLLECTION %>" /> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="collection_id" value="<%= collection.getID() %>" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-collection.button.delete"/>" /> + <input class="btn btn-danger col-md-12" type="submit" name="submit_delete" value="<fmt:message key="jsp.tools.edit-collection.button.delete"/>" /> </form> -<% } else { %> - <% } %> - </td> - <td align="right" class="standard"> - <dspace:popup page="/help/site-admin.html#editcollection"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - </center> +</div> +<div class="row"> +<form class="form-group" method="post" action="<%= request.getContextPath() %>/tools/edit-communities"> + <div class="col-md-8"> -<% } %> - - <form method="post" action="<%= request.getContextPath() %>/tools/edit-communities"> - <table> <%-- =========================================================== Basic metadata =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label1"/></td> - <td><input type="text" name="name" value="<%= Utils.addEntities(name) %>" size="50" /></td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label2"/></td> - <td> - <input type="text" name="short_description" value="<%= Utils.addEntities(shortDesc) %>" size="50"/> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label3"/></td> - <td> - <textarea name="introductory_text" rows="6" cols="50"><%= Utils.addEntities(intro) %></textarea> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label4"/></td> - <td> - <textarea name="copyright_text" rows="6" cols="50"><%= Utils.addEntities(copy) %></textarea> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label5"/></td> - <td> - <textarea name="side_bar_text" rows="6" cols="50"><%= Utils.addEntities(side) %></textarea> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label6"/></td> - <td> - <textarea name="license" rows="6" cols="50"><%= Utils.addEntities(license) %></textarea> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label7"/></td> - <td> - <textarea name="provenance_description" rows="6" cols="50"><%= Utils.addEntities(provenance) %></textarea> - </td> - </tr> + <div class="panel panel-primary"> + <div class="panel-heading"><fmt:message key="jsp.tools.edit-collection.form.basic-metadata" /></div> + <div class="panel-body"> + <div class="row"> + <label class="col-md-3" for="name"><fmt:message key="jsp.tools.edit-collection.form.label1"/></label> + <span class="col-md-9"> + <input class="form-control" type="text" name="name" value="<%= Utils.addEntities(name) %>" /> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="short_description"><fmt:message key="jsp.tools.edit-collection.form.label2"/></label> + <span class="col-md-9"> + <input class="form-control" type="text" name="short_description" value="<%= Utils.addEntities(shortDesc) %>" size="50"/> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="introductory_text"><fmt:message key="jsp.tools.edit-collection.form.label3"/></label> + <span class="col-md-9"> + <textarea class="form-control" name="introductory_text" rows="6" cols="50"><%= Utils.addEntities(intro) %></textarea> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="copyright_text"><fmt:message key="jsp.tools.edit-collection.form.label4"/></label> + <span class="col-md-9"> + <textarea class="form-control" name="copyright_text" rows="6" cols="50"><%= Utils.addEntities(copy) %></textarea> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="side_bar_text"><fmt:message key="jsp.tools.edit-collection.form.label5"/></label> + <span class="col-md-9"> + <textarea class="form-control" name="side_bar_text" rows="6" cols="50"><%= Utils.addEntities(side) %></textarea> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="license"><fmt:message key="jsp.tools.edit-collection.form.label6"/></label> + <span class="col-md-9"> + <textarea class="form-control" name="license" rows="6" cols="50"><%= Utils.addEntities(license) %></textarea> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="provenance_description"><fmt:message key="jsp.tools.edit-collection.form.label7"/></label> + <span class="col-md-9"> + <textarea class="form-control" name="provenance_description" rows="6" cols="50"><%= Utils.addEntities(provenance) %></textarea> + </span> + </div><br/> <%-- =========================================================== Logo =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label8"/></td> - <td> + <div class="row"> + <label class="col-md-3" for=""><fmt:message key="jsp.tools.edit-collection.form.label8"/></label> + <div class="col-md-9"> <% if (logo != null) { %> - <table> - <tr> - <td> - <img src="<%= request.getContextPath() %>/retrieve/<%= logo.getID() %>" alt="collection logo"/> - </td> - <td> - <input type="submit" name="submit_set_logo" value="<fmt:message key="jsp.tools.edit-collection.form.button.add-logo"/>" /><br/><br/> - <input type="submit" name="submit_delete_logo" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete-logo"/>" /> - </td> - </tr> - </table> + <span class="col-md-6"> + <img class="img-responsive" src="<%= request.getContextPath() %>/retrieve/<%= logo.getID() %>" alt="collection logo"/> + </span> + <input class="btn btn-default col-md-3" type="submit" name="submit_set_logo" value="<fmt:message key="jsp.tools.edit-collection.form.button.add-logo"/>" /> + <input class="btn btn-danger col-md-3" type="submit" name="submit_delete_logo" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete-logo"/>" /> <% } else { %> - <input type="submit" name="submit_set_logo" value="<fmt:message key="jsp.tools.edit-collection.form.button.set-logo"/>" /> + <input class="col-md-12 btn btn-success" type="submit" name="submit_set_logo" value="<fmt:message key="jsp.tools.edit-collection.form.button.set-logo"/>" /> <% } %> - </td> - </tr> - - <tr><td> </td></tr> + </div> + </div> + </div> + </div> +</div> +<div class="col-md-4"> <% if(bSubmittersButton || bWorkflowsButton || bAdminCreateGroup || (admins != null && bAdminRemoveGroup)) { %> - <tr><td colspan="2"><center><h3><fmt:message key="jsp.tools.edit-collection.form.label9"/></h3></center></td></tr> + <div class="panel panel-default"><div class="panel-heading"><fmt:message key="jsp.tools.edit-collection.form.label9"/></div> + <div class="panel-body"> <% } @@ -254,17 +247,17 @@ <%-- =========================================================== Collection Submitters =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label10"/></td> - <td> + <div class="row"> + <label class="col-md-6" for="submit_submitters_create"><fmt:message key="jsp.tools.edit-collection.form.label10"/></label> + <span class="col-md-6 btn-group"> <% if (submitters == null) {%> - <input type="submit" name="submit_submitters_create" value="<fmt:message key="jsp.tools.edit-collection.form.button.create"/>" /> + <input class="btn btn-success col-md-12" type="submit" name="submit_submitters_create" value="<fmt:message key="jsp.tools.edit-collection.form.button.create"/>" /> <% } else { %> - <input type="submit" name="submit_submitters_edit" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> - <input type="submit" name="submit_submitters_delete" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete"/>" /> -<% } %> - </td> - </tr> + <input class="btn btn-default col-md-6" type="submit" name="submit_submitters_edit" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> + <input class="btn btn-danger col-md-6" type="submit" name="submit_submitters_delete" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete"/>" /> +<% } %> + </span> + </div><br/> <% } %> <% if(bWorkflowsButton) { %> @@ -280,92 +273,101 @@ }; for (int i = 0; i<3; i++) { %> - <tr> - <td class="submitFormLabel"><em><%= roleTexts[i] %></em> <fmt:message key="jsp.tools.edit-collection.form.label11"/></td> - <td> + <div class="row"> + <label class="col-md-6" for="submit_wf_create_<%= i + 1 %>"><em><%= roleTexts[i] %></em> <fmt:message key="jsp.tools.edit-collection.form.label11"/></label> + <span class="col-md-6 btn-group"> <% if (wfGroups[i] == null) { %> - <input type="submit" name="submit_wf_create_<%= i + 1 %>" value="<fmt:message key="jsp.tools.edit-collection.form.button.create"/>" /> + <input class="btn btn-success col-md-12" type="submit" name="submit_wf_create_<%= i + 1 %>" value="<fmt:message key="jsp.tools.edit-collection.form.button.create"/>" /> <% } else { %> - <input type="submit" name="submit_wf_edit_<%= i + 1 %>" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> - <input type="submit" name="submit_wf_delete_<%= i + 1 %>" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete"/>" /> + <input class="btn btn-default col-md-6" type="submit" name="submit_wf_edit_<%= i + 1 %>" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> + <input class="btn btn-danger col-md-6" type="submit" name="submit_wf_delete_<%= i + 1 %>" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete"/>" /> <% } %> - </td> - </tr> + </span> + </div><br/> <% } %> <% } %> - <tr><td> </td></tr> <% if(bAdminCreateGroup || (admins != null && bAdminRemoveGroup)) { %> <%-- =========================================================== Collection Administrators =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label12"/></td> - <td> + <div class="row"> + <label class="col-md-6" for="submit_admins_create"><fmt:message key="jsp.tools.edit-collection.form.label12"/></label> + <span class="col-md-6 btn-group"> <% if (admins == null) { if (bAdminCreateGroup) { %> - <input type="submit" name="submit_admins_create" value="<fmt:message key="jsp.tools.edit-collection.form.button.create"/>" /> + <input class="btn btn-success col-md-12" type="submit" name="submit_admins_create" value="<fmt:message key="jsp.tools.edit-collection.form.button.create"/>" /> <% } } else { if (bAdminCreateGroup) { %> - <input type="submit" name="submit_admins_edit" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> + <input class="btn btn-default" type="submit" name="submit_admins_edit" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> <% } if (bAdminRemoveGroup) { %> - <input type="submit" name="submit_admins_delete" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete"/>" /> + <input class="btn btn-danger" type="submit" name="submit_admins_delete" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete"/>" /> <% } - } %> - </td> - </tr> + } %> + </span> + </div> + </div> + </div> <% } %> - +<div class="panel panel-default"> + <div class="panel-heading"><fmt:message key="jsp.tools.edit-collection.form.collection-settings" /></div> + <div class="panel-body"> <% if(bTemplateButton) { %> + <div class="row"> <%-- =========================================================== Item template =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label13"/></td> - <td> + <label class="col-md-6" for="submit_create_template"><fmt:message key="jsp.tools.edit-collection.form.label13"/></label> + <span class="col-md-6 btn-group"> <% if (template == null) {%> - <input type="submit" name="submit_create_template" value="<fmt:message key="jsp.tools.edit-collection.form.button.create"/>" /> + <input class="btn btn-success col-md-12" type="submit" name="submit_create_template" value="<fmt:message key="jsp.tools.edit-collection.form.button.create"/>" /> <% } else { %> - <input type="submit" name="submit_edit_template" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> - <input type="submit" name="submit_delete_template" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete"/>" /> -<% } %> - </td> - </tr> + <input class="btn btn-default col-md-6" type="submit" name="submit_edit_template" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> + <input class="btn btn-default col-md-6" type="submit" name="submit_delete_template" value="<fmt:message key="jsp.tools.edit-collection.form.button.delete"/>" /> +<% } %> + </span> + </div><br/> <% } %> <% if(bPolicyButton) { %> <%-- =========================================================== Edit collection's policies =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label14"/></td> - <td> - <input type="submit" name="submit_authorization_edit" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> - </td> - </tr> + <div class="row"> + <label class="col-md-6" for="submit_authorization_edit"><fmt:message key="jsp.tools.edit-collection.form.label14"/></label> + <span class="col-md-6 btn-group"> + <input class="btn btn-success col-md-12" type="submit" name="submit_authorization_edit" value="<fmt:message key="jsp.tools.edit-collection.form.button.edit"/>" /> + </span> + </div><br/> <% } %> +<% if(bAdminCollection) { %> +<%-- =========================================================== + Curate collection + =========================================================== --%> + <div class="row"> + <label class="col-md-6" for=""><fmt:message key="jsp.tools.edit-collection.form.label27"/></label> + <span class="col-md-6 btn-group"> + <input class="btn btn-success col-md-12" type="submit" name="submit_curate_collection" value="<fmt:message key="jsp.tools.edit-collection.form.button.curate"/>" /> + </span> + </div> +<% } %> - - - - - - - + </div> + </div> <% if(bAdminCollection) { %> <%-- =========================================================== Harvesting Settings =========================================================== --%> - - <tr><td> </td></tr> - <tr><td colspan="2"><center><h3><fmt:message key="jsp.tools.edit-collection.form.label15"/></h3></center></td></tr> + <div class="panel panel-default"> + <div class="panel-heading"><fmt:message key="jsp.tools.edit-collection.form.label15"/></div> + <div class="panel-body"> <%-- oaiProviderValue = hc.getOaiSource(); @@ -379,25 +381,31 @@ lastHarvestMsg = "none"; --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label16"/></td> - <td> - <input type="radio" value="source_normal" <% if (harvestLevelValue == 0) { %> checked="checked" <% } %> name="source"><fmt:message key="jsp.tools.edit-collection.form.label17"/></input><br/> - <input type="radio" value="source_harvested" <% if (harvestLevelValue > 0) { %> checked="checked" <% } %> name="source"><fmt:message key="jsp.tools.edit-collection.form.label18"/></input><br/> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label19"/></td> - <td><input type="text" name="oai_provider" value="<%= oaiProviderValue %>" size="50" /></td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label20"/></td> - <td><input type="text" name="oai_setid" value="<%= oaiSetIdValue %>" size="50" /></td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label21"/></td> - <td> - <select name="metadata_format" > + <div class="input-group"> + <label class="input-group-addon" for="source_normal"><fmt:message key="jsp.tools.edit-collection.form.label16"/></label> + <div class="form-control"> + <input class="col-md-1" type="radio" value="source_normal" <% if (harvestLevelValue == 0) { %> checked="checked" <% } %> name="source" /> + <span class="col-md-11"><fmt:message key="jsp.tools.edit-collection.form.label17"/></span> + <input class="col-md-1" type="radio" value="source_harvested" <% if (harvestLevelValue > 0) { %> checked="checked" <% } %> name="source" /> + <span class="col-md-11"><fmt:message key="jsp.tools.edit-collection.form.label18"/></span> + </div> + </div><br/> + <div class="row"> + <label class="col-md-3" for="oai_provider"><fmt:message key="jsp.tools.edit-collection.form.label19"/></label> + <span class="col-md-9"> + <input class="form-control" type="text" name="oai_provider" value="<%= oaiProviderValue %>" size="50" /> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="oai_setid"><fmt:message key="jsp.tools.edit-collection.form.label20"/></label> + <span class="col-md-9"> + <input class="form-control" type="text" name="oai_setid" value="<%= oaiSetIdValue %>" size="50" /> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="metadata_format"><fmt:message key="jsp.tools.edit-collection.form.label21"/></label> + <span class="col-md-9"> + <select class="form-control" name="metadata_format" > <% // Add an entry for each instance of ingestion crosswalks configured for harvesting String metaString = "harvester.oai.metadataformats."; @@ -423,46 +431,35 @@ } %> </select> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label22"/></td> - <td> - <input type="radio" value="1" <% if (harvestLevelValue != 2 && harvestLevelValue != 3) { %> checked="checked" <% } %> name="harvest_level"><fmt:message key="jsp.tools.edit-collection.form.label23"/></input><br/> - <input type="radio" value="2" <% if (harvestLevelValue == 2) { %> checked="checked" <% } %> name="harvest_level"><fmt:message key="jsp.tools.edit-collection.form.label24"/></input><br/> - <input type="radio" value="3" <% if (harvestLevelValue == 3) { %> checked="checked" <% } %> name="harvest_level"><fmt:message key="jsp.tools.edit-collection.form.label25"/></input><br/> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-collection.form.label26"/></td> - <td><%= lastHarvestMsg %></td> - </tr> - <!-- - <tr> - <td class="submitFormLabel">Current Status</td> - <td> </td> - </tr> - --> - - + </span> + </div><br/> + <div class="input-group"> + <label class="input-group-addon" for="harvest_level"><fmt:message key="jsp.tools.edit-collection.form.label22"/></label> + <div class="form-control"> + <input class="col-md-1" type="radio" value="1" <% if (harvestLevelValue != 2 && harvestLevelValue != 3) { %> checked="checked" <% } %> name="harvest_level" /> + <span class="col-md-11"><fmt:message key="jsp.tools.edit-collection.form.label23"/></span><br/> + <input class="col-md-1" type="radio" value="2" <% if (harvestLevelValue == 2) { %> checked="checked" <% } %> name="harvest_level" /> + <span class="col-md-11"><fmt:message key="jsp.tools.edit-collection.form.label24"/></span><br/> + <input class="col-md-1" type="radio" value="3" <% if (harvestLevelValue == 3) { %> checked="checked" <% } %> name="harvest_level" /> + <span class="col-md-11"><fmt:message key="jsp.tools.edit-collection.form.label25"/></span><br/> + </div> + </div><br/> + <div class="row"> + <label class="col-md-6"><fmt:message key="jsp.tools.edit-collection.form.label26"/></label> + <span class="col-md-6"><%= lastHarvestMsg %></span> + </div> + </div> + </div> <% } %> - - - </table> - - <p> </p> - - <center> - <table width="70%"> - <tr> - <td class="standard"> +</div> +<div class="btn-group col-md-12"> <% if (collection == null) { %> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="create" value="true" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-collection.form.button.create2"/>" /> + <input class="btn btn-success col-md-6" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-collection.form.button.create2"/>" /> <% } else @@ -471,18 +468,14 @@ <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="collection_id" value="<%= collection.getID() %>" /> <input type="hidden" name="create" value="false" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-collection.form.button.update"/>" /> + <input class="btn btn-success col-md-6" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-collection.form.button.update"/>" /> <% } %> - </td> - <td> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="action" value="<%= EditCommunitiesServlet.CONFIRM_EDIT_COLLECTION %>" /> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.edit-collection.form.button.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-warning col-md-6" type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.edit-collection.form.button.cancel"/>" /> +</div> </form> -</dspace:layout> \ No newline at end of file + </div> +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/edit-community.jsp b/dspace-jspui/src/main/webapp/tools/edit-community.jsp index d7d6828b14aaf5a2dee148b205ed0dbf405b0a3a..9dfad876b0b2b5e6d8d6a5b9177d0bea50fb471f 100644 --- a/dspace-jspui/src/main/webapp/tools/edit-community.jsp +++ b/dspace-jspui/src/main/webapp/tools/edit-community.jsp @@ -48,6 +48,8 @@ Boolean delete = (Boolean)request.getAttribute("delete_button"); boolean bDelete = (delete == null ? false : delete.booleanValue()); + Boolean adminCommunity = (Boolean)request.getAttribute("admin_community"); + boolean bAdminCommunity = (adminCommunity == null ? false : adminCommunity.booleanValue()); String name = ""; String shortDesc = ""; String intro = ""; @@ -69,135 +71,134 @@ } %> -<dspace:layout titlekey="jsp.tools.edit-community.title" +<dspace:layout style="submission" titlekey="jsp.tools.edit-community.title" navbar="admin" locbar="link" parentlink="/dspace-admin" parenttitlekey="jsp.administer" nocache="true"> - <table width="95%"> - <tr> - <td align="left"> +<div class="row"> <% if (community == null) { %> - <h1><fmt:message key="jsp.tools.edit-community.heading1"/></h1> + <h3 class="col-md-12"><fmt:message key="jsp.tools.edit-community.heading1"/> + <span> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#editcommunity\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </span> + </h3> <% } else { %> - <h1><fmt:message key="jsp.tools.edit-community.heading2"> + <h3 class="col-md-8"><fmt:message key="jsp.tools.edit-community.heading2"> <fmt:param><%= community.getHandle() %></fmt:param> </fmt:message> - </h1> + <span> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#editcommunity\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </span> + </h3> <% if(bDelete) { %> - <center> - <table width="70%"> - <tr> - <td class="standard"> - <form method="post" action=""> + <form class="col-md-4" method="post" action=""> <input type="hidden" name="action" value="<%= EditCommunitiesServlet.START_DELETE_COMMUNITY %>" /> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-community.button.delete"/>" /> + <input class="col-md-12 btn btn-danger" type="submit" name="submit_delete" value="<fmt:message key="jsp.tools.edit-community.button.delete"/>" /> </form> - </td> - </tr> - </table> - </center> <% } %> <% } %> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#editcommunity\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - - <form method="post" action=""> - <table> +</div> + +<form method="post" action=""> +<div class="row"> + <div class="col-md-<%= community != null?"8":"12" %>"> + <div class="panel panel-primary"> + <div class="panel-heading"><fmt:message key="jsp.tools.edit-community.form.basic-metadata"/></div> + + <div class="panel-body"> <%-- =========================================================== Basic metadata =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-community.form.label1"/></td> - <td><input type="text" name="name" value="<%= Utils.addEntities(name) %>" size="50" /></td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-community.form.label2"/></td> - <td> - <input type="text" name="short_description" value="<%= Utils.addEntities(shortDesc) %>" size="50" /> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-community.form.label3"/></td> - <td> - <textarea name="introductory_text" rows="6" cols="50"><%= Utils.addEntities(intro) %></textarea> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-community.form.label4"/></td> - <td> - <textarea name="copyright_text" rows="6" cols="50"><%= Utils.addEntities(copy) %></textarea> - </td> - </tr> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-community.form.label5"/></td> - <td> - <textarea name="side_bar_text" rows="6" cols="50"><%= Utils.addEntities(side) %></textarea> - </td> - </tr> + <div class="row"> + <label for="name" class="col-md-3"><fmt:message key="jsp.tools.edit-community.form.label1"/></label> + <span class="col-md-9"><input class="form-control" type="text" name="name" value="<%= Utils.addEntities(name) %>" size="50" /></span> + </div><br/> + <div class="row"> + <label for="short_description" class="col-md-3"><fmt:message key="jsp.tools.edit-community.form.label2"/></label> + <span class="col-md-9"><input class="form-control" type="text" name="short_description" value="<%= Utils.addEntities(shortDesc) %>" size="50" /> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="introductory_text"><fmt:message key="jsp.tools.edit-community.form.label3"/></label> + <span class="col-md-9"><textarea class="form-control" name="introductory_text" rows="6" cols="50"><%= Utils.addEntities(intro) %></textarea> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3" for="copyright_text"><fmt:message key="jsp.tools.edit-community.form.label4"/></label> + <span class="col-md-9"> + <textarea class="form-control" name="copyright_text" rows="6" cols="50"><%= Utils.addEntities(copy) %></textarea> + </span> + </div><br/> + <div class="row"> + <label class="col-md-3"><fmt:message key="jsp.tools.edit-community.form.label5"/></label> + <span class="col-md-9"> + <textarea class="form-control" name="side_bar_text" rows="6" cols="50"><%= Utils.addEntities(side) %></textarea> + </span> + </div><br/> <%-- =========================================================== Logo =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-community.form.label6"/></td> - <td> + <div class="row"> + <label class="col-md-3"><fmt:message key="jsp.tools.edit-community.form.label6"/></label> + <div class="col-md-9"> + <% if (logo != null) { %> - <table> - <tr> - <td> - <img src="<%= request.getContextPath() %>/retrieve/<%= logo.getID() %>" alt="logo" /> - </td> - <td> - <input type="submit" name="submit_set_logo" value="<fmt:message key="jsp.tools.edit-community.form.button.add-logo"/>" /><br/><br/> - <input type="submit" name="submit_delete_logo" value="<fmt:message key="jsp.tools.edit-community.form.button.delete-logo"/>" /> - </td> - </tr> - </table> + <span class="col-md-6"> + <img class="img-responsive" src="<%= request.getContextPath() %>/retrieve/<%= logo.getID() %>" alt="logo" /> + </span> + <input class="col-md-3 btn btn-default" type="submit" name="submit_set_logo" value="<fmt:message key="jsp.tools.edit-community.form.button.add-logo"/>" /> + <input class="col-md-3 btn btn-danger" type="submit" name="submit_delete_logo" value="<fmt:message key="jsp.tools.edit-community.form.button.delete-logo"/>" /> <% } else { %> - <input type="submit" name="submit_set_logo" value="<fmt:message key="jsp.tools.edit-community.form.button.set-logo"/>" /> + <input class="col-md-12 btn btn-success" type="submit" name="submit_set_logo" value="<fmt:message key="jsp.tools.edit-community.form.button.set-logo"/>" /> <% } %> - </td> - </tr> - <% if(bAdminCreateGroup || (admins != null && bAdminRemoveGroup)) { %> + </div> + </div> + + </div> + </div> + </div> + <% if (community != null) { %> + <div class="col-md-4"> + <div class="panel panel-default"> + <div class="panel-heading"><fmt:message key="jsp.tools.edit-community.form.community-settings" /></div> + <div class="panel-body"> +<% if(bAdminCreateGroup || (admins != null && bAdminRemoveGroup)) { %> <%-- =========================================================== Community Administrators =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-community.form.label8"/></td> - <td> + <div class="row"> + <label class="col-md-6" for="submit_admins_create"><fmt:message key="jsp.tools.edit-community.form.label8"/></label> + <span class="col-md-6 btn-group"> <% if (admins == null) { if (bAdminCreateGroup) { %> - <input type="submit" name="submit_admins_create" value="<fmt:message key="jsp.tools.edit-community.form.button.create"/>" /> + <input class="btn btn-success col-md-12" type="submit" name="submit_admins_create" value="<fmt:message key="jsp.tools.edit-community.form.button.create"/>" /> <% } } else { if (bAdminCreateGroup) { %> - <input type="submit" name="submit_admins_edit" value="<fmt:message key="jsp.tools.edit-community.form.button.edit"/>" /> + <input class="btn btn-default col-md-6" type="submit" name="submit_admins_edit" value="<fmt:message key="jsp.tools.edit-community.form.button.edit"/>" /> <% } if (bAdminRemoveGroup) { %> - <input type="submit" name="submit_admins_remove" value="<fmt:message key="jsp.tools.edit-community.form.button.remove"/>" /> + <input class="btn btn-danger col-md-6" type="submit" name="submit_admins_remove" value="<fmt:message key="jsp.tools.edit-community.form.button.remove"/>" /> <% } } %> - </td> - </tr> + </span> + </div> <% } @@ -208,35 +209,45 @@ <%-- =========================================================== Edit community's policies =========================================================== --%> - <tr> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-community.form.label7"/></td> - <td> - <input type="submit" name="submit_authorization_edit" value="<fmt:message key="jsp.tools.edit-community.form.button.edit"/>" /> - </td> - </tr> - <% } %> - - </table> + <div class="row"> + <label class="col-md-6" for="submit_authorization_edit"><fmt:message key="jsp.tools.edit-community.form.label7"/></label> + <span class="col-md-6 btn-group"> + <input class="col-md-12 btn btn-success" type="submit" name="submit_authorization_edit" value="<fmt:message key="jsp.tools.edit-community.form.button.edit"/>" /> + </span> + </div> + <% } - <p> </p> + if (bAdminCommunity) { +%> +<%-- =========================================================== + Curate Community + =========================================================== --%> + <div class="row"> + <label for="submit_curate_community" class="col-md-6"><fmt:message key="jsp.tools.edit-community.form.label9"/></label> + <span class="col-md-6"> + <input class="col-md-12 btn btn-success" type="submit" name="submit_curate_community" value="<fmt:message key="jsp.tools.edit-community.form.button.curate"/>" /> + </span> + </div> + <% } %> + </div> + </div> +</div> +<% } %> +</div> - <center> - <table width="70%"> - <tr> - <td class="standard"> - +<div class="row"> +<div class="btn-group col-md-12"> <% if (community == null) { %> <input type="hidden" name="parent_community_id" value="<%= parentID %>" /> <input type="hidden" name="create" value="true" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-community.form.button.create"/>" /> - </td> - <td> + <input class="col-md-6 btn btn-success" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-community.form.button.create"/>" /> + <input type="hidden" name="parent_community_id" value="<%= parentID %>" /> <input type="hidden" name="action" value="<%= EditCommunitiesServlet.CONFIRM_EDIT_COMMUNITY %>" /> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.edit-community.form.button.cancel"/>" /> + <input class="col-md-6 btn btn-warning" type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.edit-community.form.button.cancel"/>" /> <% } else @@ -244,18 +255,15 @@ %> <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="create" value="false" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-community.form.button.update"/>" /> - </td> - <td> + <input class="col-md-6 btn btn-success" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-community.form.button.update"/>" /> + <input type="hidden" name="community_id" value="<%= community.getID() %>" /> <input type="hidden" name="action" value="<%= EditCommunitiesServlet.CONFIRM_EDIT_COMMUNITY %>" /> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.edit-community.form.button.cancel"/>" /> + <input class="col-md-6 btn btn-warning" type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.edit-community.form.button.cancel"/>" /> <% } %> - </td> - </tr> - </table> - </center> + </div> + </div> </form> -</dspace:layout> \ No newline at end of file +</dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/edit-item-form.jsp b/dspace-jspui/src/main/webapp/tools/edit-item-form.jsp index 2260219be34ac74c49719958e5aad10c6ef65666..48b5bebbdb4c967c559a6a3c42c446de72bf7af8 100644 --- a/dspace-jspui/src/main/webapp/tools/edit-item-form.jsp +++ b/dspace-jspui/src/main/webapp/tools/edit-item-form.jsp @@ -88,6 +88,12 @@ Boolean reinstate = (Boolean)request.getAttribute("reinstate_button"); boolean bReinstate = (reinstate == null ? false : reinstate.booleanValue()); + Boolean privating = (Boolean)request.getAttribute("privating_button"); + boolean bPrivating = (privating == null ? false : privating.booleanValue()); + + Boolean publicize = (Boolean)request.getAttribute("publicize_button"); + boolean bPublicize = (publicize == null ? false : publicize.booleanValue()); + Boolean reOrderBitstreams = (Boolean)request.getAttribute("reorder_bitstreams_button"); boolean breOrderBitstreams = (reOrderBitstreams != null && reOrderBitstreams); @@ -115,7 +121,7 @@ // put up a SELECT element containing all choices if ("select".equals(cam.getPresentation(fieldName))) { - sb.append("<select id=\"").append(fieldNameIdx) + sb.append("<select class=\"form-control\" id=\"").append(fieldNameIdx) .append("\" name=\"").append(fieldNameIdx) .append("\" size=\"1\">"); Choices cs = cam.getMatches(fieldName, dcv.value, collectionID, 0, 0, null); @@ -136,18 +142,21 @@ else { String confidenceIndicator = "indicator_"+confidenceName; - sb.append("<textarea id=\"").append(fieldNameIdx).append("\" name=\"").append(fieldNameIdx) + sb.append("<textarea class=\"form-control\" 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=\"") + sb.append("<span class=\"col-md-1\">") + .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("</span>"); + sb.append("<span class=\"col-md-5\">") + .append("<input class=\"form-control\" type=\"text\" readonly value=\"") .append(dcv.authority != null ? dcv.authority : "") .append("\" id=\"").append(authorityName) .append("\" onChange=\"javascript: return DSpaceAuthorityOnChange(this, '") @@ -161,10 +170,12 @@ .append("\" >") .append("<input type=\"hidden\" value=\"").append(confidenceSymbol).append("\" id=\"").append(confidenceName) .append("\" name=\"").append(confidenceName) - .append("\" class=\"ds-authority-confidence-input\"/>"); + .append("\" class=\"ds-authority-confidence-input\"/>") + .append("</span>"); } - sb.append("<input type=\"image\" name=\"").append(fieldNameIdx).append("_lookup\" ") + sb.append("<span class=\"col-md-1\">") + .append("<button class=\"form-control\" name=\"").append(fieldNameIdx).append("_lookup\" ") .append("onclick=\"javascript: return DSpaceChoiceLookup('") .append(contextPath).append("/tools/lookup.jsp','") .append(fieldName).append("','edit_metadata','") @@ -174,7 +185,7 @@ .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\" />"); + .append("\"><span class=\"glyphicon glyphicon-search\"></span></button></span>"); } } return sb; @@ -182,10 +193,14 @@ %> <c:set var="dspace.layout.head.last" scope="request"> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/prototype.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/effects.js"></script> + <script type="text/javascript" src="<%= request.getContextPath() %>/static/js/scriptaculous/controls.js"></script> <script type="text/javascript" src="<%= request.getContextPath() %>/dspace-admin/js/bitstream-ordering.js"></script> </c:set> -<dspace:layout titlekey="jsp.tools.edit-item-form.title" +<dspace:layout style="submission" titlekey="jsp.tools.edit-item-form.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -194,24 +209,75 @@ <%-- <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"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.collection-admin\") + \"#editmetadata\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <%-- <p><strong>PLEASE NOTE: These changes are not validated in any way. 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> --%> - <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> --%> - <div><dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.collection-admin\") + \"#editmetadata\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> - - <center> - <table width="70%" summary="Edit item table"> - <tr> - <%-- <td class="submitFormLabel">Item internal ID:</td> --%> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.itemID"/></td> - <td class="standard"><%= item.getID() %></td> - <td class="standard" width="100%" align="right" rowspan="5"> -<% + <p class="alert alert-danger"><strong><fmt:message key="jsp.tools.edit-item-form.note"/></strong></p> + + <div class="row"> + <div class="col-md-9"> + <div class="panel panel-primary"> + <div class="panel-heading"><fmt:message key="jsp.tools.edit-item-form.details" /></div> + + <div class="panel-body"> + <table class="table"> + <tr> + <td><fmt:message key="jsp.tools.edit-item-form.itemID" /> + </td> + <td><%= item.getID() %></td> + </tr> + + <tr> + <td><fmt:message key="jsp.tools.edit-item-form.handle" /> + </td> + <td><%= (handle == null ? "None" : handle) %></td> + </tr> + <tr> + <td><fmt:message key="jsp.tools.edit-item-form.modified" /> + </td> + <td><dspace:date + date="<%= new DCDate(item.getLastModified()) %>" /> + </td> + </tr> + + + <%-- <td class="submitFormLabel">In Collections:</td> --%> + <tr> + <td><fmt:message key="jsp.tools.edit-item-form.collections" /> + </td> + <td> + <% for (int i = 0; i < collections.length; i++) { %> <%= collections[i].getMetadata("name") %> + <br /> <% } %> + </td> + </tr> + <tr> + <%-- <td class="submitFormLabel">Item page:</td> --%> + <td><fmt:message key="jsp.tools.edit-item-form.itempage" /> + </td> + <td> + <% if (handle == null) { %> <em><fmt:message + key="jsp.tools.edit-item-form.na" /> + </em> <% } else { + String url = ConfigurationManager.getProperty("dspace.url") + "/handle/" + handle; %> + <a target="_blank" href="<%= url %>"><%= url %></a> <% } %> + </td> + </tr> + + + </table> + </div> + </div> + </div> + + <div class="col-md-3"> + <div class="panel panel-default"> + <div class="panel-heading"><fmt:message key="jsp.actiontools"/></div> + <div class="panel-body"> + <% if (!item.isWithdrawn() && bWithdraw) { %> @@ -219,7 +285,7 @@ <input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="action" value="<%= EditItemServlet.START_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 class="btn btn-warning col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.withdraw-w-confirm.button"/>"/> </form> <% } @@ -230,13 +296,11 @@ <input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="action" value="<%= EditItemServlet.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 class="btn btn-warning col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.reinstate.button"/>"/> </form> <% } %> - - <br/> <% if (bDelete) { @@ -245,95 +309,103 @@ <input type="hidden" name="item_id" value="<%= item.getID() %>" /> <input type="hidden" name="action" value="<%= EditItemServlet.START_DELETE %>" /> <%-- <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 class="btn btn-danger col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.delete-w-confirm.button"/>"/> </form> <% } - +%> +<% if (isItemAdmin) { -%> <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="action" value="<%= EditItemServlet.START_MOVE_ITEM %>" /> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.move-item.button"/>"/> + <input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.move-item.button"/>"/> </form> <% } %> - </td> - </tr> - <tr> - <%-- <td class="submitFormLabel">Handle:</td> --%> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.handle"/></td> - <td class="standard"><%= (handle == null ? "None" : handle) %></td> - </tr> - <tr> - <%-- <td class="submitFormLabel">Last 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> - </tr> - <tr> - <%-- <td class="submitFormLabel">In Collections:</td> --%> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.collections"/></td> - <td class="standard"> -<% for (int i = 0; i < collections.length; i++) { %> - <%= collections[i].getMetadata("name") %><br/> -<% } %> - </td> - </tr> +<% + if (item.isDiscoverable() && bPrivating) + { +%> + <form method="post" action="<%= request.getContextPath() %>/tools/edit-item"> + <input type="hidden" name="item_id" value="<%= item.getID() %>" /> + <input type="hidden" name="action" value="<%= EditItemServlet.START_PRIVATING %>" /> + <input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.privating-w-confirm.button"/>"/> + </form> +<% + } + else if (!item.isDiscoverable() && bPublicize) + { +%> + <form method="post" action="<%= request.getContextPath() %>/tools/edit-item"> + <input type="hidden" name="item_id" value="<%= item.getID() %>" /> + <input type="hidden" name="action" value="<%= EditItemServlet.PUBLICIZE %>" /> + <input class="btn btn-default col-md-12" type="submit" name="submit" value="<fmt:message key="jsp.tools.edit-item-form.publicize.button"/>"/> + </form> +<% + } +%> - <tr> - <%-- <td class="submitFormLabel">Item page:</td> --%> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.itempage"/></td> - <td class="standard"> -<% if (handle == null) { %> - <em><fmt:message key="jsp.tools.edit-item-form.na"/></em> -<% } else { - String url = ConfigurationManager.getProperty("dspace.url") + "/handle/" + handle; %> - <a target="_blank" href="<%= url %>"><%= url %></a> -<% } %> - </td> - </tr> <% if (bPolicy) { %> -<%-- =========================================================== + <%-- =========================================================== Edit item's policies =========================================================== --%> - <tr> - <%-- <td class="submitFormLabel">Item's Authorizations:</td> --%> - <td class="submitFormLabel"><fmt:message key="jsp.tools.edit-item-form.item"/></td> - <td> - <form method="post" action="<%= request.getContextPath() %>/tools/authorize"> - <input type="hidden" name="handle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>" /> - <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="<fmt:message key="jsp.tools.general.edit"/>"/> - </form> - </td> - </tr> + <form method="post" + action="<%= request.getContextPath() %>/tools/authorize"> + <input type="hidden" name="handle" + value="<%= ConfigurationManager.getProperty("handle.prefix") %>" /> + <input type="hidden" name="item_id" value="<%= item.getID() %>" /> + <%-- <input type="submit" name="submit_item_select" value="Edit..."> --%> + <input class="btn btn-default col-md-12" type="submit" + name="submit_item_select" + value="<fmt:message key="jsp.tools.edit-item-form.item" />" /> + </form> <% } %> - </table> - </center> - +<% + if (isItemAdmin) + { +%> +<%-- =========================================================== + Curate Item + =========================================================== --%> + <form method="post" + action="<%= request.getContextPath() %>/tools/curate"> + <input type="hidden" name="item_id" value="<%= item.getID() %>" /> + <input class="btn btn-default col-md-12" type="submit" + name="submit_item_select" + value="<fmt:message key="jsp.tools.edit-item-form.form.button.curate"/>" /> + </form> + <% + } + %> + </div> + </div> + </div> + </div> + + + <% if (item.isWithdrawn()) { %> <%-- <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 class="alert alert-warning"><fmt:message key="jsp.tools.edit-item-form.msg"/></p> <% } %> - <p> </p> - - <form id="edit_metadata" name="edit_metadata" method="post" action="<%= request.getContextPath() %>/tools/edit-item"> - <table class="miscTable" summary="Edit item withdrawn table"> + <div class="table-responsive"> + <table class="table" summary="Edit item withdrawn table"> <tr> <%-- <th class="oddRowOddCol"><strong>Element</strong></th> <th id="t1" class="oddRowEvenCol"><strong>Qualifier</strong></th> @@ -398,26 +470,26 @@ dcv[i], collectionID).toString() %> <% } else { %> - <textarea id="value_<%= key %>_<%= sequenceNumber %>" name="value_<%= key %>_<%= sequenceNumber %>" rows="3" cols="50"><%= dcv[i].value %></textarea> + <textarea class="form-control" id="value_<%= key %>_<%= sequenceNumber %>" name="value_<%= key %>_<%= sequenceNumber %>" rows="3" cols="50"><%= dcv[i].value %></textarea> <% } %> </td> <td headers="t4" class="<%= row %>RowOddCol"> - <input type="text" name="language_<%= key %>_<%= sequenceNumber %>" value="<%= (dcv[i].language == null ? "" : dcv[i].language.trim()) %>" size="5"/> + <input class="form-control" type="text" name="language_<%= key %>_<%= sequenceNumber %>" value="<%= (dcv[i].language == null ? "" : dcv[i].language.trim()) %>" size="5"/> </td> <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="<fmt:message key="jsp.tools.general.remove"/>"/> + <button class="btn btn-danger" name="submit_remove_<%= key %>_<%= sequenceNumber %>" value="<fmt:message key="jsp.tools.general.remove"/>"> + <span class="glyphicon glyphicon-trash"></span> + </button> </td> </tr> <% row = (row.equals("odd") ? "even" : "odd"); } %> - <tr><td> </td></tr> - <tr> <td headers="t1" colspan="3" class="<%= row %>RowEvenCol"> - <select name="addfield_dctype"> + <select class="form-control" name="addfield_dctype"> <% for (int i = 0; i < dcTypes.length; i++) { Integer fieldID = new Integer(dcTypes[i].getFieldID()); @@ -428,19 +500,23 @@ </select> </td> <td headers="t3" class="<%= row %>RowOddCol"> - <textarea name="addfield_value" rows="3" cols="50"></textarea> + <textarea class="form-control" name="addfield_value" rows="3" cols="50"></textarea> </td> <td headers="t4" class="<%= row %>RowEvenCol"> - <input type="text" name="addfield_language" size="5"/> + <input class="form-control" type="text" name="addfield_language" size="5"/> </td> <td headers="t5" class="<%= row %>RowOddCol"> <%-- <input type="submit" name="submit_addfield" value="Add"> --%> - <input type="submit" name="submit_addfield" value="<fmt:message key="jsp.tools.general.add"/>"/> + <button class="btn btn-default" name="submit_addfield" value="<fmt:message key="jsp.tools.general.add"/>"> + <span class="glyphicon glyphicon-plus"></span> + </button> </td> </tr> </table> - <p> </p> + </div> + + <br/> <%-- <h2>Bitstreams</h2> --%> <h2><fmt:message key="jsp.tools.edit-item-form.heading"/></h2> @@ -448,9 +524,9 @@ <%-- <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 format field.</p> --%> - <p><fmt:message key="jsp.tools.edit-item-form.note3"/></p> - - <table id="bitstream-edit-form-table" class="miscTable" summary="Bitstream data table"> + <p class="alert alert-warning"><fmt:message key="jsp.tools.edit-item-form.note3"/></p> + <div class="table-responsive"> + <table id="bitstream-edit-form-table" class="table" summary="Bitstream data table"> <tr> <%-- <th class="oddRowEvenCol"><strong>Primary<br>Bitstream</strong></th> <th class="oddRowOddCol"><strong>Name</strong></th> @@ -458,13 +534,13 @@ <th class="oddRowOddCol"><strong>Description</strong></th> <th class="oddRowEvenCol"><strong>Format</strong></th> <th class="oddRowOddCol"><strong>User Format Description</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="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="t15" class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem10"/></strong></th> - <th id="t16" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem11"/></strong></th> + <th id="t10" class="oddRowEvenCol"> </th> + <th id="t11" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem5"/></strong></th> + <th id="t12" class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem7"/></strong></th> + <th id="t13" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem8"/></strong></th> + <th id="t14" class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem9"/></strong></th> + <th id="t15" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem10"/></strong></th> + <th id="t16" class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem11"/></strong></th> <th id="t17" class="oddRowOddCol"><strong><fmt:message key="jsp.tools.edit-item-form.elem12"/></strong></th> <th id="t18" class="oddRowEvenCol"> </th> </tr> @@ -488,31 +564,36 @@ BitstreamFormat bf = bitstreams[j].getFormat(); %> <tr id="<%="row_" + bundles[i].getName() + "_" + bitstreams[j].getID()%>"> + <td headers="t10" class="<%= row %>RowEvenCol" align="center"> + <%-- <a target="_blank" href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[j].getID() %>">View</a> <input type="submit" name="submit_delete_bitstream_<%= key %>" value="Remove"> --%> + <a class="btn btn-info" target="_blank" href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[j].getID() %>"><fmt:message key="jsp.tools.general.view"/></a> + </td> <% if (bundles[i].getName().equals("ORIGINAL")) { %> <td headers="t11" class="<%= row %>RowEvenCol" align="center"> + <span class="form-control"> <input type="radio" name="<%= bundles[i].getID() %>_primary_bitstream_id" value="<%= bitstreams[j].getID() %>" <% if (bundles[i].getPrimaryBitstreamID() == bitstreams[j].getID()) { %> checked="<%="checked" %>" - <% } %> /> + <% } %> /></span> </td> <% } else { %> <td headers="t11"> </td> <% } %> <td headers="t12" class="<%= row %>RowOddCol"> - <input type="text" name="bitstream_name_<%= key %>" value="<%= (bitstreams[j].getName() == null ? "" : Utils.addEntities(bitstreams[j].getName())) %>"/> + <input class="form-control" type="text" name="bitstream_name_<%= key %>" value="<%= (bitstreams[j].getName() == null ? "" : Utils.addEntities(bitstreams[j].getName())) %>"/> </td> <td headers="t13" class="<%= row %>RowEvenCol"> - <input type="text" name="bitstream_source_<%= key %>" value="<%= (bitstreams[j].getSource() == null ? "" : bitstreams[j].getSource()) %>"/> + <input class="form-control" type="text" name="bitstream_source_<%= key %>" value="<%= (bitstreams[j].getSource() == null ? "" : bitstreams[j].getSource()) %>"/> </td> <td headers="t14" class="<%= row %>RowOddCol"> - <input type="text" name="bitstream_description_<%= key %>" value="<%= (bitstreams[j].getDescription() == null ? "" : Utils.addEntities(bitstreams[j].getDescription())) %>"/> + <input class="form-control" type="text" name="bitstream_description_<%= key %>" value="<%= (bitstreams[j].getDescription() == null ? "" : Utils.addEntities(bitstreams[j].getDescription())) %>"/> </td> <td headers="t15" class="<%= row %>RowEvenCol"> - <input type="text" name="bitstream_format_id_<%= key %>" value="<%= bf.getID() %>" size="4"/> (<%= Utils.addEntities(bf.getShortDescription()) %>) + <input class="form-control" type="text" name="bitstream_format_id_<%= key %>" value="<%= bf.getID() %>" size="4"/> (<%= Utils.addEntities(bf.getShortDescription()) %>) </td> <td headers="t16" class="<%= row %>RowOddCol"> - <input type="text" name="bitstream_user_format_description_<%= key %>" value="<%= (bitstreams[j].getUserFormatDescription() == null ? "" : Utils.addEntities(bitstreams[j].getUserFormatDescription())) %>"/> + <input class="form-control" type="text" name="bitstream_user_format_description_<%= key %>" value="<%= (bitstreams[j].getUserFormatDescription() == null ? "" : Utils.addEntities(bitstreams[j].getUserFormatDescription())) %>"/> </td> <% if (bundles[i].getName().equals("ORIGINAL") && breOrderBitstreams) @@ -545,10 +626,14 @@ <input type="hidden" value="<%=upButtonValue%>" name="<%=bundles[i].getID()%>_<%=bitstreams[j].getID()%>_up_value"> <input type="hidden" value="<%=downButtonValue%>" name="<%=bundles[i].getID()%>_<%=bitstreams[j].getID()%>_down_value"> <div> - <input name="submit_order_<%=key%>_up" type="submit" value="<fmt:message key="jsp.tools.edit-item-form.move-up"/> " <%=j==0 ? "disabled=\"disabled\"" : ""%>/> + <button class="btn btn-default" name="submit_order_<%=key%>_up" value="<fmt:message key="jsp.tools.edit-item-form.move-up"/> " <%=j==0 ? "disabled=\"disabled\"" : ""%>> + <span class="glyphicon glyphicon-arrow-up"></span> + </button> </div> <div> - <input name="submit_order_<%=key%>_down" type="submit" value="<fmt:message key="jsp.tools.edit-item-form.move-down"/> " <%=j==(bitstreams.length-1) ? "disabled=\"disabled\"" : ""%>/> + <button class="btn btn-default" name="submit_order_<%=key%>_down" value="<fmt:message key="jsp.tools.edit-item-form.move-down"/> " <%=j==(bitstreams.length-1) ? "disabled=\"disabled\"" : ""%>> + <span class="glyphicon glyphicon-arrow-down"></span> + </button> </div> </td> @@ -562,10 +647,11 @@ } %> <td headers="t18" class="<%= row %>RowEvenCol"> - <%-- <a target="_blank" href="<%= request.getContextPath() %>/retrieve/<%= bitstreams[j].getID() %>">View</a> <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> + <% if (bRemoveBits) { %> - <input type="submit" name="submit_delete_bitstream_<%= key %>" value="<fmt:message key="jsp.tools.general.remove"/>" /> + <button class="btn btn-danger" name="submit_delete_bitstream_<%= key %>" value="<fmt:message key="jsp.tools.general.remove"/>"> + <span class="glyphicon glyphicon-trash"></span> + </button> <% } %> </td> </tr> @@ -575,18 +661,15 @@ } %> </table> - - <p> </p> + </div> + <%-- <p align="center"><input type="submit" name="submit_addbitstream" value="Add Bitstream"></p> --%> - <center> - <table width="70%" align="center"> - <tr> - <td> + <div class="btn-group col-md-12"> <% - if (bCreateBits) { - %> - <input type="submit" name="submit_addbitstream" value="<fmt:message key="jsp.tools.edit-item-form.addbit.button"/>"/> + if (bCreateBits) { + %> + <input class="btn btn-success col-md-2" type="submit" name="submit_addbitstream" value="<fmt:message key="jsp.tools.edit-item-form.addbit.button"/>"/> <% } if(breOrderBitstreams){ %> @@ -600,35 +683,23 @@ 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"); %> - <input type="submit" name="submit_addcc" value="<%= s %>" /> + <input class="btn btn-success col-md-2" type="submit" name="submit_addcc" value="<%= s %>" /> <input type="hidden" name="handle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>"/> <input type="hidden" name="item_id" value="<%= item.getID() %>"/> - <% - } -%> - </td> - </tr> - </table> - </center> + + <% + } + %> + - <p> </p> <input type="hidden" name="item_id" value="<%= item.getID() %>"/> <input type="hidden" name="action" value="<%= EditItemServlet.UPDATE_ITEM %>"/> - <center> - <table width="70%"> - <tr> - <td align="left"> + <%-- <input type="submit" name="submit" value="Update" /> --%> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.general.update"/>" /> - </td> - <td align="right"> - + <input class="btn btn-primary pull-right col-md-3" type="submit" name="submit" value="<fmt:message key="jsp.tools.general.update"/>" /> <%-- <input type="submit" name="submit_cancel" value="Cancel" /> --%> - <input type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.general.cancel"/>" /> - </td> - </tr> - </table> - </center> + <input class="btn btn-default pull-right col-md-3" type="submit" name="submit_cancel" value="<fmt:message key="jsp.tools.general.cancel"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/eperson-list.jsp b/dspace-jspui/src/main/webapp/tools/eperson-list.jsp index 7fb7775a827f9769d2c1c15683ef33b8c7cab74c..16b79e1f0022b3164de325653f71f93a8d5019c4 100644 --- a/dspace-jspui/src/main/webapp/tools/eperson-list.jsp +++ b/dspace-jspui/src/main/webapp/tools/eperson-list.jsp @@ -28,6 +28,7 @@ <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> +<%@page import="org.apache.commons.lang.StringEscapeUtils"%> <%@ page import="org.dspace.eperson.EPerson" %> <%@ page import="org.dspace.core.Utils" %> @@ -129,7 +130,16 @@ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <link rel="stylesheet" href="<%= request.getContextPath() %>/styles.css" type="text/css"/> <link rel="shortcut icon" href="<%= request.getContextPath() %>/favicon.ico" type="image/x-icon"/> - + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/jquery-ui-1.10.3.custom/redmond/jquery-ui-1.10.3.custom.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/bootstrap/bootstrap.min.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/bootstrap/bootstrap-theme.min.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/bootstrap/dspace-theme.css" type="text/css" /> + <script type='text/javascript' src="<%= request.getContextPath() %>/static/js/jquery/jquery-1.10.2.min.js"></script> + <script type='text/javascript' src='<%= request.getContextPath() %>/static/js/jquery/jquery-ui-1.10.3.custom.min.js'></script> + <script type='text/javascript' src='<%= request.getContextPath() %>/static/js/bootstrap/bootstrap.min.js'></script> + <script type='text/javascript' src='<%= request.getContextPath() %>/static/js/holder.js'></script> + <script type="text/javascript" src="<%= request.getContextPath() %>/utils.js"></script> + <script type="text/javascript"> <!-- Begin @@ -168,73 +178,65 @@ function clearEPeople() <p class="submitFormHelp"><fmt:message key="jsp.tools.eperson-list.info1"/></p> <% } %> <center> -<form method="get"> - <input type="hidden" name="first" value="<%= first %>" /> - <input type="hidden" name="sortby" value="<%= sortBy %>" /> - <input type="hidden" name="multiple" value="<%= multiple %>" /> - <label for="search"><fmt:message key="jsp.tools.eperson-list.search.query" /></label><input type="text" name="search" value="<%= search %>"/> - <input type="submit" value="<fmt:message key="jsp.tools.eperson-list.search.submit" />" /> -<% - if (search != null && !search.equals("")) - { %> - <br/> - <a href="<%= request.getContextPath() + "/tools/eperson-list?multiple=" + multiple + "&sortby=" + sortByParam + "&first="+first %>"><fmt:message key="jsp.tools.eperson-list.search.return-browse" /></a> -<% - } -%> -</form> + <form method="get"> + <input type="hidden" name="first" value="<%= first %>" /> + <input type="hidden" name="sortby" value="<%= sortBy %>" /> + <input type="hidden" name="multiple" value="<%= multiple %>" /> + <label for="search"><fmt:message key="jsp.tools.eperson-list.search.query"/></label> + <input class="form-control" style="width:200px;"type="text" name="search" value="<%= search %>"/> + <input class="btn btn-success" type="submit" value="<fmt:message key="jsp.tools.eperson-list.search.submit" />" /> + <% + if (search != null && !search.equals("")){ %> + <a class="btn btn-warning" href="<%= request.getContextPath() + "/tools/eperson-list?multiple=" + multiple + "&sortby=" + sortByParam + "&first="+first %>"><fmt:message key="jsp.tools.eperson-list.search.return-browse" /></a> + <%}%> + + </form> </center> + <%-- Controls for jumping around list--%> - <table width="99%"> - <tr> - <%-- <td width="17%" align="center"><small><strong><a href="<%= jumpLink %>0">First</a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveBack %>">< 5 Pages</a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneBack %>">< 1 Page</a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneForward %>">1 Page ></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveForward %>">5 Pages ></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpEnd %>">Last</a></strong></small></td> --%> - - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %>0"><fmt:message key="jsp.tools.eperson-list.jump.first"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveBack %>"><fmt:message key="jsp.tools.eperson-list.jump.five-back"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneBack %>"><fmt:message key="jsp.tools.eperson-list.jump.one-back"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneForward %>"><fmt:message key="jsp.tools.eperson-list.jump.one-forward"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveForward %>"><fmt:message key="jsp.tools.eperson-list.jump.five-forward"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpEnd %>"><fmt:message key="jsp.tools.eperson-list.jump.last"/></a></strong></small></td> - </tr> - </table> +<div class="span12" style="text-align:center"> + <ul class="pagination"> + <li><a href="<%= jumpLink %>0"><fmt:message key="jsp.tools.eperson-list.jump.first"/></a></li> + <li><a href="<%= jumpLink %><%= jumpFiveBack %>"><fmt:message key="jsp.tools.eperson-list.jump.five-back"/></a></li> + <li><a href="<%= jumpLink %><%= jumpOneBack %>"><fmt:message key="jsp.tools.eperson-list.jump.one-back"/></a></li> + <li><a href="<%= jumpLink %><%= jumpOneForward %>"><fmt:message key="jsp.tools.eperson-list.jump.one-forward"/></a></li> + <li><a href="<%= jumpLink %><%= jumpFiveForward %>"><fmt:message key="jsp.tools.eperson-list.jump.five-forward"/></a></li> + <li><a href="<%= jumpLink %><%= jumpEnd %>"><fmt:message key="jsp.tools.eperson-list.jump.last"/></a></li> + </ul> +</div <br/> <form method="get" action=""> <%-- Will never actually be posted, it's just so buttons will appear --%> - <table class="miscTable" align="center" summary="Epeople list"> + <table class="table table-striped" align="center" summary="Epeople list"> <% if (search != null && !search.equals("")) { %> <tr> - <th class="oddRowOddCol"> </th> - <th class="oddRowEvenCol"><fmt:message key="jsp.tools.eperson-list.th.id" /></th> - <th class="oddRowOddCol"><fmt:message key="jsp.tools.eperson-list.th.email" /></th> - <th class="oddRowEvenCol"><fmt:message key="jsp.tools.eperson-list.th.lastname" /></th> - <th class="oddRowOddCol"><fmt:message key="jsp.tools.eperson-list.th.lastname" /></th> + <th> </th> + <th><fmt:message key="jsp.tools.eperson-list.th.id" /></th> + <th><fmt:message key="jsp.tools.eperson-list.th.email" /></th> + <th><fmt:message key="jsp.tools.eperson-list.th.lastname" /></th> + <th><fmt:message key="jsp.tools.eperson-list.th.lastname" /></th> </tr> <% } else { %> <tr> - <th id="t1" class="oddRowOddCol"> </th> - <th id="t2" class="oddRowEvenCol"><% + <th id="t1"> </th> + <th id="t2"><% if (sortBy == EPerson.ID) { - %><strong><fmt:message key="jsp.tools.eperson-list.th.id.sortedby" /></strong><% + %><fmt:message key="jsp.tools.eperson-list.th.id"/><span class="glyphicon glyphicon-arrow-down"><% } else { %><a href="<%= sortLink %>id"><fmt:message key="jsp.tools.eperson-list.th.id" /></a><% } %></th> - <th id="t3" class="oddRowOddCol"><% + <th id="t3"><% if (sortBy == EPerson.EMAIL) { - %><strong><fmt:message key="jsp.tools.eperson-list.th.email.sortedby" /></strong><% + %><fmt:message key="jsp.tools.eperson-list.th.email"/><span class="glyphicon glyphicon-arrow-down"><% } else { @@ -242,10 +244,10 @@ function clearEPeople() } %></th> <%-- <th class="oddRowEvenCol"><%= sortBy == EPerson.LASTNAME ? "<strong>Last Name ↑</strong>" : "<a href=\"" + sortLink + "lastname\">Last Name</a>" %></th> --%> - <th id="t4" class="oddRowEvenCol"><% + <th id="t4"><% if (sortBy == EPerson.LASTNAME) { - %><fmt:message key="jsp.tools.eperson-list.th.lastname.sortedby" /><% + %><fmt:message key="jsp.tools.eperson-list.th.lastname"/><span class="glyphicon glyphicon-arrow-down"><% } else { @@ -253,12 +255,12 @@ function clearEPeople() } %></th> - <th id="t5" class="oddRowOddCol"><fmt:message key="jsp.tools.eperson-list.th.firstname"/></th> + <th id="t5"><fmt:message key="jsp.tools.eperson-list.th.firstname"/></th> - <th id="t6" class="oddRowEvenCol"><% + <th id="t6"><% if (sortBy == EPerson.LANGUAGE) { - %><fmt:message key="jsp.tools.eperson-list.th.language.sortedby" /><% + %><fmt:message key="jsp.tools.eperson-list.th.language"/><span class="glyphicon glyphicon-arrow-down"></span><% } else { @@ -281,23 +283,24 @@ function clearEPeople() { EPerson e = epeople[i]; // Make sure no quotes in full name will mess up our Javascript - String fullname = Utils.addEntities(e.getFullName().replace('\'', ' ')); + String fullname = StringEscapeUtils.escapeXml(StringEscapeUtils.escapeJavaScript(e.getFullName())); + String email = StringEscapeUtils.escapeXml(StringEscapeUtils.escapeJavaScript(e.getEmail())); %> - <tr> - <td headers="t1" class="<%= row %>RowOddCol"> - <input type="button" value="<% - if (multiple) { %><fmt:message key="jsp.tools.general.add"/><% } - else { %><fmt:message key="jsp.tools.general.select"/><% } %>" onclick="javascript:<%= clearList %>addEPerson(<%= e.getID() %>, '<%= e.getEmail().replaceAll("'", "\\\\'") %>', '<%= Utils.addEntities(fullname) %>');<%= closeWindow %>"/></td> - <td headers="t2" class="<%= row %>RowEvenCol"><%= e.getID() %></td> - <td headers="t3" class="<%= row %>RowOddCol"><%= e.getEmail() %></td> - <td headers="t4" class="<%= row %>RowEvenCol"> + <tr> + <td headers="t1"> + <input class="btn btn-success" type="button" value="<% + if (multiple) { %><fmt:message key="jsp.tools.general.add"/><% } + else { %><fmt:message key="jsp.tools.general.select"/><% } %>" onclick="javascript:<%= clearList %>addEPerson(<%= e.getID() %>, '<%= email %>', '<%= fullname %>');<%= closeWindow %>"/></td> + <td headers="t2"><%= e.getID() %></td> + <td headers="t3"><%= (e.getEmail() == null ? "" : Utils.addEntities(e.getEmail())) %></td> + <td headers="t4"> <%= (e.getLastName() == null ? "" : Utils.addEntities(e.getLastName())) %> </td> - <td headers="t5" class="<%= row %>RowOddCol"> + <td headers="t5"> <%= (e.getFirstName() == null ? "" : Utils.addEntities(e.getFirstName())) %> </td> - <td headers="t6" class="<%= row %>RowOddCol"> - <%= (e.getLanguage() == null ? "" : e.getLanguage()) %> + <td headers="t6"> + <%= (e.getLanguage() == null ? "" : Utils.addEntities(e.getLanguage())) %> </td> </tr> <% @@ -309,28 +312,21 @@ function clearEPeople() <br/> <%-- Controls for jumping around list--%> - <table width="99%"> - <tr> - <%-- - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %>0">First</a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveBack %>">< 5 Pages</a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneBack %>">< 1 Page</a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneForward %>">1 Page ></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveForward %>">5 Pages ></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpEnd %>">Last</a></strong></small></td> - --%> - - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %>0"><fmt:message key="jsp.tools.eperson-list.jump.first"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveBack %>"><fmt:message key="jsp.tools.eperson-list.jump.five-back"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneBack %>"><fmt:message key="jsp.tools.eperson-list.jump.one-back"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneForward %>"><fmt:message key="jsp.tools.eperson-list.jump.one-forward"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveForward %>"><fmt:message key="jsp.tools.eperson-list.jump.five-forward"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpEnd %>"><fmt:message key="jsp.tools.eperson-list.jump.last"/></a></strong></small></td> - </tr> - </table> +<div class="span12" style="text-align:center"> + <ul class="pagination"> + <li><a href="<%= jumpLink %>0"><fmt:message key="jsp.tools.eperson-list.jump.first"/></a></li> + <li><a href="<%= jumpLink %><%= jumpFiveBack %>"><fmt:message key="jsp.tools.eperson-list.jump.five-back"/></a></li> + <li><a href="<%= jumpLink %><%= jumpOneBack %>"><fmt:message key="jsp.tools.eperson-list.jump.one-back"/></a></li> + <li><a href="<%= jumpLink %><%= jumpOneForward %>"><fmt:message key="jsp.tools.eperson-list.jump.one-forward"/></a></li> + <li><a href="<%= jumpLink %><%= jumpFiveForward %>"><fmt:message key="jsp.tools.eperson-list.jump.five-forward"/></a></li> + <li><a href="<%= jumpLink %><%= jumpEnd %>"><fmt:message key="jsp.tools.eperson-list.jump.last"/></a></li> + </ul> +</div> <%-- <p align="center"><input type="button" value="Close" onClick="window.close();"/></p> --%> - <p align="center"><input type="button" value="<fmt:message key="jsp.tools.eperson-list.close.button"/>" onclick="window.close();"/></p> + <p align="center"> + <input type="button" class="btn btn-danger" value="<fmt:message key="jsp.tools.eperson-list.close.button"/>" onclick="window.close();"/> + </p> </form> diff --git a/dspace-jspui/src/main/webapp/tools/get-item-id.jsp b/dspace-jspui/src/main/webapp/tools/get-item-id.jsp index 42cf9c8329c3cb7e09bbd35883777db1a64ce0c0..610dd92a99dbcd985e5c6ce4e150339979f768c8 100644 --- a/dspace-jspui/src/main/webapp/tools/get-item-id.jsp +++ b/dspace-jspui/src/main/webapp/tools/get-item-id.jsp @@ -26,21 +26,23 @@ <%@ page import="org.dspace.core.ConfigurationManager" %> -<dspace:layout titlekey="jsp.tools.get-item-id.title" +<dspace:layout style="submission" titlekey="jsp.tools.get-item-id.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin"> <%-- <h1>Edit or Delete Item</h1> --%> - <h1><fmt:message key="jsp.tools.get-item-id.heading"/></h1> + <h1><fmt:message key="jsp.tools.get-item-id.heading"/> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#items\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup> + </h1> <% if (request.getAttribute("invalid.id") != null) { %> <%-- <p><strong>The ID you entered isn't a valid item ID.</strong> If you're trying to edit a community or collection, you need to use the --%> <%-- <a href="<%= request.getContextPath() %>/dspace-admin/edit-communities">communities/collections admin page.</a></p> --%> - <p><fmt:message key="jsp.tools.get-item-id.info1"> + <p class="alert alert-warning"><fmt:message key="jsp.tools.get-item-id.info1"> <fmt:param><%= request.getContextPath() %>/dspace-admin/edit-communities</fmt:param> </fmt:message></p> <% } %> @@ -48,31 +50,20 @@ <%-- <p>Enter the Handle or internal item ID of the item you want to edit or delete. <dspace:popup page="/help/site-admin.html#items">More help...</dspace:popup></p> --%> - <div><fmt:message key="jsp.tools.get-item-id.info2"/> <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#items\"%>"><fmt:message key="jsp.morehelp"/></dspace:popup></div> + <div><fmt:message key="jsp.tools.get-item-id.info2"/></div> <form method="get" action=""> - <center> - <table class="miscTable"> - <tr class="oddRowEvenCol"> - <%-- <td class="submitFormLabel">Handle:</td> --%> - <td class="submitFormLabel"><label for="thandle"><fmt:message key="jsp.tools.get-item-id.handle"/></label></td> - <td> - <input type="text" name="handle" id="thandle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>/" size="12"/> - <%-- <input type="submit" name="submit" value="Find" /> --%> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.get-item-id.find.button"/>" /> - </td> - </tr> - <tr><td></td></tr> - <tr class="oddRowEvenCol"> - <%-- <td class="submitFormLabel">Internal ID:</td> --%> - <td class="submitFormLabel"><label for="titem_id"><fmt:message key="jsp.tools.get-item-id.internal"/></label></td> - <td> - <input type="text" name="item_id" id="titem_id" size="12"/> - <%-- <input type="submit" name="submit" value="Find"> --%> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.get-item-id.find.button"/>" /> - </td> - </tr> - </table> - </center> + <div class="row"> + <label class="col-md-2" for="thandle"><fmt:message key="jsp.tools.get-item-id.handle"/></label> + <span class="col-md-3"><input class="form-control" type="text" name="handle" id="thandle" value="<%= ConfigurationManager.getProperty("handle.prefix") %>/" size="12"/></span> + <%-- <input type="submit" name="submit" value="Find" /> --%> + <input class="btn btn-default" type="submit" name="submit" value="<fmt:message key="jsp.tools.get-item-id.find.button"/>" /> + </div> + <div class="row"> + <label class="col-md-2" for="thandle"><fmt:message key="jsp.tools.get-item-id.internal"/></label> + <span class="col-md-3"><input class="form-control" type="text" name="item_id" id="titem_id" size="12"/></span> + <%-- <input type="submit" name="submit" value="Find"> --%> + <input class="btn btn-default" type="submit" name="submit" value="<fmt:message key="jsp.tools.get-item-id.find.button"/>" /> + </div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/group-edit.jsp b/dspace-jspui/src/main/webapp/tools/group-edit.jsp index 0abb732f3aafc408096c93f41eb450fd64ebf04c..5c105af110de61289dfb32b637eb56552dcea5a2 100644 --- a/dspace-jspui/src/main/webapp/tools/group-edit.jsp +++ b/dspace-jspui/src/main/webapp/tools/group-edit.jsp @@ -42,44 +42,40 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.tools.group-edit.title" +<dspace:layout style="submission" titlekey="jsp.tools.group-edit.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin" nocache="true"> - <table width="95%"> - <tr> - <td align="left"> - <h1><fmt:message key="jsp.tools.group-edit.title"/> : <%=group.getName()%> (id: <%=group.getID()%>)</h1> - </td> - <td align="right" class="standard"> + <h1><fmt:message key="jsp.tools.group-edit.title"/> : <%=group.getName()%> (id: <%=group.getID()%>) <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.collection-admin\") +\"#groupeditor\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - - <center> + </h1> <form name="epersongroup" method="post" action=""> - <p><label for="tgroup_name"><fmt:message key="jsp.tools.group-edit.name"/></label><input name="group_name" id="tgroup_name" value="<%= Utils.addEntities(group.getName()) %>"/></p> - <h3><fmt:message key="jsp.tools.group-edit.heading"/></h3> - - <input type="hidden" name="group_id" value="<%=group.getID()%>"/> - <table> - <tr> - <td align="center"><strong><fmt:message key="jsp.tools.group-edit.eperson"/></strong><br/> - <dspace:selecteperson multiple="true" selected="<%= epeople %>"/> - </td> - <td align="center"><strong><fmt:message key="jsp.tools.group-edit.group"/></strong><br/> - <dspace:selectgroup multiple="true" selected="<%= groups %>"/> - </td> - </tr> - </table> - - <br/> - - <p><input type="submit" name="submit_group_update" value="<fmt:message key="jsp.tools.group-edit.update.button"/>" onclick="javascript:finishEPerson();finishGroups();"/></p> + <div class="row"><label for="tgroup_name" class="col-md-2"> + <fmt:message key="jsp.tools.group-edit.name"/></label> + <span class="col-md-10"> + <input class="form-control" name="group_name" id="tgroup_name" value="<%= Utils.addEntities(group.getName()) %>"/> + </span> + </div> + <br/> + <div class="alert alert-warning"><fmt:message key="jsp.tools.group-edit.heading"/></div> + + <input type="hidden" name="group_id" value="<%=group.getID()%>"/> + + <div class="row"> + <div class="col-md-6"> + <label for="eperson_id"><fmt:message key="jsp.tools.group-edit.eperson"/></label> + <dspace:selecteperson multiple="true" selected="<%= epeople %>"/> + </div> + + <div class="col-md-6"> + <label for="eperson_id"><fmt:message key="jsp.tools.group-edit.group"/></label> + <dspace:selectgroup multiple="true" selected="<%= groups %>"/> + </div> + </div> + <br/> + <div class="row"><input class="btn btn-success col-md-2 col-md-offset-5" type="submit" name="submit_group_update" value="<fmt:message key="jsp.tools.group-edit.update.button"/>" onclick="javascript:finishEPerson();finishGroups();"/></div> </form> - </center> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/group-list.jsp b/dspace-jspui/src/main/webapp/tools/group-list.jsp index 0b95ed2a4c05de88d06b3f4d334c90d92cccb3e8..66f00f14c5fe1da138169f3efffae5ada5e4b230 100644 --- a/dspace-jspui/src/main/webapp/tools/group-list.jsp +++ b/dspace-jspui/src/main/webapp/tools/group-list.jsp @@ -33,41 +33,35 @@ (Group[]) request.getAttribute("groups"); %> -<dspace:layout titlekey="jsp.tools.group-list.title" +<dspace:layout style="submission" titlekey="jsp.tools.group-list.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" parentlink="/dspace-admin" nocache="true"> - <table width="95%"> - <tr> - <td align="left"> <%-- <h1>Group Editor</h1> --%> - <h1><fmt:message key="jsp.tools.group-list.title"/></h1> - </td> - <td align="right" class="standard"> - <%-- <dspace:popup page="/help/site-admin.html#groups">Help...</dspace:popup> --%> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#groups\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - - <p><fmt:message key="jsp.tools.group-list.note1"/></p> - <p><fmt:message key="jsp.tools.group-list.note2"/></p> - + <h1><fmt:message key="jsp.tools.group-list.title"/> + <%-- <dspace:popup page="/help/site-admin.html#groups">Help...</dspace:popup> --%> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.site-admin\") + \"#groups\"%>"><fmt:message key="jsp.help"/></dspace:popup> + </h1> + + + <p class="alert alert-info"><fmt:message key="jsp.tools.group-list.note1"/></p> + <p class="alert alert-warning"><fmt:message key="jsp.tools.group-list.note2"/></p> + <form method="post" action=""> - <p align="center"> - <input type="submit" name="submit_add" value="<fmt:message key="jsp.tools.group-list.create.button"/>" /> - </p> + <div class="row col-md-offset-5"> + <input class="btn btn-success" type="submit" name="submit_add" value="<fmt:message key="jsp.tools.group-list.create.button"/>" /> + </div> </form> - - <table class="miscTable" align="center" summary="Group data display table"> + <br/> + + <table class="table" summary="Group data display table"> <tr> <th class="oddRowOddCol"><strong><fmt:message key="jsp.tools.group-list.id" /></strong></th> <th class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.group-list.name"/></strong></th> <th class="oddRowOddCol"> </th> - <th class="oddRowEvenCol"> </th> </tr> <% @@ -88,21 +82,18 @@ %> <form method="post" action=""> <input type="hidden" name="group_id" value="<%= groups[i].getID() %>"/> - <input type="submit" name="submit_edit" value="<fmt:message key="jsp.tools.general.edit"/>" /> + <input class="btn btn-default col-md-6" type="submit" name="submit_edit" value="<fmt:message key="jsp.tools.general.edit"/>" /> </form> <% } -%> - </td> - <td class="<%= row %>RowEvenCol"> -<% + // no delete button for group Anonymous 0 and Administrator 1 to avoid accidental deletion if (groups[i].getID() > 1 ) { %> <form method="post" action=""> <input type="hidden" name="group_id" value="<%= groups[i].getID() %>"/> - <input type="submit" name="submit_group_delete" value="<fmt:message key="jsp.tools.general.delete"/>" /> + <input class="btn btn-danger col-md-6" type="submit" name="submit_group_delete" value="<fmt:message key="jsp.tools.general.delete"/>" /> <% } %> diff --git a/dspace-jspui/src/main/webapp/tools/group-select-list.jsp b/dspace-jspui/src/main/webapp/tools/group-select-list.jsp index e1b272cada2d7ab6c79eaa6106ebbaf99683ba92..f335cf29592c22337b30ea2106622e66c2691d6b 100644 --- a/dspace-jspui/src/main/webapp/tools/group-select-list.jsp +++ b/dspace-jspui/src/main/webapp/tools/group-select-list.jsp @@ -75,7 +75,11 @@ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <link rel="stylesheet" href="<%= request.getContextPath() %>/styles.css" type="text/css"/> <link rel="shortcut icon" href="<%= request.getContextPath() %>/favicon.ico" type="image/x-icon"/> - + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/bootstrap/bootstrap.min.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/bootstrap/bootstrap-theme.min.css" type="text/css" /> + <link rel="stylesheet" href="<%= request.getContextPath() %>/static/css/bootstrap/dspace-theme.css" type="text/css" /> + <script type='text/javascript' src='<%= request.getContextPath() %>/static/js/bootstrap/bootstrap.min.js'></script> + <script type="text/javascript"> <!-- Begin @@ -116,35 +120,27 @@ function clearGroups() <% } %> <%-- Controls for jumping around list--%> - <table width="99%"> - <tr> - <%-- <td width="17%" align="center"><small><strong><a href="<%= jumpLink %>0">First</A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveBack %>">< 5 Pages</A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneBack %>">< 1 Page</A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneForward %>">1 Page ></A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveForward %>">5 Pages ></A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpEnd %>">Last</A></strong></small></td> - --%> - - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %>0"><fmt:message key="jsp.tools.group-select-list.jump.first"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveBack %>"><fmt:message key="jsp.tools.group-select-list.jump.five-back"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneBack %>"><fmt:message key="jsp.tools.group-select-list.jump.one-back"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneForward %>"><fmt:message key="jsp.tools.group-select-list.jump.one-forward"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveForward %>"><fmt:message key="jsp.tools.group-select-list.jump.five-forward"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpEnd %>"><fmt:message key="jsp.tools.group-select-list.jump.last"/></a></strong></small></td> - </tr> - </table> +<div class="span12" style="text-align:center"> + <ul class="pagination"> + <li><a href="<%= jumpLink %>0"><fmt:message key="jsp.tools.group-select-list.jump.first"/></a></li> + <li><a href="<%= jumpLink %><%= jumpFiveBack %>"><fmt:message key="jsp.tools.group-select-list.jump.five-back"/></a></li> + <li><a href="<%= jumpLink %><%= jumpOneBack %>"><fmt:message key="jsp.tools.group-select-list.jump.one-back"/></a></li> + <li><a href="<%= jumpLink %><%= jumpOneForward %>"><fmt:message key="jsp.tools.group-select-list.jump.one-forward"/></a></li> + <li><a href="<%= jumpLink %><%= jumpFiveForward %>"><fmt:message key="jsp.tools.group-select-list.jump.five-forward"/></a></li> + <li><a href="<%= jumpLink %><%= jumpEnd %>"><fmt:message key="jsp.tools.group-select-list.jump.last"/></a></li> + </ul> +</div> <br/> <form method="get" action=""> <%-- Will never actually be posted, it's just so buttons will appear --%> - <table class="miscTable" align="center" summary="Group list"> + <table class="table table-striped" align="center" summary="Group list"> <tr> <th id="t1" class="oddRowOddCol"> </th> <th id="t2" class="oddRowEvenCol"><% if (sortBy == Group.ID) { - %><strong><fmt:message key="jsp.tools.group-select-list.th.id.sortedby" /></strong><% + %><fmt:message key="jsp.tools.group-select-list.th.id"/><span class="glyphicon glyphicon-arrow-down"><% } else { @@ -154,7 +150,7 @@ function clearGroups() <th id="t3" class="oddRowOddCol"><% if (sortBy == Group.NAME) { - %><strong><fmt:message key="jsp.tools.group-select-list.th.name.sortedby" /></strong><% + %><fmt:message key="jsp.tools.group-select-list.th.name" /><span class="glyphicon glyphicon-arrow-down"><% } else { @@ -180,12 +176,12 @@ function clearGroups() String fullname = g.getName().replace('\'', ' '); %> <tr> - <td headers="t1" class="<%= row %>RowOddCol"> - <input type="button" value="<% + <td headers="t1" class=""> + <input type="button" class="btn btn-success" value="<% if (multiple) { %><fmt:message key="jsp.tools.general.add"/><% } else { %><fmt:message key="jsp.tools.general.select"/><% } %>" onclick="javascript:<%= clearList %>addGroup('<%= g.getID() %>', '<%= Utils.addEntities(fullname) %>');<%= closeWindow %>"/></td> - <td headers="t2" class="<%= row %>RowEvenCol"><%= g.getID() %></td> - <td headers="t3" class="<%= row %>RowOddCol"> <%= g.getName()%></td> + <td headers="t2" class=""><%= g.getID() %></td> + <td headers="t3" class=""> <%= g.getName()%></td> </tr> <% row = (row.equals("odd") ? "even" : "odd"); @@ -196,27 +192,19 @@ function clearGroups() <br/> <%-- Controls for jumping around list--%> - <table width="99%"> - <tr> - <%-- <td width="17%" align="center"><small><strong><a href="<%= jumpLink %>0">First</A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveBack %>">< 5 Pages</A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneBack %>">< 1 Page</A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneForward %>">1 Page ></A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveForward %>">5 Pages ></A></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpEnd %>">Last</A></strong></small></td> - --%> - - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %>0"><fmt:message key="jsp.tools.group-select-list.jump.first"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveBack %>"><fmt:message key="jsp.tools.group-select-list.jump.five-back"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneBack %>"><fmt:message key="jsp.tools.group-select-list.jump.one-back"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpOneForward %>"><fmt:message key="jsp.tools.group-select-list.jump.one-forward"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpFiveForward %>"><fmt:message key="jsp.tools.group-select-list.jump.five-forward"/></a></strong></small></td> - <td width="17%" align="center"><small><strong><a href="<%= jumpLink %><%= jumpEnd %>"><fmt:message key="jsp.tools.group-select-list.jump.last"/></a></strong></small></td> - </tr> - </table> +<div class="span12" style="text-align:center"> + <ul class="pagination"> + <li><a href="<%= jumpLink %>0"><fmt:message key="jsp.tools.group-select-list.jump.first"/></a></li> + <li><a href="<%= jumpLink %><%= jumpFiveBack %>"><fmt:message key="jsp.tools.group-select-list.jump.five-back"/></a></li> + <li><a href="<%= jumpLink %><%= jumpOneBack %>"><fmt:message key="jsp.tools.group-select-list.jump.one-back"/></a></li> + <li><a href="<%= jumpLink %><%= jumpOneForward %>"><fmt:message key="jsp.tools.group-select-list.jump.one-forward"/></a></li> + <li><a href="<%= jumpLink %><%= jumpFiveForward %>"><fmt:message key="jsp.tools.group-select-list.jump.five-forward"/></a></li> + <li><a href="<%= jumpLink %><%= jumpEnd %>"><fmt:message key="jsp.tools.group-select-list.jump.last"/></a></li> + </ul> +</div> <%-- <p align="center"><input type="button" value="Close" onClick="window.close();"></p> --%> - <p align="center"><input type="button" value="<fmt:message key="jsp.tools.group-select-list.close.button"/>" onclick="window.close();"/></p> + <p align="center"><input type="button" class="btn btn-danger" value="<fmt:message key="jsp.tools.group-select-list.close.button"/>" onclick="window.close();"/></p> </form> diff --git a/dspace-jspui/src/main/webapp/tools/itemmap-browse.jsp b/dspace-jspui/src/main/webapp/tools/itemmap-browse.jsp index fd571f31e807d2fae8865bdcebf22c278cf0dc7c..9fdbe5fb86022393756ffa0c8078ee47e6f63e3c 100644 --- a/dspace-jspui/src/main/webapp/tools/itemmap-browse.jsp +++ b/dspace-jspui/src/main/webapp/tools/itemmap-browse.jsp @@ -20,6 +20,7 @@ - browsetype - "Add" or "Remove" --%> +<%@page import="org.dspace.app.webui.util.UIUtil"%> <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="http://www.dspace.org/dspace-tags.tld" prefix="dspace" %> @@ -37,17 +38,23 @@ Collection collection = (Collection)request.getAttribute("collection"); Map items = (Map)request.getAttribute("items"); Map collections = (Map)request.getAttribute("collections"); + String index = request.getParameter("index"); + String query = request.getParameter("query"); String browsetext = (String)request.getAttribute("browsetext"); Boolean showcollection = new Boolean(false); String browsetype = (String)request.getAttribute("browsetype"); // Only "Add" and "Remove" are handled properly + Boolean more = (Boolean) request.getAttribute("more"); + boolean bMore = more != null?more:false; + int pageResult = (Integer) request.getAttribute("page") != null ? (Integer) request + .getAttribute("page") : 1; %> -<dspace:layout titlekey="jsp.tools.itemmap-browse.title"> +<dspace:layout style="submission" titlekey="jsp.tools.itemmap-browse.title"> <%-- <h2>Browse <%=browsetext%></h2> --%> <h2> <% if (browsetype.equals("Add")) { %> - <fmt:message key="jsp.tools.itemmap-browse.heading-authors"> + <fmt:message key="jsp.tools.itemmap-browse.heading-search"> <fmt:param><%= browsetext %></fmt:param> </fmt:message> <% } else if (browsetype.equals("Remove")) { %> @@ -60,14 +67,14 @@ <%-- <p>Check the box next to items you wish to add or remove, and choose 'add' or 'remove'.</p> --%> <% if (browsetype.equals("Add")){ %> - <p> + <p class="alert alert-info"> <fmt:message key="jsp.tools.itemmap-browse.add"> <fmt:param><%= collection.getName() %></fmt:param> </fmt:message> </p> <% }%> <% if (browsetype.equals("Remove")){ %> - <p> + <p class="alert alert-warning"> <fmt:message key="jsp.tools.itemmap-browse.remove"> <fmt:param><%= collection.getName() %></fmt:param> </fmt:message> @@ -77,22 +84,18 @@ <%-- %>p><fmt:message key="jsp.tools.itemmap-browse.infomsg"/></p--%> <form method="post" action="<%= request.getContextPath() %>/tools/itemmap"> <input type="hidden" name="cid" value="<%=collection.getID()%>" /> - - <table> - <tr> - <td><input type="hidden" name="action" value="<%=browsetype%>" /> + <div class="btn-group"> + <input type="hidden" name="action" value="<%=browsetype%>" /> <% if (browsetype.equals("Add")) { %> - <input type="submit" value="<fmt:message key="jsp.tools.general.add"/>" /> + <input class="btn btn-success" type="submit" value="<fmt:message key="jsp.tools.general.add"/>" /> <% } else if (browsetype.equals("Remove")) { %> - <input type="submit" value="<fmt:message key="jsp.tools.general.remove"/>" /> + <input class="btn btn-danger" type="submit" value="<fmt:message key="jsp.tools.general.remove"/>" /> <% } %> - </td> - <td><input type="submit" name="cancel" value="<fmt:message key="jsp.tools.general.cancel"/>" /></td> - </tr> - </table> - - - <table class="miscTable" align="center"> + + <input class="btn btn-default" type="submit" name="cancel" value="<fmt:message key="jsp.tools.general.cancel"/>" /> + </div> + <div class="table-responsive"> + <table class="table"> <tr> <th class="oddRowOddCol"><strong><fmt:message key="jsp.tools.itemmap-browse.th.date"/></strong></th> <th class="oddRowEvenCol"><strong><fmt:message key="jsp.tools.itemmap-browse.th.author"/></strong></th> @@ -103,9 +106,9 @@ <% } else { %> <th class="oddRowEvenCol"> <% if (browsetype.equals("Add")) { %> - <input type="submit" value="<fmt:message key="jsp.tools.general.add"/>" /> + <input class="btn btn-success" type="submit" value="<fmt:message key="jsp.tools.general.add"/>" /> <% } else if (browsetype.equals("Remove")) { %> - <input type="submit" value="<fmt:message key="jsp.tools.general.remove"/>" /> + <input class="btn btn-danger" type="submit" value="<fmt:message key="jsp.tools.general.remove"/>" /> <% } %> </th> <% } %> @@ -182,20 +185,50 @@ <% } %> </table> - - <table> - <tr> - <td> + </div> + <div class="btn-group"> + <input type="hidden" name="action" value="<%=browsetype%>" /> <% if (browsetype.equals("Add")) { %> - <input type="submit" value="<fmt:message key="jsp.tools.general.add"/>" /> + <input class="btn btn-success" type="submit" value="<fmt:message key="jsp.tools.general.add"/>" /> <% } else if (browsetype.equals("Remove")) { %> - <input type="submit" value="<fmt:message key="jsp.tools.general.remove"/>" /> + <input class="btn btn-danger" type="submit" value="<fmt:message key="jsp.tools.general.remove"/>" /> <% } %> - </td> - <td><input type="submit" name="cancel" value="<fmt:message key="jsp.tools.general.cancel"/>" /></td> - </tr> - </table> + + <input class="btn btn-default" type="submit" name="cancel" value="<fmt:message key="jsp.tools.general.cancel"/>" /> + </div> + + </form> + +<% if (bMore || pageResult > 1) { %> + +<p class="alert"><fmt:message key="jsp.tools.itemmap-browse.info.change-page"/></p> +<div class="col-md-12"> +<% if (pageResult > 1) { %> + <form method="post" class="standard10" action=""> + <input type="hidden" name="cid" value="<%=collection.getID()%>"/> + <input type="hidden" name="action" value="search"/> + <input type="hidden" name="index" id="index" value="<%= index %>"/> + <input type="hidden" name="query" id="query" value="<%= query %>"/> + <input type="hidden" name="page" id="page" value="<%= pageResult -1 %>"/> + <input class="btn btn-default col-md-6" type="submit" value="<fmt:message key="jsp.tools.itemmap-browse.previous.button"/>"/> </form> +<% } + if (bMore) { %> + + <form method="post" class="standard10" action=""> + <input type="hidden" name="cid" value="<%=collection.getID()%>"/> + <input type="hidden" name="action" value="search"/> + <input type="hidden" name="index" id="index" value="<%= index %>"/> + <input type="hidden" name="query" id="query" value="<%= query %>"/> + <input type="hidden" name="page" id="page" value="<%= pageResult +1 %>"/> + <input class="btn btn-primary col-md-6" type="submit" value="<fmt:message key="jsp.tools.itemmap-browse.next.button"/>"/> + </form> + +<% } %> +</div> +<% +} +%> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/itemmap-info.jsp b/dspace-jspui/src/main/webapp/tools/itemmap-info.jsp index 363f28ce41af578dade46f4ba9e2cf1119d3756f..0975041abf76a503c96bb869f9a2dc60bcd4caf5 100644 --- a/dspace-jspui/src/main/webapp/tools/itemmap-info.jsp +++ b/dspace-jspui/src/main/webapp/tools/itemmap-info.jsp @@ -38,11 +38,11 @@ LinkedList processedItems = (LinkedList)request.getAttribute("processedItems"); %> -<dspace:layout titlekey="jsp.tools.itemmap-info.title"> +<dspace:layout style="submission" titlekey="jsp.tools.itemmap-info.title"> <h2><fmt:message key="jsp.tools.itemmap-info.heading"/></h2> - <p> + <div class="alert"> <% if (message.equals("none-selected")) { %> <fmt:message key="jsp.tools.itemmap-info.msg.none-selected" /> <% } else if (message.equals("none-removed")) { %> @@ -62,10 +62,10 @@ </fmt:message><br/> <% } %> <% } %> - </p> + </div> <form method="post"> <input type="hidden" name="cid" value="<%=collection.getID()%>"/> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.itemmap-info.button.continue"/>"/> + <input class="btn btn-default" type="submit" name="submit" value="<fmt:message key="jsp.tools.itemmap-info.button.continue"/>"/> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/itemmap-main.jsp b/dspace-jspui/src/main/webapp/tools/itemmap-main.jsp index d373679ed41e12bf8dd4098f7bdc71f640b4ccfe..acef6eab309c8f7e9ef35cfaf9a5ae047b815335 100644 --- a/dspace-jspui/src/main/webapp/tools/itemmap-main.jsp +++ b/dspace-jspui/src/main/webapp/tools/itemmap-main.jsp @@ -20,6 +20,7 @@ - count_import - how many items are 'virtual' --%> +<%@page import="java.util.List"%> <%@ page contentType="text/html;charset=UTF-8" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" @@ -45,21 +46,25 @@ Map collection_counts = (Map)request.getAttribute("collection_counts"); Collection [] all_collections = (Collection[]) request.getAttribute("all_collections"); + List<String> searchIndices = (List<String>) request.getAttribute("searchIndices"); + String prefixKey = (String) request.getAttribute("prefixKey"); + Boolean searchError = (Boolean) request.getAttribute("searchError"); + boolean bSearchError = searchError != null?searchError:false; %> -<dspace:layout titlekey="jsp.tools.itemmap-main.title"> +<dspace:layout style="submission" titlekey="jsp.tools.itemmap-main.title"> <%-- <h2>Item Mapper - Map Items from Other Collections</h2> --%> - <h2><fmt:message key="jsp.tools.itemmap-main.heading"/></h2> + <h1><fmt:message key="jsp.tools.itemmap-main.heading"/></h1> <%-- <p>Collection: "<%=collection.getMetadata("name")%>"</p> --%> - <p><fmt:message key="jsp.tools.itemmap-main.collection"> + <h2><fmt:message key="jsp.tools.itemmap-main.collection"> <fmt:param><%=collection.getMetadata("name")%></fmt:param> - </fmt:message></p> + </fmt:message></h2> <%-- <p>There are <%=count_native%> items owned by this collection, and <%=count_import%> items mapped in from other collections.</p> --%> - <p><fmt:message key="jsp.tools.itemmap-main.info1"> + <p class="alert alert-info"><fmt:message key="jsp.tools.itemmap-main.info1"> <fmt:param><%=count_native%></fmt:param> <fmt:param><%=count_import%></fmt:param> </fmt:message></p> @@ -117,17 +122,38 @@ <%-- <h3>Import By Author Match</h3> Enter part of an author's name for a list of matching items<br> --%> <h3><fmt:message key="jsp.tools.itemmap-main.info4"/></h3> - <fmt:message key="jsp.tools.itemmap-main.info5"/><br/> - - <form method="post" action=""> - <input type="hidden" name="cid" value="<%=collection.getID()%>"/> - <input name="namepart"/> - <%-- <input type="submit" name="action" value="Search Authors"/> --%> - <input type="hidden" name="action" value="Search Authors"/> - <input type="submit" value="<fmt:message key="jsp.tools.itemmap-main.search.button"/>" /> - <br/> - </form> - + <p><fmt:message key="jsp.tools.itemmap-main.info5"/></p> + + <form method="post" class="standard10" action=""> + <div class="form-group"> + <div class="input-group col-md-10"> + <input type="hidden" name="cid" value="<%=collection.getID()%>"/> + <input type="hidden" name="action" value="search"/> + <span class="col-md-4"> + <select class="form-control" name="index" id="index"> + <% + for (String index : searchIndices) + { + String key = prefixKey + index; + %> + <option value="<%= index %>"><fmt:message key="<%= key %>"/></option> + <% + } + %> + </select></span> + <span class="col-md-8"> + <input class="form-control" id="query" name="query" size="50"/> + + </span> + + </div> + <input class="btn btn-default" type="submit" value="<fmt:message key="jsp.tools.itemmap-main.search.button"/>" /> + + </div> + </form> + <% if (bSearchError) { %> + <p class="alert alert-warning"><fmt:message key="jsp.tools.itemmap-main.search-error"/></p> + <% } %> <%-- <h3>Browse Items Imported From Collections:</h3> --%> <h3><fmt:message key="jsp.tools.itemmap-main.info6"/></h3> @@ -142,7 +168,7 @@ { %> <%-- <p>This collection has no items mapped into it.</p> --%> - <p><fmt:message key="jsp.tools.itemmap-main.info8"/></p> + <p class="alert alert-warning"><fmt:message key="jsp.tools.itemmap-main.info8"/></p> <% } diff --git a/dspace-jspui/src/main/webapp/tools/move-item.jsp b/dspace-jspui/src/main/webapp/tools/move-item.jsp index c1053c1d977904b704ce3b22614f331f1bbe93a4..c95a80fc8e497e7c6a3f0792d5784e0980efc262 100644 --- a/dspace-jspui/src/main/webapp/tools/move-item.jsp +++ b/dspace-jspui/src/main/webapp/tools/move-item.jsp @@ -25,28 +25,19 @@ Item item = (Item)request.getAttribute("item"); %> -<dspace:layout titlekey="jsp.tools.move-item.title"> - - <form action="<%=request.getContextPath()%>/tools/edit-item" method="post"> - - <table class="miscTable" align="center"> - <tr> - <td class="evenRowEvenCol" colspan="2"> - <table> - <tr> - <td class="standard"> - <small><strong><fmt:message key="jsp.tools.move-item.item.name.msg"/></strong></small> - </td> - <td class="standard"> - <font color="#FF0000"><%=item.getMetadata("dc", "title", null, Item.ANY)[0].value%></font> - </td> - </tr> - <tr> - <td class="standard"> - <small><strong><fmt:message key="jsp.tools.move-item.collection.from.msg"/></strong></small> - </td> - <td class="standard"> - <select name="collection_from_id"> +<dspace:layout style="submission" titlekey="jsp.tools.move-item.title"> + <div class="container"> + <form class="form-horizontal" action="<%=request.getContextPath()%>/tools/edit-item" method="post"> + <div class="form-group"> + <label><fmt:message key="jsp.tools.move-item.item.name.msg"/></label> + <%=item.getMetadata("dc", "title", null, Item.ANY)[0].value%></font> + </div> + <div class="form-group"> + <div class="input-group"> + <span class="input-group-addon"> + <label for="collection_from_id"><fmt:message key="jsp.tools.move-item.collection.from.msg"/></label> + </span> + <select class="form-control" name="collection_from_id"> <% for (int i = 0; i < linkedCollections.length; i++) { @@ -56,14 +47,14 @@ } %> </select> - </td> - </tr> - <tr> - <td class="standard"> - <small><strong><fmt:message key="jsp.tools.move-item.collection.to.msg"/></strong></small> - </td> - <td class="standard"> - <select name="collection_to_id"> + </div> + </div> + <div class="form-group"> + <div class="input-group"> + <span class="input-group-addon"> + <label for="collection_to_id"><fmt:message key="jsp.tools.move-item.collection.to.msg"/></label> + </span> + <select class="form-control" name="collection_to_id"> <% //Later on find a away to display in a tree format with the linked one disabled? for (int i = 0; i < notLinkedCollections.length; i++) @@ -74,25 +65,22 @@ } %> </select> - </td> - </tr> - <tr> - <td class="standard"><small><strong><fmt:message key="jsp.tools.move-item.inheritpolicies"/></strong></small></td> - <td class="standard"><input type="checkbox" name="inheritpolicies" /></td> - </tr> - <tr> - <td class="standard"></td> - <td class="standard"> - <input type="submit" name="submit" value="<fmt:message key="jsp.tools.move-item.button"/>"/> - </td> - </tr> - </table> - </td> - </tr> - </table> + </div> + </div> + <div class="form-group"> + <div class="input-group"> + <span class="input-group-addon"> + <input type="checkbox" name="inheritpolicies" /> + </span> + <span class="form-control"><fmt:message key="jsp.tools.move-item.inheritpolicies"/></span> + </div> + </div> + <div class="col-md-offset-5"> + <input class="btn btn-success col-md-4" type="submit" name="submit" value="<fmt:message key="jsp.tools.move-item.button"/>"/> + </div> <input type="hidden" name="action" value="<%=EditItemServlet.CONFIRM_MOVE_ITEM%>" /> <input type="hidden" name="item_id" value="<%=item.getID() %>"/> </form> - +</div> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/tools/upload-bitstream.jsp b/dspace-jspui/src/main/webapp/tools/upload-bitstream.jsp index 103814d57184c7dac836aeba578c90f93b993307..bfffcf8a0dfea3a822ab01b03778daf306de8647 100644 --- a/dspace-jspui/src/main/webapp/tools/upload-bitstream.jsp +++ b/dspace-jspui/src/main/webapp/tools/upload-bitstream.jsp @@ -28,7 +28,7 @@ request.setAttribute("LanguageSwitch", "hide"); %> -<dspace:layout titlekey="jsp.tools.upload-bitstream.title" +<dspace:layout style="submission" titlekey="jsp.tools.upload-bitstream.title" navbar="admin" locbar="link" parenttitlekey="jsp.administer" @@ -39,17 +39,17 @@ <h1><fmt:message key="jsp.tools.upload-bitstream.title"/></h1> <%-- <p>Select the bitstream to upload</p> --%> - <p><fmt:message key="jsp.tools.upload-bitstream.info"/></p> + <p class="alert alert-info"><fmt:message key="jsp.tools.upload-bitstream.info"/></p> <form method="post" enctype="multipart/form-data" action=""> - <p align="center"> - <input type="file" size="40" name="file"/> - </p> + <div class="container row"> + <input class="form-control" type="file" size="40" name="file"/> + </div> <input type="hidden" name="item_id" value="<%= item.getID() %>"/> - + <br/> <!-- <p align="center"><input type="submit" name="submit" value="Upload"></p> --> - <p align="center"><input type="submit" name="submit" value="<fmt:message key="jsp.tools.upload-bitstream.upload"/>" /></p> + <div class="container row col-md-offset-5"><input class="btn btn-success col-md-4" type="submit" name="submit" value="<fmt:message key="jsp.tools.upload-bitstream.upload"/>" /></div> </form> </dspace:layout> diff --git a/dspace-jspui/src/main/webapp/workspace/ws-main.jsp b/dspace-jspui/src/main/webapp/workspace/ws-main.jsp index 72661d0d769e0bbef6935811213662ca0bbdd19d..7657f2b5e4ed69852b9061f1d0379b4f7211d36c 100644 --- a/dspace-jspui/src/main/webapp/workspace/ws-main.jsp +++ b/dspace-jspui/src/main/webapp/workspace/ws-main.jsp @@ -44,42 +44,32 @@ parentlink="/mydspace" parenttitlekey="jsp.mydspace" titlekey="jsp.workspace.ws-main.title"> - - <table width="100%" border="0"> - <tr> - <td align="left"> - <h1> - <fmt:message key="jsp.workspace.ws-main.wsitem"/> - </h1> - </td> - <td align="right" class="standard"> - <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#mydspace\"%>"><fmt:message key="jsp.help"/></dspace:popup> - </td> - </tr> - </table> - -<%-- <h2><%= title %></h2> --%> +<div class="container"> + <h2> <% if (titleArray.length > 0) { %> - <h2><%= titleArray[0].value %></h2> + <%= titleArray[0].value %> <% } else { %> - <h2><fmt:message key="jsp.general.untitled"/></h2> + <fmt:message key="jsp.general.untitled"/> <% } %> + <small><fmt:message key="jsp.workspace.ws-main.wsitem"/></small> + <dspace:popup page="<%= LocaleSupport.getLocalizedMessage(pageContext, \"help.index\") + \"#mydspace\"%>"><fmt:message key="jsp.help"/></dspace:popup> - <p><strong><a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a></strong></p> + </h2> + <p><a href="mailto:<%= submitter.getEmail() %>"><%= Utils.addEntities(submitter.getFullName()) %></a></p> <p><fmt:message key="jsp.workspace.ws-main.submitmsg"/> <%= workspaceItem.getCollection().getMetadata("name") %></p> - <table class="miscTable" align="center"> + <table class="table"> <tr> <th class="oddRowOddCol"><fmt:message key="jsp.workspace.ws-main.optionheading"/></th> <th class="oddRowEvenCol"><fmt:message key="jsp.workspace.ws-main.descheading"/></th> @@ -90,7 +80,7 @@ <input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>"/> <input type="hidden" name="workspace_id" value="<%= workspaceItem.getID() %>"/> <input type="hidden" name="resume" value="<%= workspaceItem.getID() %>"/> - <input type="submit" name="submit_resume" value="<fmt:message key="jsp.workspace.ws-main.button.edit"/>"/> + <input class="col-md-2 btn btn-primary btn-group-justified" type="submit" name="submit_resume" value="<fmt:message key="jsp.workspace.ws-main.button.edit"/>"/> </form> </td> <td class="evenRowEvenCol"> @@ -102,7 +92,7 @@ <td class="oddRowOddCol" align="center"> <form action="<%= request.getContextPath() %>/view-workspaceitem" method="post"> <input type="hidden" name="workspace_id" value="<%= workspaceItem.getID() %>"/> - <input type="submit" name="submit_view" value="<fmt:message key="jsp.workspace.ws-main.button.view"/>"/> + <input class="col-md-2 btn btn-default btn-group-justified" type="submit" name="submit_view" value="<fmt:message key="jsp.workspace.ws-main.button.view"/>"/> </form> </td> <td class="oddRowEvenCol"> @@ -115,7 +105,7 @@ <form action="<%= request.getContextPath() %>/mydspace" method="post"> <input type="hidden" name="step" value="<%= MyDSpaceServlet.MAIN_PAGE %>"/> <input type="hidden" name="workspace_id" value="<%= workspaceItem.getID() %>"/> - <input type="submit" name="submit_delete" value="<fmt:message key="jsp.workspace.ws-main.button.remove"/>"/> + <input class="col-md-2 btn btn-danger btn-group-justified" type="submit" name="submit_delete" value="<fmt:message key="jsp.workspace.ws-main.button.remove"/>"/> </form> </td> <td class="evenRowEvenCol"> @@ -126,5 +116,5 @@ </table> <p><a href="<%= request.getContextPath() %>/mydspace"><fmt:message key="jsp.mydspace.general.returnto-mydspace"/></a></p> - +</div> </dspace:layout> diff --git a/dspace-lni/dspace-lni-client/pom.xml b/dspace-lni/dspace-lni-client/pom.xml index d73c72acb1fcf3770bef18e6963f04e75a6efeb0..f58ec0e01ee802a28d9f2714a2d9cd06d73d8ebf 100644 --- a/dspace-lni/dspace-lni-client/pom.xml +++ b/dspace-lni/dspace-lni-client/pom.xml @@ -11,7 +11,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>../..</relativePath> </parent> @@ -46,7 +46,7 @@ <execution> <phase>generate-sources</phase> <configuration> - <tasks> + <target> <taskdef resource="axis-tasks.properties" classpathref="maven.compile.classpath" /> <mkdir dir="src/main/config" /> <axis-java2wsdl classname="org.dspace.app.dav.LNISoapServlet" location="http://localhost/dspace/lni/DSpaceLNI" methods="lookup,propfind,proppatch,copy" namespace="http://dspace.org/xmlns/lni" output="src/main/resources/dspace-lni.wsdl" /> @@ -54,7 +54,7 @@ <axis-wsdl2java output="src/main/java" verbose="true" url="src/main/resources/dspace-lni.wsdl"> <mapping namespace="http://dspace.org/xmlns/lni" package="org.dspace.app.dav.client" /> </axis-wsdl2java> - </tasks> + </target> </configuration> <goals> <goal>run</goal> diff --git a/dspace-lni/pom.xml b/dspace-lni/pom.xml index 86009aba1e7fb116482cf0210b93471182fe1587..400c41979a052931537a73a0e4c10ee4c3a3d6b6 100644 --- a/dspace-lni/pom.xml +++ b/dspace-lni/pom.xml @@ -11,7 +11,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> diff --git a/dspace-lni/src/main/java/org/dspace/app/dav/DAVCollection.java b/dspace-lni/src/main/java/org/dspace/app/dav/DAVCollection.java index 50d7d00e8356d2b5db8cbfb645e3c45c32b0db55..e8d97063e5c3a75077a68f2e8fce46487ff8d500 100644 --- a/dspace-lni/src/main/java/org/dspace/app/dav/DAVCollection.java +++ b/dspace-lni/src/main/java/org/dspace/app/dav/DAVCollection.java @@ -57,8 +57,8 @@ class DAVCollection extends DAVDSpaceObject private Collection collection = null; /** The temporary upload directory. */ - private static String tempDirectory = ConfigurationManager - .getProperty("upload.temp.dir"); + private static String tempDirectory = (ConfigurationManager.getProperty("upload.temp.dir") != null) + ? ConfigurationManager.getProperty("upload.temp.dir") : System.getProperty("java.io.tmpdir"); /** The Constant short_descriptionProperty. */ private static final Element short_descriptionProperty = new Element( diff --git a/dspace-lni/src/main/java/org/dspace/app/dav/DAVItem.java b/dspace-lni/src/main/java/org/dspace/app/dav/DAVItem.java index b419b4ce2d4c74cd42ae6b5fbfe22e9e4d429c74..608ac08b704ae0d89e05cb4e15c3b0bcd7e581a6 100644 --- a/dspace-lni/src/main/java/org/dspace/app/dav/DAVItem.java +++ b/dspace-lni/src/main/java/org/dspace/app/dav/DAVItem.java @@ -467,7 +467,8 @@ class DAVItem extends DAVDSpaceObject try { // Create a temporary file to disseminate into - String tempDirectory = ConfigurationManager.getProperty("upload.temp.dir"); + String tempDirectory = (ConfigurationManager.getProperty("upload.temp.dir") != null) + ? ConfigurationManager.getProperty("upload.temp.dir") : System.getProperty("java.io.tmpdir"); File tempFile = File.createTempFile("DAVItemGet" + this.item.hashCode(), null, new File(tempDirectory)); tempFile.deleteOnExit(); diff --git a/dspace-lni/src/main/java/org/dspace/app/dav/DAVSite.java b/dspace-lni/src/main/java/org/dspace/app/dav/DAVSite.java index 7b051e237f40ff67d694fb36cac97fcce333b26e..ecb9ceb826b195491c9c3d76ae724d6f7029f308 100644 --- a/dspace-lni/src/main/java/org/dspace/app/dav/DAVSite.java +++ b/dspace-lni/src/main/java/org/dspace/app/dav/DAVSite.java @@ -20,6 +20,8 @@ import org.dspace.authorize.AuthorizeManager; import org.dspace.content.Community; import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; +import org.dspace.core.LicenseManager; +import org.dspace.core.NewsManager; import org.jdom.Element; @@ -61,7 +63,7 @@ class DAVSite extends DAVResource /** * Instantiates a new DAV site. - * + * * @param context the context * @param request the request * @param response the response @@ -76,14 +78,14 @@ class DAVSite extends DAVResource /** * Match resource URI. - * + * * @param context the context * @param request the request * @param response the response * @param pathElt the path elt - * + * * @return the DAV resource - * + * * @throws DAVStatusException the DAV status exception * @throws SQLException the SQL exception */ @@ -143,15 +145,15 @@ class DAVSite extends DAVResource } else if (elementsEqualIsh(property, news_topProperty)) { - value = ConfigurationManager.readNewsFile("news-top.html"); + value = NewsManager.readNewsFile("news-top.html"); } else if (elementsEqualIsh(property, news_sideProperty)) { - value = ConfigurationManager.readNewsFile("news-side.html"); + value = NewsManager.readNewsFile("news-side.html"); } else if (elementsEqualIsh(property, default_licenseProperty)) { - value = ConfigurationManager.getDefaultSubmissionLicense(); + value = LicenseManager.getDefaultSubmissionLicense(); } else { @@ -186,7 +188,7 @@ class DAVSite extends DAVResource throw new DAVStatusException(HttpServletResponse.SC_FORBIDDEN, "Not authorized to modify this property."); } - ConfigurationManager.writeNewsFile("news-top.html", newValue); + NewsManager.writeNewsFile("news-top.html", newValue); } else if (elementsEqualIsh(prop, news_sideProperty)) { @@ -195,7 +197,7 @@ class DAVSite extends DAVResource throw new DAVStatusException(HttpServletResponse.SC_FORBIDDEN, "Not authorized to modify this property."); } - ConfigurationManager.writeNewsFile("news-side.html", newValue); + NewsManager.writeNewsFile("news-side.html", newValue); } else if (elementsEqualIsh(prop, displaynameProperty)) { diff --git a/dspace-lni/src/main/java/org/dspace/app/dav/LoadDSpaceLNIConfig.java b/dspace-lni/src/main/java/org/dspace/app/dav/LoadDSpaceLNIConfig.java deleted file mode 100644 index f777bffbfa2dc428dd587a59dd82198926fade27..0000000000000000000000000000000000000000 --- a/dspace-lni/src/main/java/org/dspace/app/dav/LoadDSpaceLNIConfig.java +++ /dev/null @@ -1,44 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.dav; - -import javax.servlet.http.HttpServlet; - -import org.dspace.core.ConfigurationManager; - -/** - * Simple servlet to load in DSpace and log4j configurations. Should always be - * started up before other servlets (use <loadOnStartup>) - * - * This class holds code to be removed in the next version of the DSpace XMLUI, - * it is now managed by a Shared Context Listener inthe dspace-api project. - * - * It is deprecated, rather than removed to maintain backward compatibility for - * local DSpace 1.5.x customized overlays. - * - * TODO: Remove in trunk - * - * @deprecated Use Servlet Context Listener provided in dspace-api (remove in > - * 1.5.x) - * @author Robert Tansley - * @version $Revision$ - */ -public class LoadDSpaceLNIConfig extends HttpServlet -{ - public void init() - { - if(!ConfigurationManager.isConfigured()) - { - // Get config parameter - String config = getServletContext().getInitParameter("dspace-config"); - - // Load in DSpace config - ConfigurationManager.loadConfig(config); - } - } -} diff --git a/dspace-lni/src/main/webapp/WEB-INF/web.xml b/dspace-lni/src/main/webapp/WEB-INF/web.xml index 226da84869c8391f820eacb6f7f04934152d98e0..f1625ad78bce1025e3b05386d6372395a3de73f7 100644 --- a/dspace-lni/src/main/webapp/WEB-INF/web.xml +++ b/dspace-lni/src/main/webapp/WEB-INF/web.xml @@ -21,8 +21,24 @@ </description> </context-param> - <!-- - Listener to initialise DSpace configuration and clean up the application + <!-- new ConfigurationService initialization for dspace.dir --> + <context-param> + <param-name>dspace.dir</param-name> + <param-value>${dspace.dir}</param-value> + <description> + The location of the main DSpace configuration file + </description> + </context-param> + + + + <!-- kernel start listener (from impl), starts up the kernel for standalong webapps --> + <listener> + <listener-class>org.dspace.servicemanager.servlet.DSpaceKernelServletContextListener</listener-class> + </listener> + + <!-- + Listener to initialise DSpace configuration and clean up the application --> <listener> <listener-class> diff --git a/dspace-oai/pom.xml b/dspace-oai/pom.xml index c5c690d51c598c6af37227a19841ff4fe5293f83..990aee6c9c7d802608ed590bcd2530c78e116622 100644 --- a/dspace-oai/pom.xml +++ b/dspace-oai/pom.xml @@ -8,7 +8,7 @@ <parent> <artifactId>dspace-parent</artifactId> <groupId>org.dspace</groupId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> @@ -81,7 +81,17 @@ <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> - <version>3.3.0</version> + <version>${solr.version}</version> + <exclusions> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>jcl-over-slf4j</artifactId> + </exclusion> + <exclusion> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>javax.servlet</groupId> @@ -91,12 +101,10 @@ <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> - <version>1.5.6</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> - <version>1.5.6</version> </dependency> <dependency> <groupId>com.google.guava</groupId> diff --git a/dspace-oai/src/main/java/org/dspace/xoai/DSpaceOAIDataProvider.java b/dspace-oai/src/main/java/org/dspace/xoai/DSpaceOAIDataProvider.java index 767ebe7e3e15ab0447a561f961a81b80fb14abb9..0d4180015bba2602b8ff847358802bc4df2436f7 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/DSpaceOAIDataProvider.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/DSpaceOAIDataProvider.java @@ -158,6 +158,11 @@ public class DSpaceOAIDataProvider extends HttpServlet "Requested OAI context \"" + request.getPathInfo().replace("/", "") + "\" does not exist"); + } finally { + if(context != null && context.isValid()) + { + context.abort(); + } } } diff --git a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java index d2f9d07af49c210a14855d4da10506d504a1dd0d..9988be24cb3a8056aa01b1b75e8400f2d0b94b03 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/app/XOAI.java @@ -175,9 +175,9 @@ public class XOAI .println("Incremental import. Searching for documents modified after: " + last.toString()); - String sqlQuery = "SELECT item_id FROM item WHERE in_archive=TRUE AND last_modified > ?"; + String sqlQuery = "SELECT item_id FROM item WHERE in_archive=TRUE AND discoverable=TRUE AND last_modified > ?"; if(DatabaseManager.isOracle()){ - sqlQuery = "SELECT item_id FROM item WHERE in_archive=1 AND last_modified > ?"; + sqlQuery = "SELECT item_id FROM item WHERE in_archive=1 AND discoverable=1 AND last_modified > ?"; } try @@ -200,9 +200,9 @@ public class XOAI try { - String sqlQuery = "SELECT item_id FROM item WHERE in_archive=TRUE"; + String sqlQuery = "SELECT item_id FROM item WHERE in_archive=TRUE AND discoverable=TRUE"; if(DatabaseManager.isOracle()){ - sqlQuery = "SELECT item_id FROM item WHERE in_archive=1"; + sqlQuery = "SELECT item_id FROM item WHERE in_archive=1 AND discoverable=1"; } TableRowIterator iterator = DatabaseManager.query(_context, diff --git a/dspace-oai/src/main/java/org/dspace/xoai/solr/DSpaceSolrServer.java b/dspace-oai/src/main/java/org/dspace/xoai/solr/DSpaceSolrServer.java index 8bbd49b15c9680d5c91de3c4ff0028b3610015dd..fbddda91600346743db51ae10b9d3080cbc74e33 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/solr/DSpaceSolrServer.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/solr/DSpaceSolrServer.java @@ -8,13 +8,11 @@ package org.dspace.xoai.solr; -import java.net.MalformedURLException; - import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.solr.client.solrj.SolrServer; import org.apache.solr.client.solrj.SolrServerException; -import org.apache.solr.client.solrj.impl.CommonsHttpSolrServer; +import org.apache.solr.client.solrj.impl.HttpSolrServer; import org.dspace.core.ConfigurationManager; /** @@ -33,14 +31,10 @@ public class DSpaceSolrServer { try { - _server = new CommonsHttpSolrServer( + _server = new HttpSolrServer( ConfigurationManager.getProperty("oai", "solr.url")); log.debug("Solr Server Initialized"); - } - catch (MalformedURLException e) - { - throw new SolrServerException(e); - } + } catch (Exception e) { log.error(e.getMessage(), e); diff --git a/dspace-oai/src/main/java/org/dspace/xoai/util/DateUtils.java b/dspace-oai/src/main/java/org/dspace/xoai/util/DateUtils.java index ddfdbe321f7aa8108735e35026a9be0e3dd11b46..dd69ff9417069c6de18f70f95c957dc277ed5e7d 100644 --- a/dspace-oai/src/main/java/org/dspace/xoai/util/DateUtils.java +++ b/dspace-oai/src/main/java/org/dspace/xoai/util/DateUtils.java @@ -7,13 +7,14 @@ */ package org.dspace.xoai.util; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; + import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; - -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; +import java.util.TimeZone; /** * @@ -33,8 +34,8 @@ public class DateUtils // 2008-01-01T00:00:00Z SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.'000Z'"); if (!init) sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.'999Z'"); + sdf.setTimeZone(TimeZone.getTimeZone("UTC")); String ret = sdf.format(date); - System.out.println(ret); return ret; } diff --git a/dspace-services/pom.xml b/dspace-services/pom.xml index d2a6a71215a3d2fcbe21c760cf1e79564a97fbd9..209923cfbf19bebd660983e48b45752809aefe2a 100644 --- a/dspace-services/pom.xml +++ b/dspace-services/pom.xml @@ -9,7 +9,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> </parent> <properties> @@ -22,7 +22,6 @@ <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> - <version>1.5.6</version> </dependency> <!-- spring service manager --> <dependency> @@ -48,6 +47,10 @@ <artifactId>servlet-api</artifactId> <scope>provided</scope> </dependency> + <dependency> + <groupId>javax.mail</groupId> + <artifactId>mail</artifactId> + </dependency> <!-- SPECIAL CASE - need JUNIT at build time and testing time --> <dependency> <groupId>junit</groupId> @@ -75,7 +78,6 @@ <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> - <version>1.5.6</version> </dependency> <dependency> <groupId>log4j</groupId> diff --git a/dspace-services/src/main/java/org/dspace/kernel/config/SpringLoader.java b/dspace-services/src/main/java/org/dspace/kernel/config/SpringLoader.java index d9b57c789126d1b602502769bb2028c836b1fc2e..8bde2a8dc6d7afd7e7a842c93fb4b506250b47ed 100644 --- a/dspace-services/src/main/java/org/dspace/kernel/config/SpringLoader.java +++ b/dspace-services/src/main/java/org/dspace/kernel/config/SpringLoader.java @@ -10,11 +10,9 @@ package org.dspace.kernel.config; import org.dspace.services.ConfigurationService; /** - * User: kevin (kevin at atmire.com) - * Date: 3-aug-2011 - * Time: 11:19:33 - * * Interface that is used so that modules can determine their own spring file locations + * + * @author Kevin Van de Velde (kevin at atmire dot com) */ public interface SpringLoader { @@ -27,5 +25,4 @@ public interface SpringLoader { */ public String[] getResourcePaths(ConfigurationService configurationService); - } diff --git a/dspace-services/src/main/java/org/dspace/servicemanager/config/DSpaceConfigurationService.java b/dspace-services/src/main/java/org/dspace/servicemanager/config/DSpaceConfigurationService.java index 4d4a5ef2f1b16a993d175855daf30e8b3e2ec299..7a7f1c3a4b671af7cdb83fe91f64f517a28cfdf6 100644 --- a/dspace-services/src/main/java/org/dspace/servicemanager/config/DSpaceConfigurationService.java +++ b/dspace-services/src/main/java/org/dspace/servicemanager/config/DSpaceConfigurationService.java @@ -64,6 +64,7 @@ public final class DSpaceConfigurationService implements ConfigurationService { /* (non-Javadoc) * @see org.dspace.services.ConfigurationService#getAllProperties() */ + @Override public Map<String, String> getAllProperties() { Map<String, String> props = new LinkedHashMap<String, String>(); // for (Entry<String, DSpaceConfig> config : configuration.entrySet()) { @@ -79,6 +80,7 @@ public final class DSpaceConfigurationService implements ConfigurationService { /* (non-Javadoc) * @see org.dspace.services.ConfigurationService#getProperties() */ + @Override public Properties getProperties() { Properties props = new Properties(); for (DSpaceConfig config : configuration.values()) { @@ -90,6 +92,7 @@ public final class DSpaceConfigurationService implements ConfigurationService { /* (non-Javadoc) * @see org.dspace.services.ConfigurationService#getProperty(java.lang.String) */ + @Override public String getProperty(String name) { DSpaceConfig config = configuration.get(name); String value = null; @@ -102,6 +105,7 @@ public final class DSpaceConfigurationService implements ConfigurationService { /* (non-Javadoc) * @see org.dspace.services.ConfigurationService#getPropertyAsType(java.lang.String, java.lang.Class) */ + @Override public <T> T getPropertyAsType(String name, Class<T> type) { String value = getProperty(name); return convert(value, type); @@ -110,6 +114,7 @@ public final class DSpaceConfigurationService implements ConfigurationService { /* (non-Javadoc) * @see org.dspace.services.ConfigurationService#getPropertyAsType(java.lang.String, java.lang.Object) */ + @Override public <T> T getPropertyAsType(String name, T defaultValue) { return getPropertyAsType(name, defaultValue, false); } @@ -118,6 +123,7 @@ public final class DSpaceConfigurationService implements ConfigurationService { * @see org.dspace.services.ConfigurationService#getPropertyAsType(java.lang.String, java.lang.Object, boolean) */ @SuppressWarnings("unchecked") + @Override public <T> T getPropertyAsType(String name, T defaultValue, boolean setDefaultIfNotFound) { String value = getProperty(name); T property = null; @@ -141,6 +147,7 @@ public final class DSpaceConfigurationService implements ConfigurationService { /* (non-Javadoc) * @see org.dspace.services.ConfigurationService#setProperty(java.lang.String, java.lang.Object) */ + @Override public boolean setProperty(String name, Object value) { if (name == null) { throw new IllegalArgumentException("name cannot be null for setting configuration"); @@ -300,8 +307,35 @@ public final class DSpaceConfigurationService implements ConfigurationService { // loading from files code /** - * Loads up the default initial configuration from the dspace config - * files in the file home and on the classpath. + * Loads up the default initial configuration from the DSpace configuration + * files in the file home and on the classpath. Order: + * <ol> + * <li>Create {@code serverId} from local host name if available.</li> + * <li>Create {@code dspace.testing = false}. + * <li>Determine the value of {@code dspace.dir} and add to configuration.</li> + * <li>Load {@code classpath:config/dspace_defaults.cfg}.</li> + * <li>Copy system properties with names beginning "dspace." <em>except</em> + * {@code dspace.dir}, removing the "dspace." prefix from the name.</li> + * <li>Load all {@code classpath:dspace/config-*.cfg} using whatever + * matched "*" as module prefix.</li> + * <li>Load all {@code ${dspace.dir}/config/modules/*.cfg} using whatever + * matched "*" as module prefix.</li> + * <li>Load {@code classpath:dspace.cfg}.</li> + * <li>Load from the path in the system property {@code dspace.configuration} + * if defined, or {@code ${dspace.dir}/config/dspace.cfg}.</li> + * <li>Perform variable substitutions throughout the assembled configuration.</li> + * </ol> + * + * <p>The initial value of {@code dspace.dir} will be:</p> + * <ol> + * <li>the value of the system property {@code dspace.dir} if defined;</li> + * <li>else the value of {@code providedHome} if not null;</li> + * <li>else the servlet container's home + "/dspace/" if defined (see {@link getCatalina()});</li> + * <li>else the user's home directory if defined;</li> + * <li>else "/". + * </ol> + * + * @param providedHome DSpace home directory, or null. */ public void loadInitialConfig(String providedHome) { Map<String, String> configMap = new LinkedHashMap<String, String>(); @@ -318,10 +352,10 @@ public final class DSpaceConfigurationService implements ConfigurationService { // now we load the settings from properties files String homePath = System.getProperty(DSPACE_HOME); - // now we load from the provided parameter if its not null + // now we load from the provided parameter if its not null if (providedHome != null && homePath == null) { - homePath = providedHome; - } + homePath = providedHome; + } if (homePath == null) { String catalina = getCatalina(); @@ -410,8 +444,13 @@ public final class DSpaceConfigurationService implements ConfigurationService { pushPropsToMap(configMap, readPropertyResource(DSPACE + DOT_CONFIG)); // read all the known files from the home path that are properties files - pushPropsToMap(configMap, readPropertyFile(homePath + File.separatorChar + DSPACE_CONFIG_PATH)); -// pushPropsToMap(configMap, readPropertyFile(homePath + File.separatorChar + DSPACE_CONFIG_PATH)); + String configPath = System.getProperty("dspace.configuration"); + if (null == configPath) + { + configPath = homePath + File.separatorChar + DSPACE_CONFIG_PATH; + } + pushPropsToMap(configMap, readPropertyFile(configPath)); + // TODO: still use this local file loading? // pushPropsToMap(configMap, readPropertyFile(homePath + File.separatorChar + "local" + DOT_PROPERTIES)); diff --git a/dspace-services/src/main/java/org/dspace/services/caching/CachingServiceImpl.java b/dspace-services/src/main/java/org/dspace/services/caching/CachingServiceImpl.java index ce4f31a799f245632305952a9705ffb76977a793..3570f5d56a18c3304d370e50f013670a4c21c980 100644 --- a/dspace-services/src/main/java/org/dspace/services/caching/CachingServiceImpl.java +++ b/dspace-services/src/main/java/org/dspace/services/caching/CachingServiceImpl.java @@ -223,6 +223,9 @@ public final class CachingServiceImpl implements CachingService, InitializedServ log.info("init()"); // get settings reloadConfig(); + + // don't display the EhCache update notice in logs - it's meant for developers, not users + System.setProperty("net.sf.ehcache.skipUpdateCheck", "true"); // make sure we have a cache manager if (cacheManager == null) { diff --git a/dspace-services/src/main/resources/spring/spring-dspace-core-services.xml b/dspace-services/src/main/resources/spring/spring-dspace-core-services.xml index 61422b01e3dab73fe36a08a03a0df46deeed1cc8..4ac43874cda1458ea84b7ec3616095bb82d8ba1c 100644 --- a/dspace-services/src/main/resources/spring/spring-dspace-core-services.xml +++ b/dspace-services/src/main/resources/spring/spring-dspace-core-services.xml @@ -45,4 +45,11 @@ <!-- EVENTS --> <bean id="org.dspace.services.EventService" class="org.dspace.services.events.SystemEventService" /> + <!-- EMAIL --> + <bean id="org.dspace.services.email.EmailServiceImpl" + class="org.dspace.services.email.EmailServiceImpl"> + <property name="cfg" + ref="org.dspace.services.ConfigurationService" /> + </bean> + </beans> \ No newline at end of file diff --git a/dspace-sword/pom.xml b/dspace-sword/pom.xml index db8385f848c887818a9c0e574180aa544ebfb50e..4fa3e84473c64b5d3a576419a71d7e4ad829e44c 100644 --- a/dspace-sword/pom.xml +++ b/dspace-sword/pom.xml @@ -15,7 +15,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> diff --git a/dspace-sword/src/main/java/org/dspace/sword/SWORDConfiguration.java b/dspace-sword/src/main/java/org/dspace/sword/SWORDConfiguration.java index 4e268fb4461ceb3268e958fd13d4024e121995b9..9ce309ddd66502ac906f36db7647576c93958ce7 100644 --- a/dspace-sword/src/main/java/org/dspace/sword/SWORDConfiguration.java +++ b/dspace-sword/src/main/java/org/dspace/sword/SWORDConfiguration.java @@ -457,11 +457,7 @@ public class SWORDConfiguration public String getTempDir() throws DSpaceSWORDException { - String tempDir = ConfigurationManager.getProperty("upload.temp.dir"); - if (tempDir == null || "".equals(tempDir)) - { - throw new DSpaceSWORDException("There is no temporary upload directory specified in configuration: upload.temp.dir"); - } - return tempDir; + return (ConfigurationManager.getProperty("upload.temp.dir") != null) + ? ConfigurationManager.getProperty("upload.temp.dir") : System.getProperty("java.io.tmpdir"); } } diff --git a/dspace-sword/src/main/java/org/purl/sword/base/ChecksumUtils.java b/dspace-sword/src/main/java/org/purl/sword/base/ChecksumUtils.java index a2e469a22b815e9f029fb60a2621f8d810905531..bcf038d75ec1c60b2815f2806258dc9016887f55 100644 --- a/dspace-sword/src/main/java/org/purl/sword/base/ChecksumUtils.java +++ b/dspace-sword/src/main/java/org/purl/sword/base/ChecksumUtils.java @@ -17,7 +17,8 @@ import org.apache.log4j.Logger; /** * Utility class that holds Checksum related methods. * - * @author Neil Taylor, Stuart Lewis + * @author Neil Taylor + * @author Stuart Lewis */ public class ChecksumUtils { diff --git a/dspace-sword/src/main/java/org/purl/sword/base/SWORDEntry.java b/dspace-sword/src/main/java/org/purl/sword/base/SWORDEntry.java index ba3d605658451510839a5cf62164c8dede966c88..a23f9648919623e33e8eda92d13c1275d98ab099 100644 --- a/dspace-sword/src/main/java/org/purl/sword/base/SWORDEntry.java +++ b/dspace-sword/src/main/java/org/purl/sword/base/SWORDEntry.java @@ -32,7 +32,7 @@ public class SWORDEntry extends Entry protected SwordNoOp swordNoOp; /** - * Use to supply a verbose description. + * Used to supply a verbose description. */ protected SwordVerboseDescription swordVerboseDescription; @@ -49,7 +49,7 @@ public class SWORDEntry extends Entry protected SwordUserAgent swordUserAgent; /** - * The packaging infomation + * The packaging information */ private SwordPackaging swordPackaging; diff --git a/dspace-sword/src/main/java/org/purl/sword/client/SWORDClient.java b/dspace-sword/src/main/java/org/purl/sword/client/SWORDClient.java index 95b836c3cfa1998692d225bcc921563d42e83e41..41fe686fce5c435cffc14cc29b1e380b664bc1f7 100644 --- a/dspace-sword/src/main/java/org/purl/sword/client/SWORDClient.java +++ b/dspace-sword/src/main/java/org/purl/sword/client/SWORDClient.java @@ -15,77 +15,76 @@ import org.purl.sword.base.ServiceDocument; */ public interface SWORDClient { - /** - * Set the server that is to be contacted on the next access. - * - * @param server The name of the server, e.g. www.aber.ac.uk - * @param port The port number, e.g. 80. - */ - public void setServer( String server, int port ); - - /** - * Set the user credentials that are to be used for subsequent accesses. - * - * @param username The username. - * @param password The password. - */ - public void setCredentials( String username, String password ); + /** + * Set the server that is to be contacted on the next access. + * + * @param server The name of the server, e.g. www.aber.ac.uk + * @param port The port number, e.g. 80. + */ + public void setServer( String server, int port ); + + /** + * Set the user credentials that are to be used for subsequent accesses. + * + * @param username The username. + * @param password The password. + */ + public void setCredentials( String username, String password ); - /** + /** * Clear the credentials settings on the client. */ - public void clearCredentials(); + public void clearCredentials(); - /** - * Set the proxy that is to be used for subsequent accesses. - * - * @param host The host name, e.g. cache.host.com. - * @param port The port, e.g. 8080. - */ - public void setProxy( String host, int port ); - - /** - * Get the status result returned from the most recent network test. - * - * @return An the status code and message. - */ - public Status getStatus( ); - - /** - * Get a service document, specified in the URL. - * - * @param url The URL to connect to. - * @return A ServiceDocument that contains the Service details that were - * obained from the specified URL. - * - * @throws SWORDClientException If there is an error accessing the - * URL. - */ - public ServiceDocument getServiceDocument( String url ) throws SWORDClientException; - - /** - * Get a service document, specified in the URL. The document is accessed on - * behalf of the specified user. - * - * @param url The URL to connect to. - * @param onBehalfOf The username for the onBehalfOf access. - * @return A ServiceDocument that contains the Service details that were - * obained from the specified URL. - * - * @throws SWORDClientException If there is an error accessing the - * URL. - */ - public ServiceDocument getServiceDocument(String url, String onBehalfOf ) throws SWORDClientException; - - /** - * Post a file to the specified destination URL. - * - * @param message The message that defines the requirements for the operation. - * - * @return A DespoitResponse if the response is successful. If there was an error, - * <code>null</code> should be returned. - * - * @throws SWORDClientException If there is an error accessing the URL. - */ - public DepositResponse postFile( PostMessage message ) throws SWORDClientException; + /** + * Set the proxy that is to be used for subsequent accesses. + * + * @param host The host name, e.g. cache.host.com. + * @param port The port, e.g. 8080. + */ + public void setProxy( String host, int port ); + + /** + * Get the status result returned from the most recent network test. + * + * @return The status code and message. + */ + public Status getStatus( ); + + /** + * Get a service document, specified in the URL. + * + * @param url The URL to connect to. + * @return A ServiceDocument that contains the Service details that were + * obained from the specified URL. + * + * @throws SWORDClientException If there is an error accessing the + * URL. + */ + public ServiceDocument getServiceDocument( String url ) throws SWORDClientException; + + /** + * Get a service document, specified in the URL. The document is accessed on + * behalf of the specified user. + * + * @param url The URL to connect to. + * @param onBehalfOf The username for the onBehalfOf access. + * @return A ServiceDocument that contains the Service details that were + * obtained from the specified URL. + * + * @throws SWORDClientException If there is an error accessing the URL. + */ + public ServiceDocument getServiceDocument(String url, String onBehalfOf ) throws SWORDClientException; + + /** + * Post a file to the specified destination URL. + * + * @param message The message that defines the requirements for the operation. + * + * @return A DespoitResponse if the response is successful. If there was an error, + * <code>null</code> should be returned. + * + * @throws SWORDClientException If there is an error accessing the URL. + */ + public DepositResponse postFile( PostMessage message ) throws SWORDClientException; } diff --git a/dspace-swordv2/pom.xml b/dspace-swordv2/pom.xml index 1c933da7800bf2d25a9935b6fb0cad13b5b8b474..965c7ac63041326f890aaf142e33511898192a22 100644 --- a/dspace-swordv2/pom.xml +++ b/dspace-swordv2/pom.xml @@ -13,7 +13,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> @@ -96,15 +96,15 @@ </dependency> <dependency> <groupId>org.swordapp</groupId> - <artifactId>server</artifactId> - <version>2.0</version> + <artifactId>sword2-server</artifactId> + <version>1.0</version> <type>jar</type> <classifier>classes</classifier> </dependency> <dependency> <groupId>org.swordapp</groupId> - <artifactId>server</artifactId> - <version>2.0</version> + <artifactId>sword2-server</artifactId> + <version>1.0</version> <type>war</type> </dependency> <dependency> diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/AbstractSwordContentIngester.java b/dspace-swordv2/src/main/java/org/dspace/sword2/AbstractSwordContentIngester.java index 64bac4d2fa92d238fecd4ddc76f54390c0414d62..482d6fd862c37c4ff51808bbcbf9e8a87f0c6848 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/AbstractSwordContentIngester.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/AbstractSwordContentIngester.java @@ -11,6 +11,7 @@ import org.dspace.authorize.AuthorizeException; import org.dspace.content.Bitstream; import org.dspace.content.BitstreamFormat; import org.dspace.content.Bundle; +import org.dspace.content.Collection; import org.dspace.content.DCDate; import org.dspace.content.DCValue; import org.dspace.content.DSpaceObject; @@ -30,11 +31,31 @@ import java.util.StringTokenizer; public abstract class AbstractSwordContentIngester implements SwordContentIngester { - public abstract DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription) - throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException; - - public abstract DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription, DepositResult result) - throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException; + public DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription) + throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException + { + return this.ingest(context, deposit, dso, verboseDescription, null); + } + + public DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription, DepositResult result) + throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException + { + if (dso instanceof Collection) + { + return this.ingestToCollection(context, deposit, (Collection) dso, verboseDescription, result); + } + else if (dso instanceof Item) + { + return this.ingestToItem(context, deposit, (Item) dso, verboseDescription, result); + } + return null; + } + + public abstract DepositResult ingestToCollection(Context context, Deposit deposit, Collection collection, VerboseDescription verboseDescription, DepositResult result) + throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException; + + public abstract DepositResult ingestToItem(Context context, Deposit deposit, Item item, VerboseDescription verboseDescription, DepositResult result) + throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException; protected BitstreamFormat getFormat(Context context, String fileName) throws SQLException diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/AtomStatementDisseminator.java b/dspace-swordv2/src/main/java/org/dspace/sword2/AtomStatementDisseminator.java index da462621f76333fd32b73cde5653893ae7d10646..0b9f4909af081fb08d045434d2367c0e48138b7e 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/AtomStatementDisseminator.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/AtomStatementDisseminator.java @@ -44,7 +44,7 @@ public class AtomStatementDisseminator extends GenericStatementDisseminator impl } DCValue[] dcvs = item.getMetadata(field); - if (dcvs == null) + if (dcvs == null || dcvs.length == 0) { return null; } diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/BinaryContentIngester.java b/dspace-swordv2/src/main/java/org/dspace/sword2/BinaryContentIngester.java index c05862020a3e0c42c93f48782b3f6473617b32f1..ee5db5a4a2ac858673eb40c77aa7d41dc7be90a3 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/BinaryContentIngester.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/BinaryContentIngester.java @@ -28,26 +28,6 @@ import java.util.List; public class BinaryContentIngester extends AbstractSwordContentIngester { - public DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription) - throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException - { - return this.ingest(context, deposit, dso, verboseDescription, null); - } - - public DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription, DepositResult result) - throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException - { - if (dso instanceof Collection) - { - return this.ingestToCollection(context, deposit, (Collection) dso, verboseDescription, result); - } - else if (dso instanceof Item) - { - return this.ingestToItem(context, deposit, (Item) dso, verboseDescription, result); - } - return null; - } - public DepositResult ingestToCollection(Context context, Deposit deposit, Collection collection, VerboseDescription verboseDescription, DepositResult result) throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException { @@ -79,7 +59,7 @@ public class BinaryContentIngester extends AbstractSwordContentIngester // now we have an item in the workspace, and we need to consider adding some metadata to it, // but since the binary file didn't contain anything, what do we do? - item.addMetadata("dc", "title", null, null, "Unititled: " + deposit.getFilename()); + item.addMetadata("dc", "title", null, null, "Untitled: " + deposit.getFilename()); item.addMetadata("dc", "description", null, null, "Zip file deposted by SWORD without accompanying metadata"); // update the item metadata to inclue the current time as @@ -145,7 +125,9 @@ public class BinaryContentIngester extends AbstractSwordContentIngester original = item.createBundle("ORIGINAL"); } - Bitstream bs = item.createSingleBitstream(deposit.getInputStream()); + Bitstream bs = original.createBitstream(deposit.getInputStream()); + BitstreamFormat format = this.getFormat(context, deposit.getFilename()); + bs.setFormat(format); bs.setName(deposit.getFilename()); bs.update(); diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionCollectionGenerator.java b/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionCollectionGenerator.java index 6de4e13e99486744ec695a046f75f687dda73c06..61262a130d674f3e9bd5e4aeb41c1da7b568d41a 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionCollectionGenerator.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionCollectionGenerator.java @@ -28,10 +28,10 @@ public class CollectionCollectionGenerator implements AtomCollectionGenerator private static Logger log = Logger.getLogger(CommunityCollectionGenerator.class); /** - * Build the collection for the given DSpaceObject. In this - * implementation, if the object is not a DSpace Collection, it will - * throw an exception. + * Build the collection for the given DSpaceObject. In this implementation, + * if the object is not a DSpace COllection, it will throw an exception * @param dso + * @return * @throws DSpaceSwordException */ public SwordCollection buildCollection(Context context, DSpaceObject dso, SwordConfigurationDSpace swordConfig) diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionDepositManagerDSpace.java b/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionDepositManagerDSpace.java index 2020b11f9bf291b0a6f3795efd2c9419936e19e3..8662029b47b6fe397b7d6830b4d6270acc42b159 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionDepositManagerDSpace.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionDepositManagerDSpace.java @@ -76,6 +76,10 @@ public class CollectionDepositManagerDSpace extends DSpaceSwordAPI implements Co // get the deposit target Collection collection = this.getDepositTarget(context, collectionUri, config); + if (collection == null) + { + throw new SwordError(404); + } // Ensure that this method is allowed WorkflowManager wfm = WorkflowManagerFactory.getInstance(); @@ -185,7 +189,7 @@ public class CollectionDepositManagerDSpace extends DSpaceSwordAPI implements Co long delta = finish.getTime() - start.getTime(); this.verboseDescription.append("Total time for deposit processing: " + delta + " ms"); - receipt.setVerboseDescription(this.verboseDescription.toString()); + this.addVerboseDescription(receipt, this.verboseDescription); // if something hasn't killed it already (allowed), then complete the transaction sc.commit(); @@ -303,6 +307,10 @@ public class CollectionDepositManagerDSpace extends DSpaceSwordAPI implements Co // get the target collection Collection collection = urlManager.getCollection(context, depositUrl); + if (collection == null) + { + throw new SwordError(404); + } this.verboseDescription.append("Performing deposit using deposit URL: " + depositUrl); diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionListManagerDSpace.java b/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionListManagerDSpace.java index 221f857f9e84480fe3360ac6cec0f3d15fcaafd5..de59da0563ff9f2fe0daa08dc6d73442f571d75e 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionListManagerDSpace.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/CollectionListManagerDSpace.java @@ -46,6 +46,10 @@ public class CollectionListManagerDSpace extends DSpaceSwordAPI implements Colle SwordUrlManager urlManager = config.getUrlManager(context, config); Collection collection = urlManager.getCollection(context, colIRI.toString()); + if (collection == null) + { + throw new SwordError(404); + } List<Item> items = this.listItems(sc, collection, swordConfig); Feed feed = this.itemListToFeed(sc, items, swordConfig); diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/ContainerManagerDSpace.java b/dspace-swordv2/src/main/java/org/dspace/sword2/ContainerManagerDSpace.java index a1621f754812b8b611eda5cbcd4bbe4e3288fbdd..34d68a7fa965c498495f832b921f81e8cc5b0d7b 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/ContainerManagerDSpace.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/ContainerManagerDSpace.java @@ -9,12 +9,15 @@ package org.dspace.sword2; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; import org.dspace.content.Collection; import org.dspace.content.InProgressSubmission; import org.dspace.content.Item; import org.dspace.content.WorkspaceItem; +import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; +import org.dspace.workflow.WorkflowItem; import org.swordapp.server.AuthCredentials; import org.swordapp.server.ContainerManager; import org.swordapp.server.Deposit; @@ -92,11 +95,27 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM SwordUrlManager urlManager = config.getUrlManager(context, config); Item item = urlManager.getItem(context, editIRI); + if (item == null) + { + throw new SwordError(404); + } + + // we can't give back an entry unless the user is authorised to retrieve it + AuthorizeManager.authorizeAction(context, item, Constants.READ); ReceiptGenerator genny = new ReceiptGenerator(); DepositReceipt receipt = genny.createReceipt(context, item, config); + sc.abort(); return receipt; } + catch (AuthorizeException e) + { + throw new SwordAuthException(); + } + catch (SQLException e) + { + throw new SwordServerException(e); + } catch (DSpaceSwordException e) { throw new SwordServerException(e); @@ -135,6 +154,10 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM // get the deposit target Item item = this.getDSpaceTarget(context, editIRI, config); + if (item == null) + { + throw new SwordError(404); + } // now we have the deposit target, we can determine whether this operation is allowed // at all @@ -210,7 +233,7 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM long delta = finish.getTime() - start.getTime(); this.verboseDescription.append("Total time for deposit processing: " + delta + " ms"); - receipt.setVerboseDescription(this.verboseDescription.toString()); + this.addVerboseDescription(receipt, this.verboseDescription); // if something hasn't killed it already (allowed), then complete the transaction sc.commit(); @@ -258,6 +281,10 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM // get the deposit target Item item = this.getDSpaceTarget(context, editIRI, config); + if (item == null) + { + throw new SwordError(404); + } // Ensure that this method is allowed WorkflowManager wfm = WorkflowManagerFactory.getInstance(); @@ -334,7 +361,7 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM long delta = finish.getTime() - start.getTime(); this.verboseDescription.append("Total time for deposit processing: " + delta + " ms"); - receipt.setVerboseDescription(this.verboseDescription.toString()); + this.addVerboseDescription(receipt, this.verboseDescription); // if something hasn't killed it already (allowed), then complete the transaction sc.commit(); @@ -359,7 +386,7 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM public DepositReceipt addMetadataAndResources(String s, Deposit deposit, AuthCredentials authCredentials, SwordConfiguration config) throws SwordError, SwordServerException { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public DepositReceipt addMetadata(String editIRI, Deposit deposit, AuthCredentials authCredentials, SwordConfiguration swordConfig) @@ -386,6 +413,10 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM // get the deposit target Item item = this.getDSpaceTarget(context, editIRI, config); + if (item == null) + { + throw new SwordError(404); + } // now we have the deposit target, we can determine whether this operation is allowed // at all @@ -461,7 +492,7 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM long delta = finish.getTime() - start.getTime(); this.verboseDescription.append("Total time for deposit processing: " + delta + " ms"); - receipt.setVerboseDescription(this.verboseDescription.toString()); + this.addVerboseDescription(receipt, this.verboseDescription); // if something hasn't killed it already (allowed), then complete the transaction sc.commit(); @@ -486,7 +517,7 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM public DepositReceipt addResources(String s, Deposit deposit, AuthCredentials authCredentials, SwordConfiguration config) throws SwordError, SwordServerException { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public void deleteContainer(String editIRI, AuthCredentials authCredentials, SwordConfiguration swordConfig) @@ -513,6 +544,10 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM // get the deposit target Item item = this.getDSpaceTarget(context, editIRI, config); + if (item == null) + { + throw new SwordError(404); + } // now we have the deposit target, we can determine whether this operation is allowed // at all @@ -591,6 +626,10 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM // get the deposit target Item item = this.getDSpaceTarget(context, editIRI, config); + if (item == null) + { + throw new SwordError(404); + } // now we have the deposit target, we can determine whether this operation is allowed // at all @@ -634,7 +673,7 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM long delta = finish.getTime() - start.getTime(); this.verboseDescription.append("Total time for modify processing: " + delta + " ms"); - receipt.setVerboseDescription(this.verboseDescription.toString()); + this.addVerboseDescription(receipt, this.verboseDescription); // if something hasn't killed it already (allowed), then complete the transaction sc.commit(); @@ -679,7 +718,7 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM // delegate the to the version manager to get rid of any existing content and to version // if if necessary VersionManager vm = new VersionManager(); - vm.emptyBundle(item, "ORIGINAL"); + vm.removeBundle(item, "ORIGINAL"); } catch (SQLException e) { @@ -822,6 +861,10 @@ public class ContainerManagerDSpace extends DSpaceSwordAPI implements ContainerM // get the target collection Item item = urlManager.getItem(context, editUrl); + if (item == null) + { + throw new SwordError(404); + } this.verboseDescription.append("Performing replace using edit-media URL: " + editUrl); this.verboseDescription.append("Location resolves to item with handle: " + item.getHandle()); diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/DSpaceSwordAPI.java b/dspace-swordv2/src/main/java/org/dspace/sword2/DSpaceSwordAPI.java index 179f9dc9e696c6ca0e78fa0663e161c946b60f50..67a818ebc4634c232bf8014684752ec3e73d1e04 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/DSpaceSwordAPI.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/DSpaceSwordAPI.java @@ -19,6 +19,7 @@ import org.dspace.content.Item; import org.dspace.core.*; import org.swordapp.server.AuthCredentials; import org.swordapp.server.Deposit; +import org.swordapp.server.DepositReceipt; import org.swordapp.server.SwordAuthException; import org.swordapp.server.SwordError; import org.swordapp.server.SwordServerException; @@ -68,6 +69,12 @@ public class DSpaceSwordAPI public SwordContext doAuth(AuthCredentials authCredentials) throws SwordAuthException, SwordError, DSpaceSwordException { + // if there is no supplied username, then we should request a retry + if (authCredentials.getUsername() == null) + { + throw new SwordAuthException(true); + } + // first authenticate the request // note: this will build our various DSpace contexts for us SwordAuthenticator auth = new SwordAuthenticator(); @@ -281,7 +288,7 @@ public class DSpaceSwordAPI String fn = this.createEntryFilename(context, deposit, true); entryBitstream.setName(fn); - entryBitstream.setDescription("SWORD entry document"); + entryBitstream.setDescription("Original SWORD entry document"); BitstreamFormat bf = BitstreamFormat.findByMIMEType(context, "application/xml"); if (bf != null) @@ -321,7 +328,7 @@ public class DSpaceSwordAPI } bitstream.setName(fn); - bitstream.setDescription("SWORD deposit package"); + bitstream.setDescription("Orignal SWORD deposit file"); BitstreamFormat bf = BitstreamFormat.findByMIMEType(context, deposit.getMimeType()); if (bf != null) @@ -336,7 +343,7 @@ public class DSpaceSwordAPI // shouldn't mess with it result.setOriginalDeposit(bitstream); } - verboseDescription.append("Original package stored as " + fn + ", in item bundle " + swordBundle); + verboseDescription.append("Original deposit stored as " + fn + ", in item bundle " + swordBundle); } swordBundle.update(); @@ -503,4 +510,13 @@ public class DSpaceSwordAPI pw.println("User name=" + auth.getUsername()); pw.close(); } + + protected void addVerboseDescription(DepositReceipt receipt, VerboseDescription verboseDescription) + { + boolean includeVerbose = ConfigurationManager.getBooleanProperty("swordv2-server", "verbose-description.receipt.enable"); + if (includeVerbose) + { + receipt.setVerboseDescription(verboseDescription.toString()); + } + } } diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/DSpaceUriRegistry.java b/dspace-swordv2/src/main/java/org/dspace/sword2/DSpaceUriRegistry.java index d21ccc7a6e06c8f5f65d5b78dcca984f850a688c..9df390e30695976ba8406f06c6377ed0899a83e1 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/DSpaceUriRegistry.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/DSpaceUriRegistry.java @@ -12,30 +12,32 @@ public class DSpaceUriRegistry public static final String DSPACE_SWORD_NS = "http://www.dspace.org/ns/sword/2.0/"; /** if unpackaging the package fails */ - public static final String UNPACKAGE_FAIL = DSPACE_SWORD_NS + "/errors/UnpackageFail"; + public static final String UNPACKAGE_FAIL = DSPACE_SWORD_NS + "errors/UnpackageFail"; /** if the url of the request does not resolve to something meaningful */ - public static final String BAD_URL = DSPACE_SWORD_NS + "/errors/BadUrl"; + public static final String BAD_URL = DSPACE_SWORD_NS + "errors/BadUrl"; /** if the media requested is unavailable */ - public static final String MEDIA_UNAVAILABLE = DSPACE_SWORD_NS + "/errors/MediaUnavailable"; + public static final String MEDIA_UNAVAILABLE = DSPACE_SWORD_NS + "errors/MediaUnavailable"; /* additional codes */ /** Invalid package */ - public static final String PACKAGE_ERROR = DSPACE_SWORD_NS + "/errors/PackageError"; + public static final String PACKAGE_ERROR = DSPACE_SWORD_NS + "errors/PackageError"; /** Missing resources in package */ - public static final String PACKAGE_VALIDATION_ERROR = DSPACE_SWORD_NS + "/errors/PackageValidationError"; + public static final String PACKAGE_VALIDATION_ERROR = DSPACE_SWORD_NS + "errors/PackageValidationError"; /** Crosswalk error */ - public static final String CROSSWALK_ERROR = DSPACE_SWORD_NS + "/errors/CrosswalkError"; + public static final String CROSSWALK_ERROR = DSPACE_SWORD_NS + "errors/CrosswalkError"; /** Invalid collection for linking */ - public static final String COLLECTION_LINK_ERROR = DSPACE_SWORD_NS + "/errors/CollectionLinkError"; + public static final String COLLECTION_LINK_ERROR = DSPACE_SWORD_NS + "errors/CollectionLinkError"; /** Database or IO Error when installing new item */ - public static final String REPOSITORY_ERROR = DSPACE_SWORD_NS + "/errors/RepositoryError"; + public static final String REPOSITORY_ERROR = DSPACE_SWORD_NS + "errors/RepositoryError"; - public static final String NOT_ACCEPTABLE = DSPACE_SWORD_NS + "/errors/NotAcceptable"; + // FIXME: this is being withdrawn from all 406 responses for the time being, in preference + // for ErrorContent as per the spec (whether that is right or wrong) + public static final String NOT_ACCEPTABLE = DSPACE_SWORD_NS + "errors/NotAcceptable"; } diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/FeedContentDisseminator.java b/dspace-swordv2/src/main/java/org/dspace/sword2/FeedContentDisseminator.java index da6c42f56b38257bc262f25c964de5aeaa171275..5352be133b789733726498d8c73708fbdf52531d 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/FeedContentDisseminator.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/FeedContentDisseminator.java @@ -11,6 +11,7 @@ import org.apache.abdera.Abdera; import org.apache.abdera.i18n.iri.IRI; import org.apache.abdera.model.Entry; import org.apache.abdera.model.Feed; +import org.apache.abdera.model.Link; import org.dspace.content.Bitstream; import org.dspace.content.BitstreamFormat; import org.dspace.content.Bundle; @@ -24,8 +25,10 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.sql.SQLException; +import java.util.Date; +import java.util.Map; -public class FeedContentDisseminator implements SwordContentDisseminator +public class FeedContentDisseminator extends AbstractSimpleDC implements SwordContentDisseminator { public InputStream disseminate(Context context, Item item) throws DSpaceSwordException, SwordError, SwordServerException @@ -35,6 +38,8 @@ public class FeedContentDisseminator implements SwordContentDisseminator Abdera abdera = new Abdera(); Feed feed = abdera.newFeed(); + this.addMetadata(feed, item); + Bundle[] originals = item.getBundles("ORIGINAL"); for (Bundle original : originals) { @@ -61,6 +66,35 @@ public class FeedContentDisseminator implements SwordContentDisseminator } } + private void addMetadata(Feed feed, Item item) + { + SimpleDCMetadata md = this.getMetadata(item); + + /* not necessary ... + Map<String, String> dc = md.getDublinCore(); + for (String element : dc.keySet()) + { + String value = dc.get(element); + feed.addSimpleExtension(new QName(UriRegistry.DC_NAMESPACE, element), value); + } + */ + + Map<String, String> atom = md.getAtom(); + for (String element : atom.keySet()) + { + if ("author".equals(element)) + { + feed.addAuthor(atom.get(element)); + } + } + + // ensure that the feed has one author or more + if (feed.getAuthors().size() == 0) + { + feed.addAuthor(ConfigurationManager.getProperty("dspace.name")); + } + } + private void populateEntry(Context context, Entry entry, Bitstream bitstream) throws DSpaceSwordException { @@ -71,13 +105,28 @@ public class FeedContentDisseminator implements SwordContentDisseminator contentType = format.getMIMEType(); } + SwordUrlManager urlManager = new SwordUrlManager(new SwordConfigurationDSpace(), context); + String bsUrl = urlManager.getBitstreamUrl(bitstream); + + entry.setId(bsUrl); entry.setTitle(bitstream.getName()); - entry.setSummary(bitstream.getDescription()); + String desc = bitstream.getDescription(); + if ("".equals(desc) || desc == null) + { + desc = bitstream.getName(); + } + entry.setSummary(desc); + entry.setUpdated(new Date()); // required, though content is spurious - SwordUrlManager urlManager = new SwordUrlManager(new SwordConfigurationDSpace(), context); + // add an edit-media link for the bitstream ... + Abdera abdera = new Abdera(); + Link link = abdera.getFactory().newLink(); + link.setHref(urlManager.getActionableBitstreamUrl(bitstream)); + link.setMimeType(contentType); + link.setRel("edit-media"); + entry.addLink(link); // set the content of the bitstream - String bsUrl = urlManager.getBitstreamUrl(bitstream); entry.setContent(new IRI(bsUrl), contentType); } diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/GenericStatementDisseminator.java b/dspace-swordv2/src/main/java/org/dspace/sword2/GenericStatementDisseminator.java index ceaa8b4cc8f012f7d3f186d6de1b05a5b5b09550..8f55ce8cd4daf5388aaa730bc156f5dca4f7d66d 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/GenericStatementDisseminator.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/GenericStatementDisseminator.java @@ -31,29 +31,39 @@ public abstract class GenericStatementDisseminator implements SwordStatementDiss throws DSpaceSwordException { this.urlManager = new SwordUrlManager(new SwordConfigurationDSpace(), context); - List<OriginalDeposit> originalDeposits = this.getOriginalDeposits(context, item); + List<String> includeBundles = this.getIncludeBundles(); + String originalDepositBundle = this.getOriginalDepositsBundle(); + + // we only list the original deposits in full if the sword bundle is in the includeBundles + if (includeBundles.contains(originalDepositBundle)) + { + List<OriginalDeposit> originalDeposits = this.getOriginalDeposits(context, item, originalDepositBundle); + statement.setOriginalDeposits(originalDeposits); + } + Map<String, String> states = this.getStates(context, item); - List<ResourcePart> resources = this.getResourceParts(context, item); - Date lastModified = this.getLastModified(context, item); + statement.setStates(states); + // remove the original deposit bundle from the include bundles + includeBundles.remove(originalDepositBundle); + List<ResourcePart> resources = this.getResourceParts(context, item, includeBundles); + statement.setResources(resources); + + Date lastModified = this.getLastModified(context, item); statement.setLastModified(lastModified); - statement.setOriginalDeposits(originalDeposits); - statement.setStates(states); - statement.setResources(resources); } - protected List<OriginalDeposit> getOriginalDeposits(Context context, Item item) + protected List<OriginalDeposit> getOriginalDeposits(Context context, Item item, String swordBundle) throws DSpaceSwordException { try { - // an original deposit is everything in the SWORD bundle + // NOTE: DSpace does not store file metadata, so we can't access the information + // about who deposited what, when, on behalf of whoever. + List<OriginalDeposit> originalDeposits = new ArrayList<OriginalDeposit>(); - String swordBundle = ConfigurationManager.getProperty("swordv2-server", "bundle.name"); - if (swordBundle == null) - { - swordBundle = "SWORD"; - } + + // an original deposit is everything in the SWORD bundle Bundle[] swords = item.getBundles(swordBundle); for (Bundle sword : swords) { @@ -106,25 +116,29 @@ public abstract class GenericStatementDisseminator implements SwordStatementDiss return states; } - protected List<ResourcePart> getResourceParts(Context context, Item item) + protected List<ResourcePart> getResourceParts(Context context, Item item, List<String> includeBundles) throws DSpaceSwordException { try { - // the list of resource parts is everything in the ORIGINAL bundle + // the list of resource parts is everything in the bundles to be included List<ResourcePart> resources = new ArrayList<ResourcePart>(); - Bundle[] originals = item.getBundles("ORIGINAL"); - for (Bundle original : originals) - { - for (Bitstream bitstream : original.getBitstreams()) - { - // note that individual bitstreams have actionable urls - ResourcePart part = new ResourcePart(this.urlManager.getActionableBitstreamUrl(bitstream)); - part.setMediaType(bitstream.getFormat().getMIMEType()); - resources.add(part); - } - } + for (String bundleName : includeBundles) + { + Bundle[] bundles = item.getBundles(bundleName); + for (Bundle bundle : bundles) + { + for (Bitstream bitstream : bundle.getBitstreams()) + { + // note that individual bitstreams have actionable urls + ResourcePart part = new ResourcePart(this.urlManager.getActionableBitstreamUrl(bitstream)); + part.setMediaType(bitstream.getFormat().getMIMEType()); + resources.add(part); + } + } + } + return resources; } catch (SQLException e) @@ -137,4 +151,34 @@ public abstract class GenericStatementDisseminator implements SwordStatementDiss { return item.getLastModified(); } + + private List<String> getIncludeBundles() + { + String cfg = ConfigurationManager.getProperty("swordv2-server", "statement.bundles"); + if (cfg == null || "".equals(cfg)) + { + cfg = "ORIGINAL, SWORD"; + } + String[] bits = cfg.split(","); + List<String> include = new ArrayList<String>(); + for (String bit : bits) + { + String bundleName = bit.trim().toUpperCase(); + if (!include.contains(bundleName)) + { + include.add(bundleName); + } + } + return include; + } + + private String getOriginalDepositsBundle() + { + String swordBundle = ConfigurationManager.getProperty("swordv2-server", "bundle.name"); + if (swordBundle == null) + { + swordBundle = "SWORD"; + } + return swordBundle; + } } diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/MediaResourceManagerDSpace.java b/dspace-swordv2/src/main/java/org/dspace/sword2/MediaResourceManagerDSpace.java index e58ead096f34c383be8c576f9cc781bf30f92689..4fe68054633790fe13a2998404dd079254623cf0 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/MediaResourceManagerDSpace.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/MediaResourceManagerDSpace.java @@ -9,9 +9,13 @@ package org.dspace.sword2; import org.apache.log4j.Logger; import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; +import org.dspace.authorize.ResourcePolicy; import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.swordapp.server.AuthCredentials; @@ -41,106 +45,214 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR private VerboseDescription verboseDescription = new VerboseDescription(); - public MediaResource getMediaResourceRepresentation(String uri, Map<String, String> accept, AuthCredentials authCredentials, SwordConfiguration swordConfig) - throws SwordError, SwordServerException, SwordAuthException + private boolean isAccessible(Context context, Bitstream bitstream) + throws DSpaceSwordException { try { - SwordContext sc = null; - SwordConfigurationDSpace config = (SwordConfigurationDSpace) swordConfig; + return AuthorizeManager.authorizeActionBoolean(context, bitstream, Constants.READ); + } + catch (SQLException e) + { + throw new DSpaceSwordException(e); + } + } - SwordAuthenticator auth = new SwordAuthenticator(); - sc = auth.authenticate(authCredentials); - Context context = sc.getContext(); + private boolean isAccessible(Context context, Item item) + throws DSpaceSwordException + { + try + { + return AuthorizeManager.authorizeActionBoolean(context, item, Constants.READ); + } + catch (SQLException e) + { + throw new DSpaceSwordException(e); + } + } - if (log.isDebugEnabled()) + private MediaResource getBitstreamResource(Context context, Bitstream bitstream) + throws SwordServerException, SwordAuthException + { + try + { + InputStream stream = bitstream.retrieve(); + MediaResource mr = new MediaResource(stream, bitstream.getFormat().getMIMEType(), null, true); + mr.setContentMD5(bitstream.getChecksum()); + mr.setLastModified(this.getLastModified(context, bitstream)); + return mr; + } + catch (IOException e) + { + throw new SwordServerException(e); + } + catch (SQLException e) + { + throw new SwordServerException(e); + } + catch (AuthorizeException e) + { + throw new SwordAuthException(e); + } + } + + private MediaResource getItemResource(Context context, Item item, SwordUrlManager urlManager, String uri, Map<String, String> accept) + throws SwordError, DSpaceSwordException, SwordServerException + { + boolean feedRequest = urlManager.isFeedRequest(context, uri); + SwordContentDisseminator disseminator = null; + + // first off, consider the accept headers. The accept argument is a map + // from accept header to value. + // we only care about Accept and Accept-Packaging + if (!feedRequest) + { + String acceptContentType = this.getHeader(accept, "Accept", null); + String acceptPackaging = this.getHeader(accept, "Accept-Packaging", UriRegistry.PACKAGE_SIMPLE_ZIP); + + // we know that only one Accept-Packaging value is allowed, so we don't need + // to do any further work on it. + + // we extract from the Accept header the ordered list of content types + TreeMap<Float, List<String>> analysed = this.analyseAccept(acceptContentType); + + // the meat of this is done by the package disseminator + disseminator = SwordDisseminatorFactory.getContentInstance(analysed, acceptPackaging); + } + else + { + // we just want to ask for the atom version, so we bypass the main content + // negotiation place + Map<Float, List<String>> analysed = new HashMap<Float, List<String>>(); + List<String> list = new ArrayList<String>(); + list.add("application/atom+xml"); + analysed.put((float) 1.0, list); + disseminator = SwordDisseminatorFactory.getContentInstance(analysed, null); + } + + // Note that at this stage, if we don't have a desiredContentType, it will + // be null, and the disseminator is free to choose the format + InputStream stream = disseminator.disseminate(context, item); + MediaResource mr = new MediaResource(stream, disseminator.getContentType(), disseminator.getPackaging()); + return mr; + } + + public MediaResource getMediaResourceRepresentation(String uri, Map<String, String> accept, AuthCredentials authCredentials, SwordConfiguration swordConfig) + throws SwordError, SwordServerException, SwordAuthException + { + // all the bits we need to make this method function + SwordContext sc = null; + SwordConfigurationDSpace config = (SwordConfigurationDSpace) swordConfig; + Context ctx = null; + + try + { + // create an unauthenticated context for our initial explorations + ctx = new Context(); + SwordUrlManager urlManager = config.getUrlManager(ctx, config); + + // is this a request for a bitstream or an item (which is the full media resource)? + if (urlManager.isActionableBitstreamUrl(ctx, uri)) { - log.debug(LogManager.getHeader(context, "sword_get_media_resource", "")); - } + // request for a bitstream + Bitstream bitstream = urlManager.getBitstream(ctx, uri); + if (bitstream == null) + { + // bitstream not found in the database, so 404 the client. + // Arguably, we should try to authenticate first, but it's not so important + throw new SwordError(404); + } - // log the request - String un = authCredentials.getUsername() != null ? authCredentials.getUsername() : "NONE"; - String obo = authCredentials.getOnBehalfOf() != null ? authCredentials.getOnBehalfOf() : "NONE"; - log.info(LogManager.getHeader(context, "sword_get_media_resource", "username=" + un + ",on_behalf_of=" + obo)); + // find out, now we know what we're being asked for, whether this is allowed + WorkflowManagerFactory.getInstance().retrieveBitstream(ctx, bitstream); - // first thing is to figure out what we're being asked to work on; it may be an Item or a Bitstream - SwordUrlManager urlManager = config.getUrlManager(context, config); - if (urlManager.isActionableBitstreamUrl(context, uri)) - { - // we're being asked for the bitstream itself - Bitstream bitstream = urlManager.getBitstream(context, uri); - - // find out, now we know what we're being asked for, whether this is allowed - WorkflowManagerFactory.getInstance().retrieveBitstream(context, bitstream); - - InputStream stream = bitstream.retrieve(); - MediaResource mr = new MediaResource(stream, bitstream.getFormat().getMIMEType(), null, true); - mr.setContentMD5(bitstream.getChecksum()); - mr.setLastModified(this.getLastModified(context, bitstream)); - return mr; - } - else - { - // we're dealing with a request for a representation of the item as a media resource - Item item = urlManager.getItem(context, uri); - boolean feedRequest = urlManager.isFeedRequest(context, uri); + // we can do this in principle, but now find out whether the bitstream is accessible without credentials + boolean accessible = this.isAccessible(ctx, bitstream); - // find out, now we know what we're being asked for, whether this is allowed - WorkflowManagerFactory.getInstance().retrieveContent(context, item); + if (!accessible) + { + // try to authenticate, and if successful switch the contexts around + sc = this.doAuth(authCredentials); + ctx.abort(); + ctx = sc.getContext(); - SwordContentDisseminator disseminator = null; + // re-retrieve the bitstream using the new context + bitstream = Bitstream.find(ctx, bitstream.getID()); - // first off, consider the accept headers. The accept argument is a map - // from accept header to value. - // we only care about Accept and Accept-Packaging - if (!feedRequest) - { - String acceptContentType = this.getHeader(accept, "Accept", null); - String acceptPackaging = this.getHeader(accept, "Accept-Packaging", UriRegistry.PACKAGE_SIMPLE_ZIP); + // and re-verify its accessibility + accessible = this.isAccessible(ctx, bitstream); + if (!accessible) + { + throw new SwordAuthException(); + } + } - // we know that only one Accept-Packaging value is allowed, so we don't need - // to do any further work on it. + // if we get to here we are either allowed to access the bitstream without credentials, + // or we have been authenticated with acceptable credentials + MediaResource mr = this.getBitstreamResource(ctx, bitstream); + if (sc != null) + { + sc.abort(); + } + if (ctx.isValid()) + { + ctx.abort(); + } + return mr; + } + else + { + // request for an item + Item item = urlManager.getItem(ctx, uri); + if (item == null) + { + // item now found in the database, so 404 the client + // Arguably, we should try to authenticate first, but it's not so important + throw new SwordError(404); + } - // we extract from the Accept header the ordered list of content types - TreeMap<Float, List<String>> analysed = this.analyseAccept(acceptContentType); + // find out, now we know what we're being asked for, whether this is allowed + WorkflowManagerFactory.getInstance().retrieveContent(ctx, item); - // the meat of this is done by the package disseminator - disseminator = SwordDisseminatorFactory.getContentInstance(analysed, acceptPackaging); - } - else - { - // we just want to ask for the atom version, so we bypass the main content - // negotiation place - Map<Float, List<String>> analysed = new HashMap<Float, List<String>>(); - List<String> list = new ArrayList<String>(); - list.add("application/atom+xml"); - analysed.put((float) 1.0, list); - disseminator = SwordDisseminatorFactory.getContentInstance(analysed, null); - } + // we can do this in principle but now find out whether the item is accessible without credentials + boolean accessible = this.isAccessible(ctx, item); - // Note that at this stage, if we don't have a desiredContentType, it will - // be null, and the disseminator is free to choose the format - InputStream stream = disseminator.disseminate(context, item); - MediaResource mr = new MediaResource(stream, disseminator.getContentType(), disseminator.getPackaging()); - return mr; - } + if (!accessible) + { + // try to authenticate, and if successful switch the contexts around + sc = this.doAuth(authCredentials); + ctx.abort(); + ctx = sc.getContext(); + } + + // if we get to here we are either allowed to access the bitstream without credentials, + // or we have been authenticated + MediaResource mr = this.getItemResource(ctx, item, urlManager, uri, accept); + // sc.abort(); + ctx.abort(); + return mr; + } + } + catch (SQLException e) + { + throw new SwordServerException(e); } catch (DSpaceSwordException e) { throw new SwordServerException(e); } - catch (SQLException e) - { - throw new SwordServerException(e); - } - catch (IOException e) - { - throw new SwordServerException(e); - } - catch (AuthorizeException e) - { - throw new SwordServerException(e); - } + finally + { + // if there is a sword context, abort it (this will abort the inner dspace context as well) + if (sc != null) + { + sc.abort(); + } + if (ctx != null && ctx.isValid()) + { + ctx.abort(); + } + } } private Date getLastModified(Context context, Bitstream bitstream) @@ -196,6 +308,10 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR if (urlManager.isActionableBitstreamUrl(context, emUri)) { Bitstream bitstream = urlManager.getBitstream(context, emUri); + if (bitstream == null) + { + throw new SwordError(404); + } // now we have the deposit target, we can determine whether this operation is allowed // at all @@ -266,6 +382,10 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR { // get the deposit target Item item = this.getDSpaceTarget(context, emUri, config); + if (item == null) + { + throw new SwordError(404); + } // now we have the deposit target, we can determine whether this operation is allowed // at all @@ -333,8 +453,8 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR // now we've produced a deposit, we need to decide on its workflow state wfm.resolveState(context, deposit, null, this.verboseDescription, false); - // ReceiptGenerator genny = new ReceiptGenerator(); - // DepositReceipt receipt = genny.createReceipt(context, result, config); + ReceiptGenerator genny = new ReceiptGenerator(); + receipt = genny.createMediaResourceReceipt(context, item, config); } Date finish = new Date(); @@ -397,6 +517,10 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR if (urlManager.isActionableBitstreamUrl(context, emUri)) { Bitstream bitstream = urlManager.getBitstream(context, emUri); + if (bitstream == null) + { + throw new SwordError(404); + } // now we have the deposit target, we can determine whether this operation is allowed // at all @@ -425,6 +549,10 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR else { Item item = this.getDSpaceTarget(context, emUri, config); + if (item == null) + { + throw new SwordError(404); + } // now we have the deposit target, we can determine whether this operation is allowed // at all @@ -518,6 +646,10 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR // get the deposit target Item item = this.getDSpaceTarget(context, emUri, config); + if (item == null) + { + throw new SwordError(404); + } // now we have the deposit target, we can determine whether this operation is allowed // at all @@ -620,7 +752,7 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR long delta = finish.getTime() - start.getTime(); this.verboseDescription.append("Total time for add processing: " + delta + " ms"); - receipt.setVerboseDescription(this.verboseDescription.toString()); + this.addVerboseDescription(receipt, this.verboseDescription); // if something hasn't killed it already (allowed), then complete the transaction sc.commit(); @@ -652,7 +784,7 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR Bundle[] originals = item.getBundles("ORIGINAL"); for (Bundle original : originals) { - vm.emptyBundle(item, original); + vm.removeBundle(item, original); } } catch (SQLException e) @@ -714,7 +846,7 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR // delegate the to the version manager to get rid of any existing content and to version // if if necessary VersionManager vm = new VersionManager(); - vm.emptyBundle(item, "ORIGINAL"); + vm.removeBundle(item, "ORIGINAL"); } catch (SQLException e) { @@ -741,8 +873,11 @@ public class MediaResourceManagerDSpace extends DSpaceSwordAPI implements MediaR throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException { // FIXME: this is basically not possible with the existing DSpace API. - // we are going to hack around the problem, by deleting the old bitstream and - // adding the new one and returning it + + // We hack around it by deleting the old bitstream and + // adding the new one and returning it, + // but this isn't in line with the REST approach of SWORD, so the caller should really + // 405 the client // get the things out of the service that we need Context context = swordContext.getContext(); diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/ReceiptGenerator.java b/dspace-swordv2/src/main/java/org/dspace/sword2/ReceiptGenerator.java index 9386e5ef07ca329a30524797b656576854747f3f..41b6e582f0fc6863af3aefb21863a77df36c2e5a 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/ReceiptGenerator.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/ReceiptGenerator.java @@ -50,6 +50,15 @@ public class ReceiptGenerator return receipt; } + protected DepositReceipt createMediaResourceReceipt(Context context, Item item, SwordConfigurationDSpace config) + throws DSpaceSwordException, SwordError, SwordServerException + { + SwordUrlManager urlManager = config.getUrlManager(context, config); + DepositReceipt receipt = new DepositReceipt(); + receipt.setLocation(urlManager.getContentUrl(item)); + return receipt; + } + protected DepositReceipt createReceipt(Context context, DepositResult result, SwordConfigurationDSpace config) throws DSpaceSwordException, SwordError, SwordServerException { @@ -61,7 +70,7 @@ public class ReceiptGenerator * * @throws DSpaceSwordException */ - protected DepositReceipt createReceipt(Context context, DepositResult result, SwordConfigurationDSpace config, boolean mediaResource) + protected DepositReceipt createReceipt(Context context, DepositResult result, SwordConfigurationDSpace config, boolean mediaResourceLocation) throws DSpaceSwordException, SwordError, SwordServerException { SwordUrlManager urlManager = config.getUrlManager(context, config); @@ -78,7 +87,7 @@ public class ReceiptGenerator receipt.setMediaFeedIRI(urlManager.getMediaFeedUrl(result.getItem())); receipt.setLastModified(result.getItem().getLastModified()); - if (mediaResource) + if (mediaResourceLocation) { receipt.setLocation(urlManager.getContentUrl(result.getItem())); } @@ -206,11 +215,6 @@ public class ReceiptGenerator return receipt; } - private void addMetadata(DepositResult result, DepositReceipt receipt) - { - - } - /** * Add all the subject classifications from the bibliographic * metadata. diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/ServiceDocumentManagerDSpace.java b/dspace-swordv2/src/main/java/org/dspace/sword2/ServiceDocumentManagerDSpace.java index 8724097b4cbd1df0164c8c745018e26d0e8707b6..dfdf7453d280e9d9b384def44c382cecf656547b 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/ServiceDocumentManagerDSpace.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/ServiceDocumentManagerDSpace.java @@ -140,6 +140,10 @@ public class ServiceDocumentManagerDSpace implements ServiceDocumentManager { // we are dealing with a partial or sub-service document DSpaceObject dso = urlManager.extractDSpaceObject(url); + if (dso == null) + { + throw new SwordError(404); + } if (dso instanceof Community) { diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCEntryDisseminator.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCEntryDisseminator.java index 607cba6a95b955c945d2ba8b4b3af9af711e16c9..4852b39bf99d88801800b1dbbeaaaa607c748d37 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCEntryDisseminator.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCEntryDisseminator.java @@ -7,67 +7,58 @@ */ package org.dspace.sword2; -import org.dspace.content.DCValue; import org.dspace.content.Item; -import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; import org.swordapp.server.DepositReceipt; import org.swordapp.server.SwordError; import org.swordapp.server.SwordServerException; -import java.util.HashMap; import java.util.Map; -import java.util.Properties; -public class SimpleDCEntryDisseminator implements SwordEntryDisseminator +public class SimpleDCEntryDisseminator extends AbstractSimpleDC implements SwordEntryDisseminator { - private Map<String, String> dcMap; - - public SimpleDCEntryDisseminator() - { - // we should load our DC map from configuration - this.dcMap = new HashMap<String, String>(); - Properties props = ConfigurationManager.getProperties(); - for (Object key : props.keySet()) - { - String keyString = (String) key; - if (keyString.startsWith("sword2.simpledc.")) - { - String k = keyString.substring("sword2.simpledc.".length()); - String v = (String) props.get(key); - this.dcMap.put(k, v); - } - } - } + public SimpleDCEntryDisseminator() { } public DepositReceipt disseminate(Context context, Item item, DepositReceipt receipt) throws DSpaceSwordException, SwordError, SwordServerException { - DCValue[] all = item.getMetadata(Item.ANY, Item.ANY, Item.ANY, Item.ANY); + SimpleDCMetadata md = this.getMetadata(item); + + Map<String, String> dc = md.getDublinCore(); + for (String element : dc.keySet()) + { + String value = dc.get(element); + receipt.addDublinCore(element, value); + } - for (DCValue dcv : all) + Map<String, String> atom = md.getAtom(); + for (String element : atom.keySet()) { - String valueMatch = dcv.schema + "." + dcv.element; - if (dcv.qualifier != null) + String value = atom.get(element); + if ("author".equals(element)) + { + receipt.getWrappedEntry().addAuthor(value); + } + else if ("published".equals(element)) + { + receipt.getWrappedEntry().setPublished(value); + } + else if ("rights".equals(element)) + { + receipt.getWrappedEntry().setRights(value); + } + else if ("summary".equals(element)) + { + receipt.getWrappedEntry().setSummary(value); + } + else if ("title".equals(element)) + { + receipt.getWrappedEntry().setTitle(value); + } + else if ("updated".equals(element)) { - valueMatch += "." + dcv.qualifier; + receipt.getWrappedEntry().setUpdated(value); } - for (String key : this.dcMap.keySet()) - { - String value = this.dcMap.get(key); - if (valueMatch.equals(value)) - { - receipt.addDublinCore(key, dcv.value); - if (key.equals("title")) - { - receipt.getWrappedEntry().setTitle(dcv.value); - } - if (key.equals("abstract")) - { - receipt.getWrappedEntry().setSummary(dcv.value); - } - } - } } return receipt; diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCEntryIngester.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCEntryIngester.java index e1dc8cff1d85cdd8600b0a1d9b4316543759ee08..5f0333c0e1e7e3b56a2e66f48527ca51dc5f922a 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCEntryIngester.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleDCEntryIngester.java @@ -24,31 +24,18 @@ import org.swordapp.server.SwordServerException; import java.io.IOException; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; -public class SimpleDCEntryIngester implements SwordEntryIngester +public class SimpleDCEntryIngester extends AbstractSimpleDC implements SwordEntryIngester { - private Map<String, String> dcMap; - public SimpleDCEntryIngester() { - // we should load our DC map from configuration - this.dcMap = new HashMap<String, String>(); - Properties props = ConfigurationManager.getProperties("swordv2-server"); - for (Object key : props.keySet()) - { - String keyString = (String) key; - if (keyString.startsWith("simpledc.")) - { - String k = keyString.substring("simpledc.".length()); - String v = (String) props.get(key); - this.dcMap.put(k, v); - } - } + this.loadMetadataMaps(); } public DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription) @@ -82,9 +69,11 @@ public class SimpleDCEntryIngester implements SwordEntryIngester } result.setItem(item); - // NOTE: this implementation does not remove pre-existing metadata, as that is actually - // rather hard to handle in DSpace (what do you do about provenance and other administrator - // added metadata?). Instead "replace" does nothing different to "create new" or "add". + // clean out any existing item metadata which is allowed to be replaced + if (replace) + { + this.removeMetadata(item); + } // add the metadata to the item this.addMetadataToItem(deposit, item); @@ -119,6 +108,47 @@ public class SimpleDCEntryIngester implements SwordEntryIngester } } + private void removeMetadata(Item item) + throws DSpaceSwordException + { + String raw = ConfigurationManager.getProperty("swordv2-server", "metadata.replaceable"); + String[] parts = raw.split(","); + for (String part : parts) + { + DCValue dcv = this.makeDCValue(part.trim(), null); + item.clearMetadata(dcv.schema, dcv.element, dcv.qualifier, Item.ANY); + } + } + + private void addUniqueMetadata(DCValue dcv, Item item) + { + String qual = dcv.qualifier; + if (dcv.qualifier == null) + { + qual = Item.ANY; + } + + String lang = dcv.language; + if (dcv.language == null) + { + lang = Item.ANY; + } + DCValue[] existing = item.getMetadata(dcv.schema, dcv.element, qual, lang); + for (DCValue dcValue : existing) + { + // FIXME: probably we want to be slightly more careful about qualifiers and languages + // + // if the submitted value is already attached to the item, just skip it + if (dcValue.value.equals(dcv.value)) + { + return; + } + } + + // if we get to here, go on and add the metadata + item.addMetadata(dcv.schema, dcv.element, dcv.qualifier, dcv.language, dcv.value); + } + private void addMetadataToItem(Deposit deposit, Item item) throws DSpaceSwordException { @@ -134,7 +164,7 @@ public class SimpleDCEntryIngester implements SwordEntryIngester if (titleField != null) { DCValue dcv = this.makeDCValue(titleField, title); - item.addMetadata(dcv.schema, dcv.element, dcv.qualifier, dcv.language, dcv.value); + this.addUniqueMetadata(dcv, item); } } if (summary != null) @@ -143,7 +173,7 @@ public class SimpleDCEntryIngester implements SwordEntryIngester if (abstractField != null) { DCValue dcv = this.makeDCValue(abstractField, summary); - item.addMetadata(dcv.schema, dcv.element, dcv.qualifier, dcv.language, dcv.value); + this.addUniqueMetadata(dcv, item); } } @@ -157,21 +187,12 @@ public class SimpleDCEntryIngester implements SwordEntryIngester continue; } - // clear any pre-existing metadata - DCValue dcv = this.makeDCValue(dsTerm, null); - if (dcv.qualifier == null) - { - item.clearMetadata(dcv.schema, dcv.element, Item.ANY, Item.ANY); - } - else - { - item.clearMetadata(dcv.schema, dcv.element, dcv.qualifier, Item.ANY); - } - // now add all the metadata terms + DCValue dcv = this.makeDCValue(dsTerm, null); for (String value : dc.get(term)) { - item.addMetadata(dcv.schema, dcv.element, dcv.qualifier, dcv.language, value); + dcv.value = value; + this.addUniqueMetadata(dcv, item); } } } @@ -241,9 +262,6 @@ public class SimpleDCEntryIngester implements SwordEntryIngester } } - - - public DCValue makeDCValue(String field, String value) throws DSpaceSwordException { diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleZipContentIngester.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleZipContentIngester.java index 994a1e3d355cc7fc55a290a9f125787aceecf044..ae4028fcfd59fb1c81ef2baa5110f9e467b07a51 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleZipContentIngester.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SimpleZipContentIngester.java @@ -20,6 +20,7 @@ import org.swordapp.server.Deposit; import org.swordapp.server.SwordAuthException; import org.swordapp.server.SwordError; import org.swordapp.server.SwordServerException; +import org.swordapp.server.UriRegistry; import java.io.File; import java.io.IOException; @@ -31,30 +32,11 @@ import java.util.Date; import java.util.Enumeration; import java.util.List; import java.util.zip.ZipEntry; +import java.util.zip.ZipException; import java.util.zip.ZipFile; public class SimpleZipContentIngester extends AbstractSwordContentIngester { - public DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription) - throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException - { - return this.ingest(context, deposit, dso, verboseDescription, null); - } - - public DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription, DepositResult result) - throws DSpaceSwordException, SwordError, SwordAuthException - { - if (dso instanceof Collection) - { - return this.ingestToCollection(context, deposit, (Collection) dso, verboseDescription, result); - } - else if (dso instanceof Item) - { - return this.ingestToItem(context, deposit, (Item) dso, verboseDescription, result); - } - return null; - } - public DepositResult ingestToCollection(Context context, Deposit deposit, Collection collection, VerboseDescription verboseDescription, DepositResult result) throws DSpaceSwordException, SwordError, SwordAuthException { @@ -142,7 +124,7 @@ public class SimpleZipContentIngester extends AbstractSwordContentIngester } private List<Bitstream> unzipToBundle(Context context, File depositFile, Bundle target) - throws DSpaceSwordException, SwordAuthException + throws DSpaceSwordException, SwordError, SwordAuthException { try { @@ -165,6 +147,10 @@ public class SimpleZipContentIngester extends AbstractSwordContentIngester return derivedResources; } + catch (ZipException e) + { + throw new SwordError(UriRegistry.ERROR_BAD_REQUEST, "unable to unzip provided package", e); + } catch (IOException e) { throw new DSpaceSwordException(e); diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/StatementManagerDSpace.java b/dspace-swordv2/src/main/java/org/dspace/sword2/StatementManagerDSpace.java index ca1731d8b88dfa0b67c5976bb1d1a6eebc832425..3834a1d4be0fbffd13e5ac8ba1bfd4cd31218276 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/StatementManagerDSpace.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/StatementManagerDSpace.java @@ -8,7 +8,10 @@ package org.dspace.sword2; import org.apache.log4j.Logger; +import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; import org.dspace.content.Item; +import org.dspace.core.Constants; import org.dspace.core.Context; import org.dspace.core.LogManager; import org.swordapp.server.AuthCredentials; @@ -21,6 +24,7 @@ import org.swordapp.server.SwordServerException; import org.swordapp.server.UriRegistry; import java.io.InputStream; +import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -34,9 +38,9 @@ public class StatementManagerDSpace extends DSpaceSwordAPI implements StatementM public Statement getStatement(String stateIRI, Map<String, String> accept, AuthCredentials authCredentials, SwordConfiguration swordConfig) throws SwordServerException, SwordError, SwordAuthException { + SwordContext sc = null; try { - SwordContext sc = null; SwordConfigurationDSpace config = (SwordConfigurationDSpace) swordConfig; SwordAuthenticator auth = new SwordAuthenticator(); @@ -56,6 +60,13 @@ public class StatementManagerDSpace extends DSpaceSwordAPI implements StatementM // first thing is to figure out what we're being asked to work on SwordUrlManager urlManager = config.getUrlManager(context, config); Item item = urlManager.getItem(context, stateIRI); + if (item == null) + { + throw new SwordError(404); + } + + // find out if we are allowed to read the item's statement + AuthorizeManager.authorizeAction(context, item, Constants.READ); // find out, now we know what we're being asked for, whether this is allowed WorkflowManagerFactory.getInstance().retrieveStatement(context, item); @@ -86,9 +97,24 @@ public class StatementManagerDSpace extends DSpaceSwordAPI implements StatementM Statement statement = disseminator.disseminate(context, item); return statement; } + catch (AuthorizeException e) + { + throw new SwordAuthException(); + } + catch (SQLException e) + { + throw new SwordServerException(e); + } catch (DSpaceSwordException e) { throw new SwordServerException(e); } + finally + { + if (sc != null) + { + sc.abort(); + } + } } } diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordAuthenticator.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordAuthenticator.java index bf74920bf11843a4afd3d65a5dcc3d37fd2c60ad..e9cef62c1b04f92cdf9cf66818279b6645c1eb49 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordAuthenticator.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordAuthenticator.java @@ -86,11 +86,12 @@ public class SwordAuthenticator } /** - * Authenticate the given service document request. This extracts the - * appropriate information from the request and forwards to the - * appropriate authentication method. + * Authenticate the given service document request. This extracts the appropriate + * information from the request and forwards to the appropriate authentication + * method * * @param auth + * @return * @throws DSpaceSwordException * @throws SwordError * @throws SwordAuthException @@ -139,115 +140,6 @@ public class SwordAuthenticator return sc; } - /** - * Authenticate the given atom document request. This extracts the appropriate information - * from the request, and forwards to the appropriate authentication method - * - * @param request - * @return - * @throws SWORDException - * @throws SWORDErrorException - * @throws SWORDAuthenticationException - */ -// public SwordContext authenticate(AtomDocumentRequest request) -// throws SWORDException, SWORDErrorException, SWORDAuthenticationException -// { -// Context context = this.constructContext(request.getIPAddress()); -// SwordContext sc = null; -// try -// { -// sc = this.authenticate(context, request); -// } -// catch (SWORDException e) -// { -// if (context != null && context.isValid()) -// { -// context.abort(); -// } -// throw e; -// } -// catch (SWORDErrorException e) -// { -// if (context != null && context.isValid()) -// { -// context.abort(); -// } -// throw e; -// } -// catch (SWORDAuthenticationException e) -// { -// if (context != null && context.isValid()) -// { -// context.abort(); -// } -// throw e; -// } -// catch (RuntimeException e) -// { -// if (context != null && context.isValid()) -// { -// context.abort(); -// } -// throw e; -// } -// return sc; -// } - - - /** - * Authenticate the deposit request. - * - * @param deposit - * @return - * @throws SWORDException - * @throws SWORDErrorException - * @throws SWORDAuthenticationException - */ -// public SwordContext authenticate(Deposit deposit) -// throws SWORDException, SWORDErrorException, SWORDAuthenticationException -// { -// Context context = this.constructContext(deposit.getIPAddress()); -// SwordContext sc = null; -// try -// { -// sc = this.authenticate(context, deposit); -// } -// catch (SWORDException e) -// { -// if (context != null && context.isValid()) -// { -// context.abort(); -// } -// throw e; -// } -// catch (SWORDErrorException e) -// { -// if (context != null && context.isValid()) -// { -// context.abort(); -// } -// throw e; -// } -// catch (SWORDAuthenticationException e) -// { -// if (context != null && context.isValid()) -// { -// context.abort(); -// } -// throw e; -// } -// catch (RuntimeException e) -// { -// if (context != null && context.isValid()) -// { -// context.abort(); -// } -// throw e; -// } -// return sc; -// } - - /** * Authenticate the given username/password pair, in conjunction with * the onBehalfOf user. The rules are that the username/password pair @@ -355,7 +247,7 @@ public class SwordAuthenticator if (ep != null) { log.info(LogManager.getHeader(context, "sword_unable_to_set_user", "username=" + un)); - throw new SwordAuthException("Unable to authenticate the supplied used"); + throw new SwordAuthException("Unable to authenticate with the supplied credentials"); } else { @@ -984,116 +876,104 @@ public class SwordAuthenticator } } - /** - * Does the given context have the authority to submit to the given item. - * - * The context has permission of the following conditions are met: - * - * IF: the authenticated user is an administrator - * AND: - * (the on-behalf-of user is an administrator - * OR the on-behalf-of user is authorised to WRITE on the item and ADD on the ORIGINAL bundle - * OR the on-behalf-of user is null) - * OR IF: the authenticated user is authorised to WRITE on the item and ADD on the ORIGINAL bundle - * AND: - * (the on-behalf-of user is an administrator - * OR the on-behalf-of user is authorised to WRITE on the item and ADD on the ORIGINAL bundle - * OR the on-behalf-of user is null) - * - * @param swordContext - * @return the array of allowed collections - * @throws DSpaceSwordException - */ - public boolean canSubmitTo(SwordContext swordContext, Item item) - throws DSpaceSwordException - { - // a user can submit to a collection in the following conditions: - // - // - the authenticated user is an administrator - // -- the on-behalf-of user is an administrator - // -- the on-behalf-of user is authorised to WRITE on the item and ADD on the ORIGINAL bundle - // -- the on-behalf-of user is null - // - the authenticated user is authorised to WRITE on the item and ADD on the ORIGINAL bundle - // -- the on-behalf-of user is an administrator - // -- the on-behalf-of user is authorised to WRITE on the item and ADD on the ORIGINAL bundle - // -- the on-behalf-of user is null - - try - { - boolean authAllowed = false; - boolean oboAllowed = false; - - // check for obo null - if (swordContext.getOnBehalfOf() == null) - { - oboAllowed = true; - } - - // get the "ORIGINAL" bundle(s) - Bundle[] bundles = item.getBundles("ORIGINAL"); - - // look up the READ policy on the community. This will include determining if the user is an administrator - // so we do not need to check that separately - if (!authAllowed) - { - boolean write = AuthorizeManager.authorizeActionBoolean(swordContext.getAuthenticatorContext(), item, Constants.WRITE); - - boolean add = false; - if (bundles.length == 0) - { - add = AuthorizeManager.authorizeActionBoolean(swordContext.getAuthenticatorContext(), item, Constants.ADD); - } - else + public boolean canSubmitTo(SwordContext swordContext, Item item) + throws DSpaceSwordException + { + // a context can submit to an item if the following are satisfied + // + // 1/ the primary authenticating user is authenticated (which is implicit + // in there being a context in the first place) + // 2/ If an On-Behalf-Of request, the On-Behalf-Of user is authorised to + // carry out the action and the authenticating user is in the list + // of allowed mediaters + // 3/ If not an On-Behalf-Of request, the authenticating user is authorised + // to carry out the action + + try + { + boolean isObo = swordContext.getOnBehalfOf() != null; + Context allowContext = null; + if (isObo) + { + // we need to find out if the authenticated user is permitted to mediate + if (!this.allowedToMediate(swordContext.getAuthenticatorContext())) { - for (int i = 0; i < bundles.length; i++) - { - add = AuthorizeManager.authorizeActionBoolean(swordContext.getAuthenticatorContext(), bundles[i], Constants.ADD); - if (!add) - { - break; - } - } + return false; } + allowContext = swordContext.getOnBehalfOfContext(); + } + else + { + allowContext = swordContext.getAuthenticatorContext(); + } - authAllowed = write && add; - } - - // if we have not already determined that the obo user is ok to submit, look up the READ policy on the - // community. THis will include determining if the user is an administrator. - if (!oboAllowed) - { - boolean write = AuthorizeManager.authorizeActionBoolean(swordContext.getOnBehalfOfContext(), item, Constants.WRITE); + // we now need to check whether the selected context that we are authorising + // has the appropriate permissions + boolean write = AuthorizeManager.authorizeActionBoolean(allowContext, item, Constants.WRITE); - boolean add = false; - if (bundles.length == 0) - { - add = AuthorizeManager.authorizeActionBoolean(swordContext.getAuthenticatorContext(), item, Constants.ADD); - } - else + Bundle[] bundles = item.getBundles("ORIGINAL"); + boolean add = false; + if (bundles.length == 0) + { + add = AuthorizeManager.authorizeActionBoolean(allowContext, item, Constants.ADD); + } + else + { + for (int i = 0; i < bundles.length; i++) { - for (int i = 0; i < bundles.length; i++) + add = AuthorizeManager.authorizeActionBoolean(allowContext, bundles[i], Constants.ADD); + if (!add) { - add = AuthorizeManager.authorizeActionBoolean(swordContext.getAuthenticatorContext(), bundles[i], Constants.ADD); - if (!add) - { - break; - } + break; } } + } - oboAllowed = write && add; - } + boolean allowed = write && add; + return allowed; + } + catch (SQLException e) + { + log.error("Caught exception: ", e); + throw new DSpaceSwordException(e); + } + } - // final check to see if we are allowed to READ - return (authAllowed && oboAllowed); + private boolean allowedToMediate(Context context) + { + // get the configuration + String mediatorCfg = ConfigurationManager.getProperty("swordv2-server", "on-behalf-of.update.mediators"); + if (mediatorCfg == null) + { + // if there's no explicit list of mediators, then anyone can mediate + return true; + } - } - catch (SQLException e) - { - log.error("Caught exception: ", e); - throw new DSpaceSwordException(e); - } - } + // get the email and netid of the mediator + EPerson eperson = context.getCurrentUser(); + if (eperson == null) + { + return false; + } + String email = eperson.getEmail(); + String netid = eperson.getNetid(); + + String[] mediators = mediatorCfg.split(","); + for (String mediator : mediators) + { + String m = mediator.trim(); + if (email != null && m.equals(email.trim())) + { + return true; + } + if (netid != null && m.equals(netid.trim())) + { + return true; + } + } + + return false; + } /** * Can the given context submit to the specified DSpace object? diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordConfigurationDSpace.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordConfigurationDSpace.java index 00138b2dbbe5858ac5ec75a3697098a893ac53de..6396f81917260bbbed746255c90c486dff9fa6a8 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordConfigurationDSpace.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordConfigurationDSpace.java @@ -14,6 +14,7 @@ import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; +import org.dspace.core.PluginManager; import org.jaxen.function.FalseFunction; import org.swordapp.server.SwordConfiguration; import org.swordapp.server.SwordError; @@ -168,7 +169,7 @@ public class SwordConfigurationDSpace implements SwordConfiguration public boolean returnStackTraceInError() { - return true; + return ConfigurationManager.getBooleanProperty("swordv2-server", "verbose-description.error.enable"); } public boolean returnErrorBody() @@ -206,7 +207,17 @@ public class SwordConfigurationDSpace implements SwordConfiguration return this.getStringProperty("swordv2-server", "upload.tempdir", null); } - /////////////////////////////////////////////////////////////////////////////////// + public String getAlternateUrl() + { + return ConfigurationManager.getProperty("swordv2-server", "error.alternate.url"); + } + + public String getAlternateUrlContentType() + { + return ConfigurationManager.getProperty("swordv2-server", "error.alternate.content-type"); + } + + /////////////////////////////////////////////////////////////////////////////////// // Required by DSpace-side implementation /////////////////////////////////////////////////////////////////////////////////// @@ -216,6 +227,7 @@ public class SwordConfigurationDSpace implements SwordConfiguration } public List<String> getDisseminatePackaging() + throws DSpaceSwordException, SwordError { List<String> dps = new ArrayList<String>(); Properties props = ConfigurationManager.getProperties("swordv2-server"); @@ -237,7 +249,23 @@ public class SwordConfigurationDSpace implements SwordConfiguration } String value = props.getProperty((key)); - dps.add(value); + + // now we want to ensure that the packaging format we offer has a disseminator + // associated with it + boolean disseminable = true; + try + { + SwordContentDisseminator disseminator = SwordDisseminatorFactory.getContentInstance(null, value); + } + catch (SwordError e) + { + disseminable = false; + } + + if (disseminable) + { + dps.add(value); + } } return dps; } @@ -253,8 +281,9 @@ public class SwordConfigurationDSpace implements SwordConfiguration } /** - * Get the bundle name that SWORD will store its original deposit - * packages in, when storing them inside an item. + * Get the bundle name that sword will store its original deposit packages in, when + * storing them inside an item + * @return */ public String getSwordBundle() { @@ -594,9 +623,49 @@ public class SwordConfigurationDSpace implements SwordConfiguration throws DSpaceSwordException { List<String> accepts = this.getAccepts(context, dso); + for (String acc : accepts) + { + if (this.contentTypeMatches(type, acc)) + { + return true; + } + } return accepts.contains(type); } + private boolean contentTypeMatches(String type, String pattern) + { + if ("*/*".equals(pattern.trim())) + { + return true; + } + + // get the prefix and suffix match patterns + String[] bits = pattern.trim().split("/"); + String prefixPattern = bits.length > 0 ? bits[0] : "*"; + String suffixPattern = bits.length > 1 ? bits[1] : "*"; + + // get the incoming type prefix and suffix + String[] tbits = type.trim().split("/"); + String typePrefix = tbits.length > 0 ? tbits[0] : "*"; + String typeSuffix = tbits.length > 1 ? tbits[1] : "*"; + + boolean prefixMatch = false; + boolean suffixMatch = false; + + if ("*".equals(prefixPattern) || prefixPattern.equals(typePrefix)) + { + prefixMatch = true; + } + + if ("*".equals(suffixPattern) || suffixPattern.equals(typeSuffix)) + { + suffixMatch = true; + } + + return prefixMatch && suffixMatch; + } + public String getStateUri(String state) { return ConfigurationManager.getProperty("swordv2-server", "state." + state + ".uri"); @@ -606,4 +675,9 @@ public class SwordConfigurationDSpace implements SwordConfiguration { return ConfigurationManager.getProperty("swordv2-server", "state." + state + ".description"); } + + public boolean allowUnauthenticatedMediaAccess() + { + return false; + } } diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordDisseminatorFactory.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordDisseminatorFactory.java index 7849b3e7a2ef8428ee87441dc7abf3fb2efe6ac7..5bbc1b537fb3a79fbff6fc5a06f23cfd2f5d0a93 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordDisseminatorFactory.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordDisseminatorFactory.java @@ -10,6 +10,7 @@ package org.dspace.sword2; import org.dspace.core.PluginManager; import org.swordapp.server.SwordError; import org.swordapp.server.SwordServerException; +import org.swordapp.server.UriRegistry; import java.util.List; import java.util.Map; @@ -89,7 +90,7 @@ public class SwordDisseminatorFactory if (disseminator == null) { - throw new SwordError(DSpaceUriRegistry.NOT_ACCEPTABLE, 406, "No plugin can disseminate the requested formats"); + throw new SwordError(UriRegistry.ERROR_CONTENT, 406, "No plugin can disseminate the requested formats"); } disseminator.setPackaging(acceptPackaging); @@ -126,7 +127,7 @@ public class SwordDisseminatorFactory if (disseminator == null) { - throw new SwordError(DSpaceUriRegistry.NOT_ACCEPTABLE, 406, "No plugin can disseminate the requested formats"); + throw new SwordError(UriRegistry.ERROR_CONTENT, 406, "No plugin can disseminate the requested formats"); } return disseminator; diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordMETSContentIngester.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordMETSContentIngester.java index 9bde8137e9548ae1444add9f0a21f9ceee0460ab..98d7bf97c5d5ba31f1a47546a3c0e3d5e0514b81 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordMETSContentIngester.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordMETSContentIngester.java @@ -7,15 +7,21 @@ */ package org.dspace.sword2; +import java.io.ByteArrayInputStream; import java.io.File; import org.apache.log4j.Logger; +import org.dspace.content.Bitstream; +import org.dspace.content.BitstreamFormat; +import org.dspace.content.Bundle; import org.dspace.content.Collection; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.content.WorkspaceItem; import org.dspace.content.packager.PackageIngester; import org.dspace.content.packager.PackageParameters; +import org.dspace.content.packager.PackageUtils; import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; import org.dspace.core.PluginManager; @@ -38,71 +44,87 @@ public class SwordMETSContentIngester extends AbstractSwordContentIngester return this.ingest(context, deposit, dso, verboseDescription, null); } - /* (non-Javadoc) - * @see org.dspace.sword.SWORDIngester#ingest(org.dspace.core.Context, org.purl.sword.base.Deposit) - */ - public DepositResult ingest(Context context, Deposit deposit, DSpaceObject dso, VerboseDescription verboseDescription, DepositResult result) - throws DSpaceSwordException, SwordError - { - // FIXME: it's not clear how to make the METS ingester work over an existing item - - try + @Override + public DepositResult ingestToCollection(Context context, Deposit deposit, Collection collection, VerboseDescription verboseDescription, DepositResult result) + throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException + { + try { - // first, make sure this is the right kind of ingester, and set the collection - if (!(dso instanceof Collection)) - { - throw new DSpaceSwordException("Tried to run an ingester on wrong target type"); - } - Collection collection = (Collection) dso; + // if we are actuall given an item in the deposit result of a previous operation + // then we do an ingestToItem + if (result != null) + { + Item item = result.getItem(); + return this.ingestToItem(context, deposit, item, verboseDescription, result); + } + + // otherwise, go on and do a create ... + + // create the an item in the workspace. This is necessary, because later + // we are going to ask a package ingester to /replace/ this item, which gives + // us finer control over the workflow state of the item, whereas asking + // the ingester to /create/ this item causes it to be injected into the workflow, + // irrespective of the In-Progress header provided by the depositor + WorkspaceItem wsi = WorkspaceItem.create(context, collection, true); + Item item = wsi.getItem(); + + // need to add a licence file, otherwise the METS replace function raises a NullPointerException + String licence = collection.getLicense(); + if (PackageUtils.findDepositLicense(context, item) == null) + { + PackageUtils.addDepositLicense(context, licence, item, collection); + } // get deposited file as InputStream File depositFile = deposit.getFile(); // load the plugin manager for the required configuration - String cfg = ConfigurationManager.getProperty("swordv2-server", "mets-ingester.package-ingester"); + String cfg = ConfigurationManager.getProperty("sword-server", "mets-ingester.package-ingester"); if (cfg == null || "".equals(cfg)) { cfg = "METS"; // default to METS } verboseDescription.append("Using package manifest format: " + cfg); - PackageIngester pi = (PackageIngester)PluginManager.getNamedPlugin("swordv2-server", PackageIngester.class, cfg); + PackageIngester pi = (PackageIngester) PluginManager.getNamedPlugin(PackageIngester.class, cfg); verboseDescription.append("Loaded package ingester: " + pi.getClass().getName()); - // the licence is either in the zip or the mets manifest. Either way - // it's none of our business here - String licence = null; - // Initialize parameters to packager PackageParameters params = new PackageParameters(); - // Force package ingester to respect Collection workflows - params.setWorkflowEnabled(true); - // Should restore mode be enabled, i.e. keep existing handle? - if (ConfigurationManager.getBooleanProperty("swordv2-server", "restore-mode.enable",false)) - params.setRestoreModeEnabled(true); + // Force package ingester to respect Collection workflows + params.setWorkflowEnabled(true); + + // Should restore mode be enabled, i.e. keep existing handle? + if (ConfigurationManager.getBooleanProperty("sword-server", "restore-mode.enable",false)) + { + params.setRestoreModeEnabled(true); + } + + // Whether or not to use the collection template + params.setUseCollectionTemplate(ConfigurationManager.getBooleanProperty("mets.default.ingest.useCollectionTemplate", false)); // ingest the item from the temp file - DSpaceObject ingestedObject = pi.ingest(context, collection, depositFile, params, licence); + DSpaceObject ingestedObject = pi.replace(context, item, depositFile, params); if (ingestedObject == null) { verboseDescription.append("Failed to ingest the package; throwing exception"); - throw new SwordError(DSpaceUriRegistry.UNPACKAGE_FAIL, "METS package ingester failed to unpack package"); + throw new SwordError(DSpaceUriRegistry.UNPACKAGE_FAIL, "METS package ingester failed to unpack package"); } - //Verify we have an Item as a result -- SWORD can only ingest Items - if (!(ingestedObject instanceof Item)) - { - throw new DSpaceSwordException("DSpace Ingester returned wrong object type -- not an Item result."); - } - else + // Verify we have an Item as a result + if (!(ingestedObject instanceof Item)) { - //otherwise, we have an item, and a workflow should have already been started for it. - verboseDescription.append("Workflow process started"); + throw new DSpaceSwordException("DSpace Ingester returned wrong object type -- not an Item result."); } + else + { + //otherwise, we have an item, and a workflow should have already been started for it. + verboseDescription.append("Workflow process started"); + } // get reference to item so that we can report on it - Item installedItem = (Item)ingestedObject; + Item installedItem = (Item) ingestedObject; // update the item metadata to inclue the current time as // the updated date @@ -142,19 +164,112 @@ public class SwordMETSContentIngester extends AbstractSwordContentIngester return dr; } - catch (RuntimeException re) - { - log.error("caught exception: ", re); - throw re; - } - catch (Exception e) + catch (RuntimeException re) + { + log.error("caught exception: ", re); + throw re; + } + catch (Exception e) + { + log.error("caught exception: ", e); + throw new DSpaceSwordException(e); + } + } + + @Override + public DepositResult ingestToItem(Context context, Deposit deposit, Item item, VerboseDescription verboseDescription, DepositResult result) + throws DSpaceSwordException, SwordError, SwordAuthException, SwordServerException + { + if (result == null) + { + result = new DepositResult(); + } + + try { - log.error("caught exception: ", e); - throw new DSpaceSwordException(e); + // get deposited file as InputStream + File depositFile = deposit.getFile(); + + // load the plugin manager for the required configuration + String cfg = ConfigurationManager.getProperty("sword-server", "mets-ingester.package-ingester"); + if (cfg == null || "".equals(cfg)) + { + cfg = "METS"; // default to METS + } + verboseDescription.append("Using package manifest format: " + cfg); + + PackageIngester pi = (PackageIngester) PluginManager.getNamedPlugin(PackageIngester.class, cfg); + verboseDescription.append("Loaded package ingester: " + pi.getClass().getName()); + + // Initialize parameters to packager + PackageParameters params = new PackageParameters(); + + // Force package ingester to respect Collection workflows + params.setWorkflowEnabled(true); + + // Should restore mode be enabled, i.e. keep existing handle? + if (ConfigurationManager.getBooleanProperty("sword-server", "restore-mode.enable",false)) + { + params.setRestoreModeEnabled(true); + } + + // Whether or not to use the collection template + params.setUseCollectionTemplate(ConfigurationManager.getBooleanProperty("mets.default.ingest.useCollectionTemplate", false)); + + // ingest the item from the temp file + DSpaceObject ingestedObject = pi.replace(context, item, depositFile, params); + if (ingestedObject == null) + { + verboseDescription.append("Failed to replace the package; throwing exception"); + throw new SwordError(DSpaceUriRegistry.UNPACKAGE_FAIL, "METS package ingester failed to unpack package"); + } + + // Verify we have an Item as a result + if (!(ingestedObject instanceof Item)) + { + throw new DSpaceSwordException("DSpace Ingester returned wrong object type -- not an Item result."); + } + + // get reference to item so that we can report on it + Item installedItem = (Item) ingestedObject; + + // update the item metadata to inclue the current time as + // the updated date + this.setUpdatedDate(installedItem, verboseDescription); + + // in order to write these changes, we need to bypass the + // authorisation briefly, because although the user may be + // able to add stuff to the repository, they may not have + // WRITE permissions on the archive. + boolean ignore = context.ignoreAuthorization(); + context.setIgnoreAuthorization(true); + installedItem.update(); + context.setIgnoreAuthorization(ignore); + + // for some reason, DSpace will not give you the handle automatically, + // so we have to look it up + String handle = HandleManager.findHandle(context, installedItem); + + verboseDescription.append("Replace successful"); + + result.setItem(installedItem); + result.setTreatment(this.getTreatment()); + + return result; } - } + catch (RuntimeException re) + { + log.error("caught exception: ", re); + throw re; + } + catch (Exception e) + { + log.error("caught exception: ", e); + throw new DSpaceSwordException(e); + } + } - /** + /** * The human readable description of the treatment this ingester has * put the deposit through * diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordUrlManager.java b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordUrlManager.java index 1e0d3d26fc0da40e1542129dbb3ad10caf8cfd45..7a54504085a0b8f00188dd6b3b0a267118ad726f 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/SwordUrlManager.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/SwordUrlManager.java @@ -150,7 +150,7 @@ public class SwordUrlManager catch (SQLException e) { // log.error("Caught exception:", e); - throw new DSpaceSwordException("There was a problem resolving the collection", e); + throw new DSpaceSwordException("There was a problem resolving the item", e); } } @@ -202,6 +202,10 @@ public class SwordUrlManager } DSpaceObject dso = HandleManager.resolveToObject(context, handle); + if (dso == null) + { + return null; + } if (!(dso instanceof Collection)) { @@ -281,7 +285,11 @@ public class SwordUrlManager } DSpaceObject dso = HandleManager.resolveToObject(context, url); - if (dso instanceof Collection || dso instanceof Community) + if (dso == null) + { + return null; + } + else if (dso instanceof Collection || dso instanceof Community) { return dso; } @@ -486,56 +494,6 @@ public class SwordUrlManager } } - /** - * Get the media link URL for the given bitstream. - * - * @param bitstream - * @throws DSpaceSwordException - */ - public String getMediaLink(Bitstream bitstream) - throws DSpaceSwordException - { -// try -// { -// Bundle[] bundles = bitstream.getBundles(); -// Bundle parent = null; -// if (bundles.length > 0) -// { -// parent = bundles[0]; -// } -// else -// { -// throw new DSpaceSwordException("Encountered orphaned bitstream"); -// } -// -// Item[] items = parent.getItems(); -// Item item; -// if (items.length > 0) -// { -// item = items[0]; -// } -// else -// { -// throw new DSpaceSwordException("Encountered orphaned bundle"); -// } -// -// String itemUrl = this.getMediaLink(item); -// if (itemUrl.equals(this.getBaseMediaLinkUrl())) -// { -// return itemUrl; -// } -// -// String bsUrl = itemUrl + "/bitstream/" + bitstream.getID(); -// -// return bsUrl; -// } -// catch (SQLException e) -// { -// throw new DSpaceSWORDException(e); -// } - return null; - } - // FIXME: we need a totally new kind of URL scheme; perhaps we write the identifier into the item public String getAtomStatementUri(Item item) throws DSpaceSwordException @@ -562,9 +520,34 @@ public class SwordUrlManager } public String getSplashUrl(Item item) + throws DSpaceSwordException { - // FIXME: this appears not to return the item's handle - return HandleManager.getCanonicalForm(item.getHandle()); + WorkflowTools wft = new WorkflowTools(); + + // if the item is in the workspace, we need to give it it's own + // special identifier + if (wft.isItemInWorkspace(context, item)) + { + String urlTemplate = ConfigurationManager.getProperty("swordv2-server", "workspace.url-template"); + if (urlTemplate != null) + { + return urlTemplate.replace("#wsid#", Integer.toString(wft.getWorkspaceItem(context, item).getID())); + } + } + // otherwise, it may be in the workflow, in which case there is + // no identifier + else if (wft.isItemInWorkflow(context, item)) + { + // do nothing + return null; + } + // finally, otherwise we need to just return the handle of the + // item + else + { + return HandleManager.getCanonicalForm(item.getHandle()); + } + return null; } public IRI getContentUrl(Item item) diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/VersionManager.java b/dspace-swordv2/src/main/java/org/dspace/sword2/VersionManager.java index fca8cd08bcb838ecacaf55d12baa30e9b1eb3ea1..72e4b4f98c8c0f39e873adab64fd61e7a3993f6f 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/VersionManager.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/VersionManager.java @@ -20,36 +20,41 @@ import java.util.Date; public class VersionManager { - public void emptyBundle(Item item, String name) + public void removeBundle(Item item, String name) throws SQLException, AuthorizeException, IOException { boolean keep = ConfigurationManager.getBooleanProperty("swordv2-server", "versions.keep"); Bundle[] bundles = item.getBundles(name); for (Bundle b : bundles) { - this.emptyBundle(item, b, keep); + this.removeBundle(item, b, keep); } } - public void emptyBundle(Item item, Bundle source) + public void removeBundle(Item item, Bundle source) throws SQLException, AuthorizeException, IOException { boolean keep = ConfigurationManager.getBooleanProperty("swordv2-server", "versions.keep"); - this.emptyBundle(item, source, keep); + this.removeBundle(item, source, keep); } - public void emptyBundle(Item item, Bundle source, boolean archive) + public void removeBundle(Item item, Bundle source, boolean archive) throws SQLException, AuthorizeException, IOException { + // archive the bundle contents if desired if (archive) { this.archiveBundle(item, source); } + // remove all the bitstreams from the bundle for (Bitstream bitstream : source.getBitstreams()) { source.removeBitstream(bitstream); } + + // delete the bundle itself + item.removeBundle(source); } public void removeBitstream(Item item, Bitstream bitstream) @@ -76,15 +81,27 @@ public class VersionManager bundle.removeBitstream(bitstream); } } + + // there is nowhere in the metadata to say when this file was moved, so we + // are going to drop it into the description + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + String desc = bitstream.getDescription(); + String newDesc = "[Deleted on: " + sdf.format(new Date()) + "] "; + if (desc != null) + { + newDesc += desc; + } + bitstream.setDescription(newDesc); + bitstream.update(); } - public Bundle archiveBitstream(Item item, Bitstream bitstream) + private Bundle archiveBitstream(Item item, Bitstream bitstream) throws SQLException, AuthorizeException, IOException { - String swordBundle = ConfigurationManager.getProperty("swordv2-server", "bundle.name"); + String swordBundle = ConfigurationManager.getProperty("swordv2-server", "bundle.deleted"); if (swordBundle == null) { - swordBundle = "SWORD"; + swordBundle = "DELETED"; } Bundle[] swords = item.getBundles(swordBundle); @@ -101,18 +118,18 @@ public class VersionManager return archive; } - public void archiveBitstream(Bundle target, Bitstream bitstream) + private void archiveBitstream(Bundle target, Bitstream bitstream) throws SQLException, AuthorizeException, IOException { target.addBitstream(bitstream); } - public void archiveBundle(Item item, Bundle source) + private void archiveBundle(Item item, Bundle source) throws SQLException, AuthorizeException, IOException { // get the datestamped root bundle name SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - String oldName = "V_" + sdf.format(new Date()); + String oldName = "VER" + sdf.format(new Date()); oldName = this.getNumberedName(item, oldName, 0); Bundle old = item.createBundle(oldName); diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowManagerDefault.java b/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowManagerDefault.java index 2d691def1f2bc754cd35a1a2ed8083ea436f3672..db3cdbdaae9ad53a1074068cee4ecdf68529e15e 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowManagerDefault.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowManagerDefault.java @@ -11,6 +11,7 @@ import org.dspace.content.Bitstream; import org.dspace.content.Bundle; import org.dspace.content.Collection; import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; import org.swordapp.server.Deposit; import org.swordapp.server.SwordError; @@ -18,6 +19,11 @@ import org.swordapp.server.UriRegistry; import java.sql.SQLException; +/** + * This implementation of WorkflowManager is restricted and only allows UPDATE and DELETE operations + * on items which are not in workflow, in archive, or withdrawn. These operations can only be + * performed on items which are in the deposit phase. + */ public class WorkflowManagerDefault implements WorkflowManager { public void retrieveServiceDoc(Context context) throws SwordError @@ -60,6 +66,14 @@ public class WorkflowManagerDefault implements WorkflowManager public void replaceMetadata(Context context, Item item) throws SwordError, DSpaceSwordException { + boolean allowUpdate = ConfigurationManager.getBooleanProperty("swordv2-server", "workflowmanagerdefault.always-update-metadata"); + if (allowUpdate) + { + // all updates are allowed + return; + } + + // otherwise, go ahead and figure out the state WorkflowTools wft = new WorkflowTools(); if (item.isArchived() || item.isWithdrawn()) { @@ -118,6 +132,15 @@ public class WorkflowManagerDefault implements WorkflowManager public void replaceBitstream(Context context, Bitstream bitstream) throws SwordError, DSpaceSwordException { + // File replace with DSpace actually violates the RESTful environment, so it is + // turned off by default, and strongly advised against. Nonetheless, it is used + // by some DepositMO aware extensions, so must be supported (as shown below) + boolean fileReplace = ConfigurationManager.getBooleanProperty("swordv2-server", "workflowmanagerdefault.file-replace.enable"); + if (!fileReplace) + { + throw new SwordError(UriRegistry.ERROR_METHOD_NOT_ALLOWED, "DSpace does not support file replace; you should DELETE the original file and PUT the new one"); + } + // this is equivalent to asking whether the media resource in the item can be deleted try { @@ -156,6 +179,14 @@ public class WorkflowManagerDefault implements WorkflowManager public void addMetadata(Context context, Item item) throws SwordError, DSpaceSwordException { + boolean allowUpdate = ConfigurationManager.getBooleanProperty("swordv2-server", "workflowmanagerdefault.always-update-metadata"); + if (allowUpdate) + { + // all updates are allowed + return; + } + + // otherwise, lookup the state of the item WorkflowTools wft = new WorkflowTools(); if (item.isArchived() || item.isWithdrawn()) { @@ -227,17 +258,17 @@ public class WorkflowManagerDefault implements WorkflowManager boolean inarch = item.isArchived() || item.isWithdrawn(); // in progress inws inwf inarch action description - // 0 0 0 1 ERROR the deposit finished, and the item is in the archive; this should never be allowed to arise + // 0 0 0 1 NOTHING the deposit finished, and the item is in the archive; // 0 0 1 0 NOTHING the deposit finished, and the item is in the workflow. Carry on as normal // 0 1 0 0 START WF the deposit is finished, and the item is in the workflow, so we start it - // 1 0 0 1 ERROR the deposit is not finished, and the item is in the archive; this should never be allowed to arise + // 1 0 0 1 NOTHING the deposit is not finished, and the item is in the archive; // 1 0 1 0 STOP WF the deposit is not finished, and it is in the workflow. Pull it out into the workspace // 1 1 0 0 NOTHING the deposit is not finished, and is in the workspace; leave it there if (!deposit.isInProgress() && inarch) { - verboseDescription.append("The deposit is finished, but the item is already in the archive"); - throw new DSpaceSwordException("Invalid workflow state"); + verboseDescription.append("The deposit is finished, and the item is already in the archive"); + // throw new DSpaceSwordException("Invalid workflow state"); } if (!deposit.isInProgress() && inws) @@ -248,8 +279,8 @@ public class WorkflowManagerDefault implements WorkflowManager if (deposit.isInProgress() && inarch) { - verboseDescription.append("The deposit is not finished, but the item is already in the archive"); - throw new DSpaceSwordException("Invalid workflow state"); + verboseDescription.append("The deposit is not finished, and the item is already in the archive"); + // throw new DSpaceSwordException("Invalid workflow state"); } if (deposit.isInProgress() && inwf) diff --git a/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowTools.java b/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowTools.java index 2633883c18a81552963775e199711309879a1826..d89ae1a4846eb58d97128aa475af76df490955cc 100644 --- a/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowTools.java +++ b/dspace-swordv2/src/main/java/org/dspace/sword2/WorkflowTools.java @@ -13,6 +13,9 @@ import org.dspace.content.Item; import org.dspace.content.WorkspaceItem; import org.dspace.core.ConfigurationManager; import org.dspace.core.Context; +import org.dspace.storage.rdbms.DatabaseManager; +import org.dspace.storage.rdbms.TableRow; +import org.dspace.storage.rdbms.TableRowIterator; import org.dspace.workflow.WorkflowItem; import org.dspace.workflow.WorkflowManager; import org.dspace.xmlworkflow.WorkflowConfigurationException; diff --git a/dspace-swordv2/src/main/webapp/WEB-INF/web.xml b/dspace-swordv2/src/main/webapp/WEB-INF/web.xml index 5ec371daa26710821b334169a2e108dbca4dc3b0..2ad83f297067435bfb7b2e403100f2ac4c65209e 100644 --- a/dspace-swordv2/src/main/webapp/WEB-INF/web.xml +++ b/dspace-swordv2/src/main/webapp/WEB-INF/web.xml @@ -24,11 +24,11 @@ <!-- new ConfigurationService initialization for dspace.dir --> <context-param> - <description> - The location of the main DSpace configuration file - </description> <param-name>dspace.dir</param-name> <param-value>${dspace.dir}</param-value> + <description> + The location of the main DSpace directory + </description> </context-param> <!-- Configuration Information --> diff --git a/dspace-xmlui/pom.xml b/dspace-xmlui/pom.xml index 4d111504161c84976ec71cf01108d4aade708108..12f5aac5144eeeed8260de39f6e4c532a4576a8d 100644 --- a/dspace-xmlui/pom.xml +++ b/dspace-xmlui/pom.xml @@ -11,7 +11,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> @@ -97,6 +97,10 @@ <groupId>org.dspace</groupId> <artifactId>dspace-api</artifactId> </dependency> + <dependency> + <groupId>org.dspace</groupId> + <artifactId>dspace-services</artifactId> + </dependency> <!-- Custom build DSpace cocoon --> <dependency> diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/ControlPanel.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/ControlPanel.java index 0f9e1bba54481ccde9c4a0df5c050bd96f6503a4..434dc396b3e7e25ad9bc812dc6023949c8155f58 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/ControlPanel.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/ControlPanel.java @@ -366,7 +366,7 @@ public class ControlPanel extends AbstractDSpaceTransformer implements Serviceab list.addLabel(T_JAVA_VERSION); list.addItem(System.getProperty("java.version")); list.addLabel(T_JAVA_VENDOR); - list.addItem(System.getProperty("java.vendor")); + list.addItem(System.getProperty("java.vm.name")); list.addLabel(T_OS_NAME); list.addItem(System.getProperty("os.name")); list.addLabel(T_OS_ARCH); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/FlowItemUtils.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/FlowItemUtils.java index 4835f6d907d5f8acb4535c4e9dd89e556e2e99c0..1b5a0c64cac10f5e1b6d2dc6991595ebfc495e9d 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/FlowItemUtils.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/FlowItemUtils.java @@ -333,8 +333,6 @@ public class FlowItemUtils Item item = Item.find(context, itemID); item.setDiscoverable(false); - // private item is withdrawn as well - item.withdraw(); item.update(); context.commit(); @@ -359,8 +357,6 @@ public class FlowItemUtils Item item = Item.find(context, itemID); item.setDiscoverable(true); - // since private Items are withdrawn they are reinstated during "make it public" process - item.reinstate(); item.update(); context.commit(); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/eperson/EditEPersonForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/eperson/EditEPersonForm.java index 67218c9f5c5cb1f9172d94ed1d628b4c6cff401d..4c4e4ad97eab7b7310cbccda64b38e7d2babda8d 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/eperson/EditEPersonForm.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/eperson/EditEPersonForm.java @@ -310,7 +310,7 @@ public class EditEPersonForm extends AbstractDSpaceTransformer Button submitLoginAs = special.addButton("submit_login_as"); submitLoginAs.setValue(T_submit_login_as); - if (!ConfigurationManager.getBooleanProperty("xmlui.user.assumelogin", false)) + if (!ConfigurationManager.getBooleanProperty("webui.user.assumelogin", false)) { submitLoginAs.setDisabled(); } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/AddBitstreamForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/AddBitstreamForm.java index d9889202bdc7d293104b77b11afe7ef378f90145..62ebc5734d1869f2ce78a8fc61a97bee0414a3b0 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/AddBitstreamForm.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/AddBitstreamForm.java @@ -76,7 +76,7 @@ public class AddBitstreamForm extends AbstractDSpaceTransformer public void addBody(Body body) throws SAXException, WingException, UIException, SQLException, IOException, AuthorizeException { - isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); + isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); int itemID = parameters.getParameterAsInteger("itemID", -1); org.dspace.content.Item item = org.dspace.content.Item.find(context, itemID); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/EditBitstreamForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/EditBitstreamForm.java index 18ebcb67d7e88834e3b9dfa900c5d132135be9b0..19114bdb603d16432f0f50568bb2dc8fdd56a641 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/EditBitstreamForm.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/EditBitstreamForm.java @@ -78,7 +78,7 @@ public class EditBitstreamForm extends AbstractDSpaceTransformer UIException, SQLException, IOException, AuthorizeException { - isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); + isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); // Get our parameters int bitstreamID = parameters.getParameterAsInteger("bitstreamID",-1); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/EditItemStatusForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/EditItemStatusForm.java index bac058cd0250e2cd6014ce8f3cbf589cae3f68e0..0698e2ab5fca2ffca041e1de281edfb61876a17b 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/EditItemStatusForm.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/item/EditItemStatusForm.java @@ -216,27 +216,26 @@ public class EditItemStatusForm extends AbstractDSpaceTransformer { if(item.isDiscoverable()) { itemInfo.addLabel(T_label_private); - try - { - // who can Withdraw can also Make It Private - AuthorizeUtil.authorizeWithdrawItem(context, item); - itemInfo.addItem().addButton("submit_private").setValue(T_submit_private); - } - catch (AuthorizeException authex) - { - addNotAllowedButton(itemInfo.addItem(), "submit_private", T_submit_private); - } + if (AuthorizeManager.authorizeActionBoolean(context, item, + Constants.WRITE)) + { + itemInfo.addItem().addButton("submit_private") + .setValue(T_submit_private); + } + else + { + addNotAllowedButton(itemInfo.addItem(), "submit_private", + T_submit_private); + } } else { itemInfo.addLabel(T_label_public); - try + if (AuthorizeManager.authorizeActionBoolean(context, item, Constants.WRITE)) { - // who can Reinstate can also Make It Public - AuthorizeUtil.authorizeReinstateItem(context, item); itemInfo.addItem().addButton("submit_public").setValue(T_submit_public); } - catch (AuthorizeException authex) + else { addNotAllowedButton(itemInfo.addItem(), "submit_public", T_submit_public); } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/SearchItemForm.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/SearchItemForm.java index 89e712a97cc3c5eb9d781364b65404543a35c3ee..47b73a9fa988ff4db94c9950fcd8337ec5ae1b48 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/SearchItemForm.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/administrative/mapper/SearchItemForm.java @@ -10,6 +10,7 @@ package org.dspace.app.xmlui.aspect.administrative.mapper; import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; +import java.util.List; import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer; import org.dspace.app.xmlui.wing.Message; @@ -25,10 +26,15 @@ import org.dspace.content.Collection; import org.dspace.content.DCValue; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; +import org.dspace.core.ConfigurationManager; +import org.dspace.core.PluginConfigurationError; +import org.dspace.core.PluginManager; import org.dspace.handle.HandleManager; import org.dspace.search.DSQuery; import org.dspace.search.QueryArgs; import org.dspace.search.QueryResults; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.xml.sax.SAXException; /** @@ -52,8 +58,10 @@ public class SearchItemForm extends AbstractDSpaceTransformer { private static final Message T_column2 = message("xmlui.administrative.mapper.SearchItemForm.column2"); private static final Message T_column3 = message("xmlui.administrative.mapper.SearchItemForm.column3"); private static final Message T_column4 = message("xmlui.administrative.mapper.SearchItemForm.column4"); - - + + private static final Logger log = LoggerFactory.getLogger(SearchItemForm.class); + + @Override public void addPageMeta(PageMeta pageMeta) throws WingException { pageMeta.addMetadata("title").addContent(T_title); @@ -64,6 +72,7 @@ public class SearchItemForm extends AbstractDSpaceTransformer { } + @Override public void addBody(Body body) throws SAXException, WingException, SQLException, IOException { // Get our parameters and state; @@ -163,41 +172,48 @@ public class SearchItemForm extends AbstractDSpaceTransformer { /** * Search the repository for items in other collections that can be mapped into this one. * - * @param collection The collection to mapp into + * @param collection The collection to map into * @param query The search query. */ private java.util.List<Item> performSearch(Collection collection, String query) throws SQLException, IOException { - - // Search the repository - QueryArgs queryArgs = new QueryArgs(); - queryArgs.setQuery(query); - queryArgs.setPageSize(Integer.MAX_VALUE); - QueryResults results = DSQuery.doQuery(context, queryArgs); - + // Which search provider do we use? + SearchRequestProcessor processor = null; + try { + processor = (SearchRequestProcessor) PluginManager + .getSinglePlugin(SearchRequestProcessor.class); + } catch (PluginConfigurationError e) { + log.warn("{} not properly configured. Please configure the {} plugin. {}", + new Object[] { + SearchItemForm.class.getName(), + SearchRequestProcessor.class.getName(), + e.getMessage() + }); + } + if (processor == null) + { // Discovery is the default search provider since DSpace 4.0 + processor = new DiscoverySearchRequestProcessor(); + } + + // Search the repository + List<DSpaceObject> results = processor.doItemMapSearch(context, query, collection); // Get a list of found items ArrayList<Item> items = new ArrayList<Item>(); - @SuppressWarnings("unchecked") - java.util.List<String> handles = results.getHitHandles(); - for (String handle : handles) + for (DSpaceObject resultDSO : results) { - DSpaceObject resultDSO = HandleManager.resolveToObject(context, handle); - if (resultDSO instanceof Item) { Item item = (Item) resultDSO; - + if (!item.isOwningCollection(collection)) { items.add(item); } } } - + return items; } - - - + } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AbstractSearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AbstractSearch.java index a8ab305b7b336d6392c195fced5ddfd723f39d45..0eacb814e188a97287e18c20f6675f068e3182e6 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AbstractSearch.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AbstractSearch.java @@ -57,7 +57,15 @@ import org.xml.sax.SAXException; * See the two implementations: SimpleSearch and AdvancedSearch. * * @author Scott Phillips + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public abstract class AbstractSearch extends AbstractDSpaceTransformer { private static final Logger log = Logger.getLogger(AbstractSearch.class); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearch.java index b019edaaae5f6b392890b25d3279468698e8193f..b56e4db3478301f5e580ae19710aa6fdbbb5d16f 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearch.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearch.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Map; + import org.apache.cocoon.caching.CacheableProcessingComponent; import org.apache.cocoon.environment.ObjectModelHelper; import org.apache.cocoon.environment.Request; @@ -49,7 +50,15 @@ import org.xml.sax.SAXException; * place. Possibly the sitemap configuration. * * @author Scott Phillips + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class AdvancedSearch extends AbstractSearch implements CacheableProcessingComponent { /** Language string used: */ diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearchLoggerAction.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearchLoggerAction.java index 4ee6e5a69715f52f84304fe950f4af3880e90164..445534bbfca83dde86627c9ff9a4ba08ded02800 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearchLoggerAction.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearchLoggerAction.java @@ -23,7 +23,15 @@ import java.util.List; * @author Kevin Van de Velde (kevin at atmire dot com) * @author Ben Bosman (ben at atmire dot com) * @author Mark Diggory (markd at atmire dot com) + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class AdvancedSearchLoggerAction extends SearchLoggerAction { private static final Logger log = Logger.getLogger(SearchLoggerAction.class); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearchUtils.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearchUtils.java index 1c85200d6f9463ab9347265de32848c25eb8414e..18639e69d95383726b8afa3b8911445261841690 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearchUtils.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/AdvancedSearchUtils.java @@ -22,7 +22,15 @@ import java.util.ArrayList; * @author Kevin Van de Velde (kevin at atmire dot com) * @author Ben Bosman (ben at atmire dot com) * @author Mark Diggory (markd at atmire dot com) + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class AdvancedSearchUtils { private static final int FIELD_MAX_COUNT = 12; diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionRecentSubmissions.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionRecentSubmissions.java index 4389ace1ff71ae60bce183be416d59a29160f2ac..2c0bea1d1b8b7886f35f616747dc2945cf5dbede 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionRecentSubmissions.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionRecentSubmissions.java @@ -87,7 +87,7 @@ public class CollectionRecentSubmissions extends AbstractDSpaceTransformer imple * * The validity object will include the collection being viewed and * all recently submitted items. This does not include the community / collection - * hierarch, when this changes they will not be reflected in the cache. + * hierarchy, when this changes they will not be reflected in the cache. */ public SourceValidity getValidity() { diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionSearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionSearch.java index 10c552b0dd051e1bafecbb7669c5730dbc645f23..03afa3cdbc257fcb144608535e8eab1f289297c7 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionSearch.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionSearch.java @@ -29,7 +29,15 @@ import java.sql.SQLException; * @author Kevin Van de Velde (kevin at atmire dot com) * @author Mark Diggory (markd at atmire dot com) * @author Ben Bosman (ben at atmire dot com) + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class CollectionSearch extends AbstractDSpaceTransformer { private static final Message T_full_text_search = diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionViewer.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionViewer.java index 705486c4952b652abc470e18ee4306dfda3f80ae..57954909a3aa8739c749c7fb0583fd54db66976f 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionViewer.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CollectionViewer.java @@ -10,8 +10,6 @@ package org.dspace.app.xmlui.aspect.artifactbrowser; import java.io.IOException; import java.io.Serializable; import java.sql.SQLException; -import java.util.Map; -import java.util.HashMap; import org.apache.cocoon.caching.CacheableProcessingComponent; import org.apache.cocoon.util.HashUtil; @@ -25,11 +23,8 @@ import org.dspace.app.xmlui.wing.WingException; import org.dspace.app.xmlui.wing.element.Body; import org.dspace.app.xmlui.wing.element.Division; import org.dspace.app.xmlui.wing.element.ReferenceSet; -import org.dspace.app.xmlui.wing.element.List; import org.dspace.app.xmlui.wing.element.PageMeta; import org.dspace.authorize.AuthorizeException; -import org.dspace.browse.BrowseException; -import org.dspace.browse.BrowseIndex; import org.dspace.content.Collection; import org.dspace.content.DSpaceObject; import org.dspace.core.ConfigurationManager; @@ -55,19 +50,6 @@ public class CollectionViewer extends AbstractDSpaceTransformer implements Cache public static final Message T_untitled = message("xmlui.general.untitled"); - private static final Message T_head_browse = - message("xmlui.ArtifactBrowser.CollectionViewer.head_browse"); - - private static final Message T_browse_titles = - message("xmlui.ArtifactBrowser.CollectionViewer.browse_titles"); - - private static final Message T_browse_authors = - message("xmlui.ArtifactBrowser.CollectionViewer.browse_authors"); - - private static final Message T_browse_dates = - message("xmlui.ArtifactBrowser.CollectionViewer.browse_dates"); - - /** Cached validity object */ private SourceValidity validity; @@ -101,7 +83,7 @@ public class CollectionViewer extends AbstractDSpaceTransformer implements Cache * * The validity object will include the collection being viewed and * all recently submitted items. This does not include the community / collection - * hierarch, when this changes they will not be reflected in the cache. + * hierarchy, when this changes they will not be reflected in the cache. */ public SourceValidity getValidity() { @@ -218,41 +200,10 @@ public class CollectionViewer extends AbstractDSpaceTransformer implements Cache home.setHead(name); } - // The search / browse box. + // The search / browse box placeholder, this division will be populated either in the browse or discovery aspect { -// TODO: move browse stuff out of here - Division search = home.addDivision("collection-search-browse", + home.addDivision("collection-search-browse", "secondary search-browse"); - - // Browse by list - Division browseDiv = search.addDivision("collection-browse","secondary browse"); - List browse = browseDiv.addList("collection-browse", List.TYPE_SIMPLE, - "collection-browse"); - browse.setHead(T_head_browse); - String url = contextPath + "/handle/" + collection.getHandle(); - - try - { - // Get a Map of all the browse tables - BrowseIndex[] bis = BrowseIndex.getBrowseIndices(); - for (BrowseIndex bix : bis) - { - // Create a Map of the query parameters for this link - Map<String, String> queryParams = new HashMap<String, String>(); - - queryParams.put("type", bix.getName()); - - // Add a link to this browse - browse.addItemXref(super.generateURL(url + "/browse", queryParams), - message("xmlui.ArtifactBrowser.Navigation.browse_" + bix.getName())); - } - } - catch (BrowseException bex) - { - browse.addItemXref(url + "/browse?type=title",T_browse_titles); - browse.addItemXref(url + "/browse?type=author",T_browse_authors); - browse.addItemXref(url + "/browse?type=dateissued",T_browse_dates); - } } // Add the reference diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityBrowser.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityBrowser.java index a942a146035e14963403f358aaf7f1c831aa00cb..34a347cb1f8f6ef3819f50b0e653c6a66fbf68bf 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityBrowser.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityBrowser.java @@ -47,7 +47,7 @@ import org.xml.sax.SAXException; /** * Display a list of Communities and collections. * - * This item may be configured so that it will only display to a specific depth, + * This item may be configured so that it will only display up to a specific depth, * and may include or exclude collections from the tree. * * The configuration option available: <depth exclude-collections="true">999</depth> @@ -106,7 +106,7 @@ public class CommunityBrowser extends AbstractDSpaceTransformer implements Cache /** * Generate the unique caching key. - * This key must be unique inside the space of this component. + * This key must be unique within the space of this component. */ public Serializable getKey() { @@ -118,7 +118,7 @@ public class CommunityBrowser extends AbstractDSpaceTransformer implements Cache * Generate the cache validity object. * * The validity object will include a list of all communities - * & collection being browsed along with there logo bitstreams. + * and collections being browsed along with their logo bitstreams. */ public SourceValidity getValidity() { @@ -139,8 +139,8 @@ public class CommunityBrowser extends AbstractDSpaceTransformer implements Cache validity.add(node.getDSO()); // If we are configured to use collection strengths (i.e. item counts) then include that number in the validity. - boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache"); - if (useCache) + boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show"); + if (showCount) { try { //try to determine Collection size (i.e. # of items) @@ -352,7 +352,7 @@ public class CommunityBrowser extends AbstractDSpaceTransformer implements Cache TreeNode newRoot = new TreeNode(); - // Setup for breath-first traversal + // Setup for breadth-first traversal Stack<TreeNode> stack = new Stack<TreeNode>(); for (Community community : communities) @@ -364,7 +364,7 @@ public class CommunityBrowser extends AbstractDSpaceTransformer implements Cache { TreeNode node = stack.pop(); - // Short circuit if we have reached our max depth. + // Short-circuit if we have reached our max depth. if (node.getLevel() >= this.depth) { continue; diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunitySearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunitySearch.java index 989ee259bfca163b8e6fa2e200c5d14f9aecb056..66b2cb1f232b2ee2d69cc5ab7a7370e496153baf 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunitySearch.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunitySearch.java @@ -29,7 +29,15 @@ import java.sql.SQLException; * @author Kevin Van de Velde (kevin at atmire dot com) * @author Mark Diggory (markd at atmire dot com) * @author Ben Bosman (ben at atmire dot com) + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class CommunitySearch extends AbstractDSpaceTransformer { private static final Message T_advanced_search_link= diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityViewer.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityViewer.java index 7284868d0c7262227e66507950f74fa0fb98002b..f0e5fdb0fadd07fb507462a538aa0af3df55a3a6 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityViewer.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/CommunityViewer.java @@ -10,8 +10,6 @@ package org.dspace.app.xmlui.aspect.artifactbrowser; import java.io.IOException; import java.io.Serializable; import java.sql.SQLException; -import java.util.Map; -import java.util.HashMap; import org.apache.cocoon.caching.CacheableProcessingComponent; import org.apache.cocoon.util.HashUtil; @@ -25,12 +23,9 @@ import org.dspace.app.xmlui.wing.WingException; import org.dspace.app.xmlui.wing.element.Body; import org.dspace.app.xmlui.wing.element.Division; import org.dspace.app.xmlui.wing.element.ReferenceSet; -import org.dspace.app.xmlui.wing.element.List; import org.dspace.app.xmlui.wing.element.Reference; import org.dspace.app.xmlui.wing.element.PageMeta; import org.dspace.authorize.AuthorizeException; -import org.dspace.browse.BrowseException; -import org.dspace.browse.BrowseIndex; import org.dspace.browse.ItemCountException; import org.dspace.browse.ItemCounter; import org.dspace.content.Collection; @@ -59,20 +54,7 @@ public class CommunityViewer extends AbstractDSpaceTransformer implements Cachea public static final Message T_untitled = message("xmlui.general.untitled"); - private static final Message T_head_browse = - message("xmlui.ArtifactBrowser.CommunityViewer.head_browse"); - - private static final Message T_browse_titles = - message("xmlui.ArtifactBrowser.CommunityViewer.browse_titles"); - - private static final Message T_browse_authors = - message("xmlui.ArtifactBrowser.CommunityViewer.browse_authors"); - - private static final Message T_browse_dates = - message("xmlui.ArtifactBrowser.CommunityViewer.browse_dates"); - - - private static final Message T_head_sub_communities = + private static final Message T_head_sub_communities = message("xmlui.ArtifactBrowser.CommunityViewer.head_sub_communities"); private static final Message T_head_sub_collections = @@ -141,9 +123,9 @@ public class CommunityViewer extends AbstractDSpaceTransformer implements Cachea { validity.add(subCommunity); - // Include the item count in the validity, only if the value is cached. - boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache"); - if (useCache) + // Include the item count in the validity, only if the value is shown. + boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show"); + if (showCount) { try { int size = new ItemCounter(context).getCount(subCommunity); @@ -156,9 +138,9 @@ public class CommunityViewer extends AbstractDSpaceTransformer implements Cachea { validity.add(collection); - // Include the item count in the validity, only if the value is cached. - boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache"); - if (useCache) + // Include the item count in the validity, only if the value is shown. + boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show"); + if (showCount) { try { int size = new ItemCounter(context).getCount(collection); @@ -261,42 +243,10 @@ public class CommunityViewer extends AbstractDSpaceTransformer implements Cachea home.setHead(name); } - // The search / browse box. + // The search / browse box placeholder, this division will be populated either in the browse or discovery aspect { - Division search = home.addDivision("community-search-browse", + home.addDivision("community-search-browse", "secondary search-browse"); - - -// TODO: move browse stuff out of here - // Browse by list - Division browseDiv = search.addDivision("community-browse","secondary browse"); - List browse = browseDiv.addList("community-browse", List.TYPE_SIMPLE, - "community-browse"); - browse.setHead(T_head_browse); - String url = contextPath + "/handle/" + community.getHandle(); - - try - { - // Get a Map of all the browse tables - BrowseIndex[] bis = BrowseIndex.getBrowseIndices(); - for (BrowseIndex bix : bis) - { - // Create a Map of the query parameters for this link - Map<String, String> queryParams = new HashMap<String, String>(); - - queryParams.put("type", bix.getName()); - - // Add a link to this browse - browse.addItemXref(super.generateURL(url + "/browse", queryParams), - message("xmlui.ArtifactBrowser.Navigation.browse_" + bix.getName())); - } - } - catch (BrowseException bex) - { - browse.addItemXref(url + "/browse?type=title",T_browse_titles); - browse.addItemXref(url + "/browse?type=author",T_browse_authors); - browse.addItemXref(url + "/browse?type=dateissued",T_browse_dates); - } } // Add main reference: diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/Contact.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/Contact.java index 7ce428e310f4351e4ffd6d027ed9c1b8bddbd7a7..55df4ac2dce8ab911621676c166f6728d98b2692 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/Contact.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/Contact.java @@ -105,7 +105,7 @@ public class Contact extends AbstractDSpaceTransformer implements CacheableProce list.addItem().addXref(contextPath+"/feedback",T_feedback_link); list.addLabel(T_email); - String email = ConfigurationManager.getProperty("mail.admin"); + String email = ConfigurationManager.getProperty("feedback.recipient"); list.addItem().addXref("mailto:"+email,email); } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/FrontPageSearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/FrontPageSearch.java deleted file mode 100644 index e1c1378d2bcf03f8175b8b01487366b6666f1150..0000000000000000000000000000000000000000 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/FrontPageSearch.java +++ /dev/null @@ -1,114 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.xmlui.aspect.artifactbrowser; - -import java.io.IOException; -import java.io.Serializable; -import java.sql.SQLException; - -import org.apache.cocoon.caching.CacheableProcessingComponent; -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.WingException; -import org.dspace.app.xmlui.wing.element.Body; -import org.dspace.app.xmlui.wing.element.Division; -import org.dspace.app.xmlui.wing.element.PageMeta; -import org.dspace.app.xmlui.wing.element.Para; -import org.dspace.authorize.AuthorizeException; -import org.dspace.core.ConfigurationManager; -import org.xml.sax.SAXException; - -/** - * This simple component will add a Search Box. It is intended for use on the front page. - * - * @author Scott Phillips - */ -public class FrontPageSearch extends AbstractDSpaceTransformer implements CacheableProcessingComponent -{ - /** Language Strings */ - - public static final Message T_dspace_home = - message("xmlui.general.dspace_home"); - - private static final Message T_head = - message("xmlui.ArtifactBrowser.FrontPageSearch.head"); - - private static final Message T_para1 = - message("xmlui.ArtifactBrowser.FrontPageSearch.para1"); - - private static final Message T_go = - message("xmlui.general.go"); - - - /** - * Generate the unique caching key. - * This key must be unique inside the space of this component. - */ - public Serializable getKey() - { - return "1"; - } - - /** - * Generate the cache validity object. - */ - public SourceValidity getValidity() - { - return NOPValidity.SHARED_INSTANCE; - } - - /** - * Add a page title and trail links. - */ - public void addPageMeta(PageMeta pageMeta) throws SAXException, - WingException, UIException, SQLException, IOException, - AuthorizeException - { - pageMeta.addMetadata("title").addContent(T_dspace_home); - pageMeta.addTrailLink(contextPath, T_dspace_home); - - // Add RSS links if available - String formats = ConfigurationManager.getProperty("webui.feed.formats"); - if ( formats != null ) - { - for (String format : formats.split(",")) - { - // Remove the protocol number, i.e. just list 'rss' or' atom' - String[] parts = format.split("_"); - if (parts.length < 1) - { - continue; - } - - String feedFormat = parts[0].trim()+"+xml"; - - String feedURL = contextPath+"/feed/"+format.trim()+"/site"; - pageMeta.addMetadata("feed", feedFormat).addContent(feedURL); - } - } - } - - - public void addBody(Body body) throws SAXException, WingException, - UIException, SQLException, IOException, AuthorizeException - { - Division search = - body.addInteractiveDivision("front-page-search",contextPath+"/search",Division.METHOD_GET,"primary"); - - search.setHead(T_head); - - search.addPara(T_para1); - - Para fields = search.addPara(); - fields.addText("query"); - fields.addButton("submit").setValue(T_go); - } -} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/Navigation.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/Navigation.java index 4ed8cdf92aa3e3af34b61282fe5be3dd3efe0e0d..807263c231c1925b519d445144f3bd5e739b0ed5 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/Navigation.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/Navigation.java @@ -11,7 +11,6 @@ import java.io.IOException; import java.io.Serializable; import java.sql.SQLException; import java.util.HashMap; -import java.util.Locale; import java.util.Map; import org.apache.cocoon.caching.CacheableProcessingComponent; @@ -37,7 +36,6 @@ import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.app.util.Util; import org.dspace.core.ConfigurationManager; -import org.dspace.core.I18nUtil; import org.xml.sax.SAXException; /** @@ -208,31 +206,27 @@ public class Navigation extends AbstractDSpaceTransformer implements CacheablePr pageMeta.addMetadata("page","contactURL").addContent(contextPath + "/contact"); pageMeta.addMetadata("page","feedbackURL").addContent(contextPath + "/feedback"); -// ############################################################################################# - // Add the locale meta data including language dependant labels - Locale[] locales = I18nUtil.getSupportedLocales(); - for (int i=0; i < locales.length; i++) - { - pageMeta.addMetadata("page", "supportedLocale").addContent(locales[i].toString()); - // now add the appropriate labels - pageMeta.addMetadata("supportedLocale", locales[i].toString()).addContent(locales[i].getDisplayName(locales[i])); - } - pageMeta.addMetadata("page","currentLocale").addContent(context.getCurrentLocale().toString()); -// ############################################################################################# - - DSpaceObject dso = HandleUtil.obtainHandle(objectModel); if (dso != null) { if (dso instanceof Item) { + pageMeta.addMetadata("focus","containerType").addContent("type:item"); pageMeta.addMetadata("focus","object").addContent("hdl:"+dso.getHandle()); this.getObjectManager().manageObject(dso); dso = ((Item) dso).getOwningCollection(); } - if (dso instanceof Collection || dso instanceof Community) + if (dso instanceof Collection) + { + pageMeta.addMetadata("focus","containerType").addContent("type:collection"); + pageMeta.addMetadata("focus","container").addContent("hdl:"+dso.getHandle()); + this.getObjectManager().manageObject(dso); + } + + if (dso instanceof Community) { + pageMeta.addMetadata("focus","containerType").addContent("type:community"); pageMeta.addMetadata("focus","container").addContent("hdl:"+dso.getHandle()); this.getObjectManager().manageObject(dso); } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SendFeedbackAction.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SendFeedbackAction.java index 02ca38d3eb40f9141dcb45339ed3df8b342bbb97..dbf37e7be3f95633eefdd790eda55a61acc52f4d 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SendFeedbackAction.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SendFeedbackAction.java @@ -128,7 +128,7 @@ public class SendFeedbackAction extends AbstractAction } // All data is there, send the email - Email email = ConfigurationManager.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "feedback")); + Email email = Email.getEmail(I18nUtil.getEmailFilename(context.getCurrentLocale(), "feedback")); email.addRecipient(ConfigurationManager .getProperty("feedback.recipient")); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SimpleSearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SimpleSearch.java index 23c36f0fc615effdbc4ba4631313978df3cd1994..5fe2e47788bfc6086b5c1a35a06dfa1325fe43d5 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SimpleSearch.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SimpleSearch.java @@ -35,7 +35,15 @@ import org.xml.sax.SAXException; * field query (the url parameter is named query) and the results are processed. * * @author Scott Phillips + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class SimpleSearch extends AbstractSearch implements CacheableProcessingComponent { /** Language Strings */ diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SimpleSearchLoggerAction.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SimpleSearchLoggerAction.java index 41df8598b03827f53842d88f3aa3f8773ba99cf1..66e9e762f68a45ad5a6fbe13b85f9eb439020d54 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SimpleSearchLoggerAction.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/artifactbrowser/SimpleSearchLoggerAction.java @@ -21,7 +21,15 @@ import java.util.List; * @author Kevin Van de Velde (kevin at atmire dot com) * @author Ben Bosman (ben at atmire dot com) * @author Mark Diggory (markd at atmire dot com) + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class SimpleSearchLoggerAction extends SearchLoggerAction{ @Override diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/browseArtifacts/StaticPage.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/browseArtifacts/StaticPage.java index 45d2f4402d206a64dd45255d255122add5cdc429..45cb0ed00de4d82b65c875cf5021bba0ea0c6964 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/browseArtifacts/StaticPage.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/browseArtifacts/StaticPage.java @@ -21,11 +21,11 @@ import java.io.IOException; import java.sql.SQLException; /** - * Created by IntelliJ IDEA. - * User: peterdietz - * Date: 07/12/11 - * Time: 11:39 PM - * To change this template use File | Settings | File Templates. + * Implements a Cocoon transformer for easily defining a static XMLUI page without the need to write any Java code + * + * For info on usage, see https://wiki.duraspace.org/display/DSPACE/Manakin+theme+tutorial + * + * @author Peter Dietz (pdietz84@gmail.com) */ public class StaticPage extends AbstractDSpaceTransformer { @Override diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractRecentSubmissionTransformer.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractRecentSubmissionTransformer.java index e9933a5f7ef9e60874d2a2205e69d404e768f0a4..9d605373cd023907751fdd01a71cf7b1a023c443 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractRecentSubmissionTransformer.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractRecentSubmissionTransformer.java @@ -14,6 +14,9 @@ import org.apache.log4j.Logger; import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer; import org.dspace.app.xmlui.utils.DSpaceValidity; import org.dspace.app.xmlui.utils.HandleUtil; +import org.dspace.app.xmlui.wing.Message; +import org.dspace.app.xmlui.wing.WingException; +import org.dspace.app.xmlui.wing.element.Division; import org.dspace.content.DSpaceObject; import org.dspace.core.Constants; import org.dspace.discovery.*; @@ -31,6 +34,7 @@ import java.util.List; */ public abstract class AbstractRecentSubmissionTransformer extends AbstractDSpaceTransformer implements CacheableProcessingComponent { + private static final Message view_more = message("xmlui.ArtifactBrowser.AbstractRecentSubmissionTransformer.recent_submissions_more"); private static final Logger log = Logger.getLogger(AbstractRecentSubmissionTransformer.class); /** @@ -147,6 +151,22 @@ public abstract class AbstractRecentSubmissionTransformer extends AbstractDSpace } } + /** + * Add a view more link at the bottom of a recent submission view + * @param recentSubmissionDiv recent submission div to which we are to add the link + * @param dso the site/community/collection on who's home page we are + * @throws WingException ... + */ + protected void addViewMoreLink(Division recentSubmissionDiv, DSpaceObject dso) throws WingException { + String url = contextPath; + if(dso != null) + { + url += "/handle/" + dso.getHandle(); + } + url += "/recent-submissions"; + recentSubmissionDiv.addPara("recent-submission-view-more", "recentSubmissionViewMore").addXref(url).addContent(view_more); + } + @Override public void recycle() { queryResults = null; diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractSearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractSearch.java index 86c66015217e8773e372b0161e3e990265997852..cea3a01f90f8b8ddad641fe402671583563d0144 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractSearch.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/AbstractSearch.java @@ -46,10 +46,10 @@ import java.util.List; /** * This is an abstract search page. It is a collection of search methods that - * are common between diffrent search implementation. An implementer must + * are common between different search implementation. An implementer must * implement at least three methods: addBody(), getQuery(), and generateURL(). * <p/> - * See the implementors SimpleSearch. + * See the SimpleSearch implementation. * * @author Kevin Van de Velde (kevin at atmire dot com) * @author Mark Diggory (markd at atmire dot com) @@ -208,13 +208,17 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement */ protected void buildMainForm(Division searchDiv) throws WingException, SQLException { Request request = ObjectModelHelper.getRequest(objectModel); + DSpaceObject dso = HandleUtil.obtainHandle(objectModel); //We set our action to context path, since the eventual action will depend on which url we click on Division mainForm = searchDiv.addInteractiveDivision("main-form", getBasicUrl(), Division.METHOD_POST, ""); String query = getQuery(); + //Indicate that the form we are submitting lists search results + mainForm.addHidden("search-result").setValue(Boolean.TRUE.toString()); mainForm.addHidden("query").setValue(query); + mainForm.addHidden("current-scope").setValue(dso == null ? "" : dso.getHandle()); Map<String, String[]> fqs = getParameterFilterQueries(); if (fqs != null) { @@ -245,7 +249,6 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement { order.setValue(request.getParameter("order")); }else{ - DSpaceObject dso = HandleUtil.obtainHandle(objectModel); DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(dso); order.setValue(discoveryConfiguration.getSearchSortConfiguration().getDefaultSortOrder().toString()); } @@ -253,8 +256,6 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement { mainForm.addHidden("page").setValue(request.getParameter("page")); } - //Optional redirect url ! - mainForm.addHidden("redirectUrl"); } protected abstract String getBasicUrl() throws SQLException; @@ -329,24 +330,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement Map<String, String> parameters = new HashMap<String, String>(); parameters.put("page", "{pageNum}"); String pageURLMask = generateURL(parameters); - Map<String, String[]> filterQueryParams = getParameterFilterQueries(); - if(filterQueryParams != null) - { - StringBuilder maskBuilder = new StringBuilder(pageURLMask); - for (String filterQueryParam : filterQueryParams.keySet()) - { - String[] filterQueryValues = filterQueryParams.get(filterQueryParam); - if(filterQueryValues != null) - { - for (String filterQueryValue : filterQueryValues) - { - maskBuilder.append("&").append(filterQueryParam).append("=").append(filterQueryValue); - } - } - } - - pageURLMask = maskBuilder.toString(); - } + pageURLMask = addFilterQueriesToUrl(pageURLMask); results.setMaskedPagination(itemsTotal, firstItemIndex, lastItemIndex, currentPage, pagesTotal, pageURLMask); @@ -354,7 +338,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement // Look for any communities or collections in the mix org.dspace.app.xmlui.wing.element.List dspaceObjectsList = null; - // Put in palce top level search result list + // Put it on the top of level search result list dspaceObjectsList = results.addList("search-results-repository", org.dspace.app.xmlui.wing.element.List.TYPE_DSO_LIST, "repository-search-results"); @@ -417,6 +401,28 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement //}// Empty query } + protected String addFilterQueriesToUrl(String pageURLMask) throws UIException { + Map<String, String[]> filterQueryParams = getParameterFilterQueries(); + if(filterQueryParams != null) + { + StringBuilder maskBuilder = new StringBuilder(pageURLMask); + for (String filterQueryParam : filterQueryParams.keySet()) + { + String[] filterQueryValues = filterQueryParams.get(filterQueryParam); + if(filterQueryValues != null) + { + for (String filterQueryValue : filterQueryValues) + { + maskBuilder.append("&").append(filterQueryParam).append("=").append(encodeForURL(filterQueryValue)); + } + } + } + + pageURLMask = maskBuilder.toString(); + } + return pageURLMask; + } + /** * Render the given item, all metadata is added to the given list, which metadata will be rendered where depends on the xsl * @param dspaceObjectsList a list of DSpace objects @@ -461,7 +467,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement } } - //Check our highlighted results, we may need to add non metadata (like our full text) + //Check our highlighted results, we may need to add non-metadata (like our full text) if(highlightedResults != null) { //Also add the full text snippet (if available !) @@ -574,7 +580,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement } /** - * Add the current value to the wing list, + * Add the current value to the wing list * @param highlightedResults the highlighted results * @param metadataKey the metadata key {schema}.{element}.{qualifier} * @param metadataFieldList the wing list we need to add the metadata value to @@ -592,7 +598,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement //Loop over all our highlighted results for (String highlight : highlightedResults.getHighlightResults(metadataKey)) { - //If our non highlighted value matches our original one, ensure that the highlighted one is used + //If our non-highlighted value matches our original one, ensure that the highlighted one is used DiscoverHitHighlightingField highlightConfig = queryArgs.getHitHighlightingField(metadataKey); //We might also have it configured for ALL ! if(highlightConfig == null) @@ -651,7 +657,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement } /** - * Add options to the search scope field. This field determines in what + * Add options to the search scope field. This field determines in which * communities or collections to search for the query. * <p/> * The scope list will depend upon the current search scope. There are three @@ -790,7 +796,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement //queryArgs.a type:Article^2 // TODO: This is a hack to get Publications (Articles) to always be at the top of Groups. - // TODO: I think the can be more transparently done in the solr solrconfig.xml with DISMAX and boosting + // TODO: I think that can be more transparently done in the solr solrconfig.xml with DISMAX and boosting /** sort in groups to get publications to top */ queryArgs.setSortField("dc.type", DiscoverQuery.SORT_ORDER.asc); @@ -817,6 +823,8 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement } } + queryArgs.setSpellCheck(discoveryConfiguration.isSpellCheckEnabled()); + this.queryResults = SearchUtils.getSearchService().search(context, scope, queryArgs); } @@ -840,7 +848,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement /** * Returns all the filter queries for use by solr - * This method returns more expanded filter queries then the getParameterFilterQueries + * This method returns more expanded filter queries then the getParameterFilterQueries * @return an array containing the filter queries */ protected String[] getFilterQueries() { @@ -960,7 +968,7 @@ public abstract class AbstractSearch extends AbstractDSpaceTransformer implement /** - * Add sort by options, the gear will be rendered by a combination fo javascript & css + * Add sort by options, the gear will be rendered by a combination of javascript & css */ String currentSort = getParameterSortBy(); org.dspace.app.xmlui.wing.element.List sortList = searchControlsGear.addList("sort-options", org.dspace.app.xmlui.wing.element.List.TYPE_SIMPLE, "gear-selection"); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/BrowseFacet.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/BrowseFacet.java index 582c9b2ea5ea2519c2d7102ff12a7975f47deef3..77fa2f66f73018193bcbc7c9ea9137352c42bb30 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/BrowseFacet.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/BrowseFacet.java @@ -111,7 +111,7 @@ public class BrowseFacet extends AbstractDSpaceTransformer implements CacheableP * <p/> * The validity object will include the collection being viewed and * all recently submitted items. This does not include the community / collection - * hierarch, when this changes they will not be reflected in the cache. + * hierarchy, when this changes they will not be reflected in the cache. */ public SourceValidity getValidity() { if (this.validity == null) { diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CollectionRecentSubmissions.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CollectionRecentSubmissions.java index c10f82d28bb4328e8e05e1e1bb5b50c093d27eaa..40bba89cb74f2b846350e99267b4cbcfbde58c75 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CollectionRecentSubmissions.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CollectionRecentSubmissions.java @@ -75,6 +75,8 @@ public class CollectionRecentSubmissions extends AbstractRecentSubmissionTransfo lastSubmitted.addReference(resultObj); } } + addViewMoreLink(lastSubmittedDiv, collection); + } } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CollectionSearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CollectionSearch.java index df8c2bd2baa7aeae9d06372c2174fa1c1d8cc647..0f5dcb2e5642c63606f0580e5cc987d5c2aff60b 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CollectionSearch.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CollectionSearch.java @@ -100,7 +100,7 @@ public class CollectionSearch extends AbstractDSpaceTransformer implements Cache * * The validity object will include the collection being viewed and * all recently submitted items. This does not include the community / collection - * hierarch, when this changes they will not be reflected in the cache. + * hierarchy, when this changes they will not be reflected in the cache. */ public SourceValidity getValidity() { diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CommunityRecentSubmissions.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CommunityRecentSubmissions.java index 91d6f6583112bbdbf76b8bf482189526b92fbd96..470f46a6a85f216d147065368e7fd62d6b7b5bd4 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CommunityRecentSubmissions.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/CommunityRecentSubmissions.java @@ -73,6 +73,7 @@ public class CommunityRecentSubmissions extends AbstractRecentSubmissionTransfor lastSubmitted.addReference(resultObject); } } + addViewMoreLink(lastSubmittedDiv, dso); } } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SearchFacetFilter.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SearchFacetFilter.java index 55a7009f5e4514601690a663ee4952abd3949612..1a9914b604caf1a3c3c226960908ba195abab005 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SearchFacetFilter.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SearchFacetFilter.java @@ -125,7 +125,7 @@ public class SearchFacetFilter extends AbstractDSpaceTransformer implements Cach * <p/> * The validity object will include the collection being viewed and * all recently submitted items. This does not include the community / collection - * hierarch, when this changes they will not be reflected in the cache. + * hierarchy, when this changes they will not be reflected in the cache. */ public SourceValidity getValidity() { if (this.validity == null) { diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SidebarFacetsTransformer.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SidebarFacetsTransformer.java index 8af9ff5d1bc00fd3d4ee736c19c1860954df85bc..00573d67afccc0b6bbe25ba47891425778a82ea6 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SidebarFacetsTransformer.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SidebarFacetsTransformer.java @@ -43,7 +43,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; /** - * Renders the side bar filters in discovery + * Renders the sidebar filters in Discovery * * @author Kevin Van de Velde (kevin at atmire dot com) * @author Mark Diggory (markd at atmire dot com) @@ -106,7 +106,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen * <p/> * The validity object will include the collection being viewed and * all recently submitted items. This does not include the community / collection - * hierarch, when this changes they will not be reflected in the cache. + * hierarchy, when this changes they will not be reflected in the cache. */ public SourceValidity getValidity() { if (this.validity == null) { @@ -203,7 +203,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen if (facetValues != null && 0 < facetValues.size()) { if(browse == null){ - //Since we have a value it is save to add the sidebar (doing it this way will ensure that we do not end up with an empty sidebar) + //Since we have a value it is safe to add the sidebar (doing it this way will ensure that we do not end up with an empty sidebar) browse = options.addList("discovery"); browse.setHead(T_FILTER_HEAD); @@ -219,7 +219,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen if (!iter.hasNext()) { - //When we have an hierarchical facet always show the view more they may want to filter the children of the top nodes + //When we have an hierarchical facet always show the "view more" they may want to filter the children of the top nodes if(field.getType().equals(DiscoveryConfigurationParameters.TYPE_HIERARCHICAL)){ addViewMoreUrl(filterValsList, dso, request, field.getIndexFieldName()); } @@ -249,7 +249,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen ); } } - //Show a view more url should there be more values, unless we have a date + //Show a "view more" url should there be more values, unless we have a date if (i == shownFacets - 1 && !field.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)/*&& facetField.getGap() == null*/) { addViewMoreUrl(filterValsList, dso, request, field.getIndexFieldName()); } @@ -292,7 +292,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen } } - //Join all our parameters by using an "&" sign + //Join all our parameters using an "&" sign String parametersString = StringUtils.join(parameters.toArray(new String[parameters.size()]), "&"); if(StringUtils.isNotEmpty(parametersString)){ parametersString += "&"; @@ -336,7 +336,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen if(facet.getType().equals(DiscoveryConfigurationParameters.TYPE_DATE)){ String dateFacet = facet.getIndexFieldName() + ".year"; try{ - //Get a range query so we can create facet queries ranging from out first to our last date + //Get a range query so we can create facet queries ranging from our first to our last date //Attempt to determine our oldest & newest year by checking for previously selected filters int oldestYear = -1; int newestYear = -1; @@ -349,7 +349,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen if(hasPattern){ filterQuery = matcher.group(0); //We have a range - //Resolve our range to a first & endyear + //Resolve our range to a first & last year int tempOldYear = Integer.parseInt(filterQuery.split(" TO ")[0].replace("[", "").trim()); int tempNewYear = Integer.parseInt(filterQuery.split(" TO ")[1].replace("]", "").trim()); @@ -372,7 +372,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen } } } - //Check if we have found a range, if not then retrieve our first & last year by using solr + //Check if we have found a range, if not then retrieve our first & last year using Solr if(oldestYear == -1 && newestYear == -1){ DiscoverQuery yearRangeQuery = new DiscoverQuery(); @@ -410,7 +410,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen } int gap = 1; - //Attempt to retrieve our gap by the algorithm below + //Attempt to retrieve our gap using the algorithm below int yearDifference = newestYear - oldestYear; if(yearDifference != 0){ while (10 < ((double)yearDifference / gap)){ @@ -428,7 +428,7 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen queryArgs.addFacetField(new DiscoverFacetField(facet.getIndexFieldName(), facet.getType(), 10, facet.getSortOrder())); }else{ java.util.List<String> facetQueries = new ArrayList<String>(); - //Create facet queries but limit then to 11 (11 == when we need to show a show more url) + //Create facet queries but limit them to 11 (11 == when we need to show a "show more" url) for(int year = topYear; year > oldestYear && (facetQueries.size() < 11); year-=gap){ //Add a filter to remove the last year only if we aren't the last year int bottomYear = year - gap; @@ -456,11 +456,11 @@ public class SidebarFacetsTransformer extends AbstractDSpaceTransformer implemen } } }catch (Exception e){ - log.error(LogManager.getHeader(context, "Error in discovery while setting up date facet range", "date facet: " + dateFacet), e); + log.error(LogManager.getHeader(context, "Error in Discovery while setting up date facet range", "date facet: " + dateFacet), e); } }else{ int facetLimit = facet.getFacetLimit(); - //Add one to our facet limit to make sure that if we have more then the shown facets that we show our show more url + //Add one to our facet limit to make sure that if we have more then the shown facets that we show our "show more" url facetLimit++; queryArgs.addFacetField(new DiscoverFacetField(facet.getIndexFieldName(), facet.getType(), facetLimit, facet.getSortOrder())); } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SimpleSearch.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SimpleSearch.java index 8e6f6c3a37530e549f1a865cedc0046eceb9a317..ea1dcb6b68d3e9977d52ba1ffeaa695d23e6cc1a 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SimpleSearch.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SimpleSearch.java @@ -39,6 +39,7 @@ import org.xml.sax.SAXException; * @author Kevin Van de Velde (kevin at atmire dot com) * @author Mark Diggory (markd at atmire dot com) * @author Ben Bosman (ben at atmire dot com) + * @author Adán Román Ruiz <aroman@arvo.es> (Bugfix) */ public class SimpleSearch extends AbstractSearch implements CacheableProcessingComponent { /** @@ -77,6 +78,7 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC private static final Message T_filter_notequals = message("xmlui.Discovery.SimpleSearch.filter.notequals"); private static final Message T_filter_authority = message("xmlui.Discovery.SimpleSearch.filter.authority"); private static final Message T_filter_notauthority = message("xmlui.Discovery.SimpleSearch.filter.notauthority"); + private static final Message T_did_you_mean = message("xmlui.Discovery.SimpleSearch.did_you_mean"); private SearchService searchService = null; @@ -145,6 +147,12 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC Text text = searchBoxItem.addText("query"); text.setValue(queryString); searchBoxItem.addButton("submit", "search-icon").setValue(T_go); + if(queryResults != null && StringUtils.isNotBlank(queryResults.getSpellCheckQuery())) + { + Item didYouMeanItem = searchList.addItem("did-you-mean", "didYouMean"); + didYouMeanItem.addContent(T_did_you_mean); + didYouMeanItem.addXref(getSuggestUrl(queryResults.getSpellCheckQuery()), queryResults.getSpellCheckQuery(), "didYouMean"); + } DSpaceObject dso = HandleUtil.obtainHandle(objectModel); DiscoveryConfiguration discoveryConfiguration = SearchUtils.getDiscoveryConfiguration(dso); @@ -155,7 +163,7 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC if(0 < filterFields.size() && filterTypes.size() == 0) { - //Display the add filters url ONLY if we have no filters selected & fitlers can be added + //Display the add filters url ONLY if we have no filters selected & filters can be added searchList.addItem().addXref("display-filters", T_filters_show); } addHiddenFormFields("search", request, fqs, mainSearchDiv); @@ -185,8 +193,8 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC if(StringUtils.isNotBlank(filterValue)) { - Row row = filtersTable.addRow("used-filters-" + i, Row.ROLE_DATA, "search-filter used-filter"); - addFilterRow(filterFields, i, row, filterType, filterOperator, filterValue); + Row row = filtersTable.addRow("used-filters-" + i+1, Row.ROLE_DATA, "search-filter used-filter"); + addFilterRow(filterFields, i+1, row, filterType, filterOperator, filterValue); } } filtersTable.addRow("filler-row", Row.ROLE_DATA, "search-filter filler").addCell(1, 4).addContent(""); @@ -295,7 +303,7 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC protected String generateURL(Map<String, String> parameters) throws UIException { String query = getQuery(); - if (!"".equals(query)) + if (!"".equals(query) && parameters.get("query") == null) { parameters.put("query", encodeForURL(query)); } @@ -382,4 +390,10 @@ public class SimpleSearch extends AbstractSearch implements CacheableProcessingC } } } + + protected String getSuggestUrl(String newQuery) throws UIException { + Map parameters = new HashMap(); + parameters.put("query", newQuery); + return addFilterQueriesToUrl(generateURL(parameters)); + } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SiteRecentSubmissions.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SiteRecentSubmissions.java index 9b19bbc656aacd429d3afc993b47e06acaf544c1..236b96e3f62eb4000baaca3793f43a2e61e90ad2 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SiteRecentSubmissions.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SiteRecentSubmissions.java @@ -63,6 +63,7 @@ public class SiteRecentSubmissions extends AbstractRecentSubmissionTransformer { lastSubmitted.addReference(dso); } } + addViewMoreLink(lastSubmittedDiv, null); } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SiteViewer.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SiteViewer.java index acd2803f9b21b8828433d096b7604111175d3977..c2de72a559753b6f5bcbd7fd671c9574b1871f14 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SiteViewer.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/discovery/SiteViewer.java @@ -18,16 +18,13 @@ 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.WingException; -import org.dspace.app.xmlui.wing.element.Body; -import org.dspace.app.xmlui.wing.element.Division; import org.dspace.app.xmlui.wing.element.PageMeta; -import org.dspace.app.xmlui.wing.element.Para; import org.dspace.authorize.AuthorizeException; import org.dspace.core.ConfigurationManager; import org.xml.sax.SAXException; /** - * Adds a searchbox on the dspace home page + * Adds feed links on the DSpace home page * * @author Kevin Van de Velde (kevin at atmire dot com) * @author Mark Diggory (markd at atmire dot com) @@ -40,16 +37,6 @@ public class SiteViewer extends AbstractDSpaceTransformer implements CacheablePr public static final Message T_dspace_home = message("xmlui.general.dspace_home"); - private static final Message T_head = - message("xmlui.ArtifactBrowser.FrontPageSearch.head"); - - private static final Message T_para1 = - message("xmlui.ArtifactBrowser.FrontPageSearch.para1"); - - private static final Message T_go = - message("xmlui.general.go"); - - /** * Generate the unique caching key. * This key must be unique inside the space of this component. @@ -97,20 +84,4 @@ public class SiteViewer extends AbstractDSpaceTransformer implements CacheablePr } } } - - - public void addBody(Body body) throws SAXException, WingException, - UIException, SQLException, IOException, AuthorizeException - { - Division search = - body.addInteractiveDivision("front-page-search",contextPath+"/discover",Division.METHOD_GET,"primary"); - - search.setHead(T_head); - - search.addPara(T_para1); - - Para fields = search.addPara(); - fields.addText("query"); - fields.addButton("submit").setValue(T_go); - } } \ No newline at end of file diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/eperson/EditProfile.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/eperson/EditProfile.java index e7674ef48c53b9408e07b463d8f09eeefc952821..4caf5b889da3a7cd5c3c2b6d873e705f419f2bc7 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/eperson/EditProfile.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/eperson/EditProfile.java @@ -21,6 +21,7 @@ import org.apache.cocoon.environment.ObjectModelHelper; import org.apache.cocoon.environment.Request; import org.apache.cocoon.environment.SourceResolver; import org.apache.log4j.Logger; +import org.dspace.app.util.CollectionDropDown; import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer; import org.dspace.app.xmlui.wing.Message; import org.dspace.app.xmlui.wing.WingException; @@ -33,6 +34,7 @@ import org.dspace.app.xmlui.wing.element.PageMeta; import org.dspace.app.xmlui.wing.element.Select; import org.dspace.app.xmlui.wing.element.Text; import org.dspace.content.Collection; +import org.dspace.content.Community; import org.dspace.core.ConfigurationManager; import org.dspace.core.I18nUtil; import org.dspace.core.LogManager; @@ -40,6 +42,7 @@ import org.dspace.eperson.Group; import org.dspace.eperson.Subscribe; import org.xml.sax.SAXException; + /** * Display a form that allows the user to edit their profile. * There are two cases in which this can be used: 1) when an @@ -374,12 +377,7 @@ public class EditProfile extends AbstractDSpaceTransformer subscriptions.addOption(-1,T_select_collection); for (Collection possible : possibleList) { - String name = possible.getMetadata("name"); - if (name.length() > 50) - { - name = name.substring(0, 47) + "..."; - } - subscriptions.addOption(possible.getID(), name); + subscriptions.addOption(possible.getID(), CollectionDropDown.collectionPath(possible)); } for (Collection collection: currentList) @@ -474,14 +472,14 @@ public class EditProfile extends AbstractDSpaceTransformer /** * get the available Locales for the User Interface as defined in dspace.cfg - * property xmlui.supported.locales + * property webui.supported.locales * returns an array of Locales or null * * @return an array of supported Locales or null */ private static Locale[] getSupportedLocales() { - String ll = ConfigurationManager.getProperty("xmlui.supported.locales"); + String ll = ConfigurationManager.getProperty("webui.supported.locales"); if (ll != null) { return I18nUtil.parseLocales(ll); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/searchArtifacts/Navigation.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/searchArtifacts/Navigation.java index 0a7820ecd592bcdeebd9d567b0e7946c1881a278..570b09c52cb38b70636f1b058e9e2f9e54032e6d 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/searchArtifacts/Navigation.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/searchArtifacts/Navigation.java @@ -33,7 +33,15 @@ import java.sql.SQLException; * @author Kevin Van de Velde (kevin at atmire dot com) * @author Mark Diggory (markd at atmire dot com) * @author Ben Bosman (ben at atmire dot com) + * + * @deprecated Since DSpace 4 the system use an abstraction layer named + * Discovery to provide access to different search provider. The + * legacy system build upon Apache Lucene is likely to be removed in + * a future version. If you are interested in use Lucene as backend + * for the DSpace search system please consider to build a Lucene + * implementation of the Discovery interfaces */ +@Deprecated public class Navigation extends AbstractDSpaceTransformer implements CacheableProcessingComponent { @Override diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/SearchResultLogAction.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/SearchResultLogAction.java index 3df2a5fa7a4062969b4ee021a5b85b327c7cf173..a2a9a27f9ffd0b83920c3657e06fc3ba683c3837 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/SearchResultLogAction.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/SearchResultLogAction.java @@ -42,11 +42,13 @@ public class SearchResultLogAction extends AbstractAction { public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception { Request request = ObjectModelHelper.getRequest(objectModel); Context context = ContextUtil.obtainContext(objectModel); - DSpaceObject scope = HandleUtil.obtainHandle(objectModel); + DSpaceObject result = HandleUtil.obtainHandle(objectModel); - String redirectUrl = request.getParameter("redirectUrl"); - String resultHandle = StringUtils.substringAfter(redirectUrl, "/handle/"); - DSpaceObject result = HandleManager.resolveToObject(ContextUtil.obtainContext(request), resultHandle); + DSpaceObject scope = null; + if(StringUtils.isNotBlank(request.getParameter("current-scope"))) + { + scope = HandleManager.resolveToObject(context, request.getParameter("current-scope")); + } //Fire an event to log our search result UsageSearchEvent searchEvent = new UsageSearchEvent( @@ -72,9 +74,6 @@ public class SearchResultLogAction extends AbstractAction { new DSpace().getEventService().fireEvent( searchEvent); - HttpServletResponse httpResponse = (HttpServletResponse) objectModel.get(HttpEnvironment.HTTP_RESPONSE_OBJECT); - httpResponse.sendRedirect(redirectUrl); - return new HashMap(); } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/StatisticsAuthorizedMatcher.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/StatisticsAuthorizedMatcher.java index f9cbd9ac685a98965bebefd739b7346883a36d38..5af94c76023cea626ac5ac1ae2582797ca56952e 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/StatisticsAuthorizedMatcher.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/StatisticsAuthorizedMatcher.java @@ -24,9 +24,7 @@ import java.util.HashMap; import java.sql.SQLException; /** - * User: @author kevinvandevelde (kevin at atmire.com) - * Date: 19-nov-2009 - * Time: 17:19:56 + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class StatisticsAuthorizedMatcher extends AbstractLogEnabled implements Matcher{ diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/StatisticsSearchResultTransformer.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/StatisticsSearchResultTransformer.java index da62d01afd3f34fd0e3b2bf2efc6b037ff4f6267..f42d9c93a1c0b9f21b618275eb8738d122157c27 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/StatisticsSearchResultTransformer.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statistics/StatisticsSearchResultTransformer.java @@ -47,10 +47,18 @@ public class StatisticsSearchResultTransformer extends AbstractDSpaceTransformer if(scope != null){ formUrl.append("/handle/").append(scope.getHandle()); } - formUrl.append("/dso-display"); + if(parameters.getParameterAsBoolean("advanced-search", false)) + { + formUrl.append("/advanced-search"); + } else { + formUrl.append("/search"); + } Division mainForm = body.addInteractiveDivision("dso-display", formUrl.toString(), Division.METHOD_POST, ""); + mainForm.addHidden("current-scope").setValue(scope == null ? "" : scope.getHandle()); + //Indicate that the form we are submitting lists search results + mainForm.addHidden("search-result").setValue(Boolean.TRUE.toString()); mainForm.addHidden("query").setValue(getQuery()); if(!StringUtils.isBlank(request.getParameter("rpp"))){ mainForm.addHidden("rpp").setValue(Integer.parseInt(request.getParameter("rpp"))); @@ -64,10 +72,6 @@ public class StatisticsSearchResultTransformer extends AbstractDSpaceTransformer if(!StringUtils.isBlank(request.getParameter("page"))){ mainForm.addHidden("page").setValue(Integer.parseInt(request.getParameter("page"))); } - - - //This hidden input will contain the resulting url to which we redirect once our work has been completed - mainForm.addHidden("redirectUrl"); } private String getQuery() throws UIException { diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statisticsElasticSearch/CSVOutputter.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statisticsElasticSearch/CSVOutputter.java index 6fe1abddb36677953ff8c517a8c32ee33926543b..9a3e6398126e755f29fe1c4925a87d94780f456b 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statisticsElasticSearch/CSVOutputter.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statisticsElasticSearch/CSVOutputter.java @@ -27,8 +27,9 @@ import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.storage.rdbms.TableRow; +import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; -import org.elasticsearch.client.action.search.SearchRequestBuilder; + import org.elasticsearch.search.facet.datehistogram.DateHistogramFacet; import org.elasticsearch.search.facet.terms.TermsFacet; import org.xml.sax.SAXException; @@ -114,7 +115,7 @@ public class CSVOutputter extends AbstractReader implements Recyclable StatisticsTransformer statisticsTransformerInstance = new StatisticsTransformer(fromDate, toDate); if(requestedReport.equalsIgnoreCase("topCountries")) - { + { SearchRequestBuilder requestBuilder = esStatsViewer.facetedQueryBuilder(esStatsViewer.facetTopCountries); SearchResponse searchResponse = requestBuilder.execute().actionGet(); @@ -178,7 +179,7 @@ public class CSVOutputter extends AbstractReader implements Recyclable { if(termType.equalsIgnoreCase("bitstream")) { - Bitstream bitstream = Bitstream.find(context, Integer.parseInt(facetEntry.getTerm())); + Bitstream bitstream = Bitstream.find(context, Integer.parseInt(facetEntry.getTerm().string())); Item item = (Item) bitstream.getParentObject(); String[] entryValues = new String[9]; @@ -194,7 +195,7 @@ public class CSVOutputter extends AbstractReader implements Recyclable entryValues[8] = facetEntry.getCount() + ""; writer.writeNext(entryValues); } else { - writer.writeNext(new String[]{facetEntry.getTerm(), String.valueOf(facetEntry.getCount())}); + writer.writeNext(new String[]{facetEntry.getTerm().string(), String.valueOf(facetEntry.getCount())}); } } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statisticsElasticSearch/ElasticSearchStatsViewer.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statisticsElasticSearch/ElasticSearchStatsViewer.java index 777cbc2e122117fb85bf67846546ea0082dda55c..05304c89a1652789d486b68e357a49c7decce7c3 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statisticsElasticSearch/ElasticSearchStatsViewer.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/statisticsElasticSearch/ElasticSearchStatsViewer.java @@ -20,12 +20,14 @@ import org.dspace.content.Item; import org.dspace.core.Constants; import org.dspace.statistics.DataTermsFacet; import org.dspace.statistics.ElasticSearchLogger; +import org.elasticsearch.action.search.SearchRequestBuilder; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchType; import org.elasticsearch.client.Client; -import org.elasticsearch.client.action.search.SearchRequestBuilder; + import org.elasticsearch.index.query.*; -import org.elasticsearch.search.facet.AbstractFacetBuilder; + +import org.elasticsearch.search.facet.FacetBuilder; import org.elasticsearch.search.facet.FacetBuilders; import org.elasticsearch.search.facet.datehistogram.DateHistogramFacet; import org.elasticsearch.search.facet.terms.TermsFacet; @@ -56,34 +58,34 @@ public class ElasticSearchStatsViewer extends AbstractDSpaceTransformer { protected static TermFilterBuilder justOriginals = FilterBuilders.termFilter("bundleName", "ORIGINAL"); - protected static AbstractFacetBuilder facetTopCountries = FacetBuilders.termsFacet("top_countries").field("country.untouched").size(150) + protected static FacetBuilder facetTopCountries = FacetBuilders.termsFacet("top_countries").field("country.untouched").size(150) .facetFilter(FilterBuilders.andFilter( justOriginals, FilterBuilders.notFilter(FilterBuilders.termFilter("country.untouched", ""))) ); - protected static AbstractFacetBuilder facetMonthlyDownloads = FacetBuilders.dateHistogramFacet("monthly_downloads").field("time").interval("month") + protected static FacetBuilder facetMonthlyDownloads = FacetBuilders.dateHistogramFacet("monthly_downloads").field("time").interval("month") .facetFilter(FilterBuilders.andFilter( FilterBuilders.termFilter("type", "BITSTREAM"), justOriginals )); - protected static AbstractFacetBuilder facetTopBitstreamsAllTime = FacetBuilders.termsFacet("top_bitstreams_alltime").field("id") + protected static FacetBuilder facetTopBitstreamsAllTime = FacetBuilders.termsFacet("top_bitstreams_alltime").field("id") .facetFilter(FilterBuilders.andFilter( FilterBuilders.termFilter("type", "BITSTREAM"), justOriginals )); - protected static AbstractFacetBuilder facetTopUSCities = FacetBuilders.termsFacet("top_US_cities").field("city.untouched").size(50) + protected static FacetBuilder facetTopUSCities = FacetBuilders.termsFacet("top_US_cities").field("city.untouched").size(50) .facetFilter(FilterBuilders.andFilter( FilterBuilders.termFilter("countryCode", "US"), justOriginals, FilterBuilders.notFilter(FilterBuilders.termFilter("city.untouched", "")) )); - protected static AbstractFacetBuilder facetTopUniqueIP = FacetBuilders.termsFacet("top_unique_ips").field("ip"); + protected static FacetBuilder facetTopUniqueIP = FacetBuilders.termsFacet("top_unique_ips").field("ip"); - protected static AbstractFacetBuilder facetTopTypes = FacetBuilders.termsFacet("top_types").field("type"); + protected static FacetBuilder facetTopTypes = FacetBuilders.termsFacet("top_types").field("type"); /** Language strings */ private static final Message T_dspace_home = message("xmlui.general.dspace_home"); @@ -218,7 +220,7 @@ public class ElasticSearchStatsViewer extends AbstractDSpaceTransformer { } public void showAllReports() throws WingException, SQLException{ - List<AbstractFacetBuilder> summaryFacets = new ArrayList<AbstractFacetBuilder>(); + List<FacetBuilder> summaryFacets = new ArrayList<FacetBuilder>(); summaryFacets.add(facetTopTypes); summaryFacets.add(facetTopUniqueIP); summaryFacets.add(facetTopCountries); @@ -239,12 +241,12 @@ public class ElasticSearchStatsViewer extends AbstractDSpaceTransformer { List<? extends TermsFacet.Entry> termsFacetEntries = topBitstreamsFacet.getEntries(); DataTermsFacet termsFacet = new DataTermsFacet(); for(TermsFacet.Entry entry : termsFacetEntries) { - termsFacet.addTermFacet(new DataTermsFacet.TermsFacet(entry.getTerm(), entry.getCount())); + termsFacet.addTermFacet(new DataTermsFacet.TermsFacet(entry.getTerm().string(), entry.getCount())); } division.addHidden("jsonTopDownloads").setValue(termsFacet.toJson()); } - public AbstractFacetBuilder facetTopBitstreamsLastMonth() { + public FacetBuilder facetTopBitstreamsLastMonth() { Calendar calendar = Calendar.getInstance(); // Show Previous Whole Month @@ -275,23 +277,23 @@ public class ElasticSearchStatsViewer extends AbstractDSpaceTransformer { return monthAndYearFormat.format(calendar.getTime()); } - public SearchRequestBuilder facetedQueryBuilder(AbstractFacetBuilder facet) throws WingException{ - List<AbstractFacetBuilder> facetList = new ArrayList<AbstractFacetBuilder>(); + public SearchRequestBuilder facetedQueryBuilder(FacetBuilder facet) throws WingException{ + List<FacetBuilder> facetList = new ArrayList<FacetBuilder>(); facetList.add(facet); return facetedQueryBuilder(facetList); } - public SearchRequestBuilder facetedQueryBuilder(AbstractFacetBuilder... facets) throws WingException { - List<AbstractFacetBuilder> facetList = new ArrayList<AbstractFacetBuilder>(); + public SearchRequestBuilder facetedQueryBuilder(FacetBuilder... facets) throws WingException { + List<FacetBuilder> facetList = new ArrayList<FacetBuilder>(); - for(AbstractFacetBuilder facet : facets) { + for(FacetBuilder facet : facets) { facetList.add(facet); } return facetedQueryBuilder(facetList); } - public SearchRequestBuilder facetedQueryBuilder(List<AbstractFacetBuilder> facetList) { + public SearchRequestBuilder facetedQueryBuilder(List<FacetBuilder> facetList) { TermQueryBuilder termQuery = QueryBuilders.termQuery(getOwningText(dso), dso.getID()); FilterBuilder rangeFilter = FilterBuilders.rangeFilter("time").from(dateStart).to(dateEnd); FilteredQueryBuilder filteredQueryBuilder = QueryBuilders.filteredQuery(termQuery, rangeFilter); @@ -301,7 +303,7 @@ public class ElasticSearchStatsViewer extends AbstractDSpaceTransformer { .setQuery(filteredQueryBuilder) .setSize(0); - for(AbstractFacetBuilder facet : facetList) { + for(FacetBuilder facet : facetList) { searchRequestBuilder.addFacet(facet); } @@ -356,16 +358,16 @@ public class ElasticSearchStatsViewer extends AbstractDSpaceTransformer { Row row = facetTable.addRow(); if(termName.equalsIgnoreCase("bitstream")) { - Bitstream bitstream = Bitstream.find(context, Integer.parseInt(facetEntry.getTerm())); + Bitstream bitstream = Bitstream.find(context, Integer.parseInt(facetEntry.getTerm().string())); Item item = (Item) bitstream.getParentObject(); row.addCell().addXref(contextPath + "/handle/" + item.getHandle(), item.getName()); row.addCellContent(getFirstMetadataValue(item, "dc.creator")); row.addCellContent(getFirstMetadataValue(item, "dc.publisher")); row.addCellContent(getFirstMetadataValue(item, "dc.date.issued")); } else if(termName.equalsIgnoreCase("country")) { - row.addCell("country", Cell.ROLE_DATA,"country").addContent(new Locale("en", facetEntry.getTerm()).getDisplayCountry()); + row.addCell("country", Cell.ROLE_DATA,"country").addContent(new Locale("en", facetEntry.getTerm().string()).getDisplayCountry()); } else { - row.addCell().addContent(facetEntry.getTerm()); + row.addCell().addContent(facetEntry.getTerm().string()); } row.addCell("count", Cell.ROLE_DATA, "count").addContent(facetEntry.getCount()); } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/CollectionViewer.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/CollectionViewer.java index 5bbdab4db7481b56f3d221a86fcc25798f97c9c6..cb5a8a65e9c37b8ff642e48e8351fceadd163f24 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/CollectionViewer.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/CollectionViewer.java @@ -79,7 +79,7 @@ public class CollectionViewer extends AbstractDSpaceTransformer implements Cache * * The validity object will include the collection being viewed and * all recently submitted items. This does not include the community / collection - * hierarch, when this changes they will not be reflected in the cache. + * hierarchy, when this changes they will not be reflected in the cache. */ public SourceValidity getValidity() { diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/AccessStep.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/AccessStep.java index 9282cf557f88bca0b8c443f1d4757bb50aed4ead..c65b6151080ff68f80c08cc9c8912564a4e2265c 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/AccessStep.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/AccessStep.java @@ -20,13 +20,9 @@ import org.dspace.app.xmlui.wing.WingException; import org.dspace.app.xmlui.wing.element.*; import org.dspace.app.xmlui.wing.element.List; import org.dspace.authorize.AuthorizeException; -import org.dspace.authorize.AuthorizeManager; -import org.dspace.authorize.ResourcePolicy; -import org.dspace.content.*; import org.dspace.content.Collection; import org.dspace.content.Item; import org.dspace.core.ConfigurationManager; -import org.dspace.eperson.Group; import org.xml.sax.SAXException; import java.io.IOException; @@ -42,6 +38,10 @@ public class AccessStep extends AbstractSubmissionStep protected static final Message T_submit_add_policy = message("xmlui.Submission.submit.AccessStep.submit_add_policy"); protected static final Message T_private_settings = message("xmlui.Submission.submit.AccessStep.private_settings"); protected static final Message T_private_settings_help = message("xmlui.Submission.submit.AccessStep.private_settings_help"); + protected static final Message T_private_label = message("xmlui.Submission.submit.AccessStep.private_settings_label"); + protected static final Message T_private_item = message("xmlui.Submission.submit.AccessStep.review_private_item"); + protected static final Message T_public_item = message("xmlui.Submission.submit.AccessStep.review_public_item"); + protected static final Message T_policy_head = message("xmlui.Submission.submit.AccessStep.new_policy_head"); public static final int CHECKBOX_PRIVATE_ITEM=1; public static final int RADIO_OPEN_ACCESS_ITEM_VISIBLE=0; @@ -50,7 +50,7 @@ public class AccessStep extends AbstractSubmissionStep private EditPolicyStep editPolicy= null; - /** + /** * Establish our required parameters, abstractStep will enforce these. */ public AccessStep(){ @@ -74,7 +74,8 @@ public class AccessStep extends AbstractSubmissionStep } - public void addPageMeta(PageMeta pageMeta) throws WingException{ + public void addPageMeta(PageMeta pageMeta) throws WingException, SAXException, SQLException, AuthorizeException, IOException { + super.addPageMeta(pageMeta); pageMeta.addMetadata("javascript", "static").addContent("static/js/accessFormUtil.js"); } @@ -99,26 +100,30 @@ public class AccessStep extends AbstractSubmissionStep AccessStepUtil asu = new AccessStepUtil(context); - // list Policies already added - asu.addTablePolicies(div, item); - List form = div.addList("submit-access-settings", List.TYPE_FORM); form.setHead(T_head); addPrivateCheckBox(request, form, item); - asu.addName(request.getParameter("name"), form, errorFlag); + // list Policies already added + asu.addTablePolicies(div, item, collection); + + form = div.addList("submit-add-item-policy", List.TYPE_FORM); + form.setHead(T_policy_head); + asu.addListGroups(request.getParameter("group_id"), form, errorFlag, collection); // radio buttons: Item will be visible / Embargo Access + date asu.addAccessRadios(request.getParameter("open_access_radios"), request.getParameter("embargo_until_date"), form, errorFlag, item); + asu.addName(request.getParameter("name"), form, errorFlag); + // Reason asu.addReason(request.getParameter("reason"), form, errorFlag); // Add Policy Button - boolean isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); + boolean isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); if(isAdvancedFormEnabled){ Button addPolicy = form.addItem().addButton(org.dspace.submit.step.AccessStep.FORM_ACCESS_BUTTON_ADD); addPolicy.setValue(T_submit_add_policy); @@ -133,9 +138,9 @@ public class AccessStep extends AbstractSubmissionStep privateCheckbox.setLabel(T_private_settings); privateCheckbox.setHelp(T_private_settings_help); if(request.getParameter("private_option")!=null || !item.isDiscoverable()) - privateCheckbox.addOption(true, CHECKBOX_PRIVATE_ITEM, ""); + privateCheckbox.addOption(true, CHECKBOX_PRIVATE_ITEM, T_private_label); else - privateCheckbox.addOption(false, CHECKBOX_PRIVATE_ITEM, ""); + privateCheckbox.addOption(false, CHECKBOX_PRIVATE_ITEM, T_private_label); } private Division addMainDivision(Body body, Collection collection) throws WingException { @@ -172,7 +177,17 @@ public class AccessStep extends AbstractSubmissionStep WingException, UIException, SQLException, IOException, AuthorizeException { - // License step doesn't require reviewing - return null; + List accessSection = reviewList.addList("submit-review-" + this.stepAndPage, List.TYPE_FORM); + accessSection.setHead(T_head); + + Item item = submission.getItem(); + + accessSection.addLabel(T_private_settings); + accessSection.addItem(item.isDiscoverable() ? T_public_item : T_private_item); + + AccessStepUtil asu = new AccessStepUtil(context); + asu.addListPolicies(accessSection, item, item.getOwningCollection()); + + return accessSection; } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/AccessStepUtil.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/AccessStepUtil.java index b4b3422504580d83483209a39abc0e0c536af45c..55ba5b77f09be651acf46af995aa4c9772bd0f28 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/AccessStepUtil.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/AccessStepUtil.java @@ -13,6 +13,7 @@ import org.dspace.app.xmlui.wing.Message; import org.dspace.authorize.AuthorizeManager; import org.dspace.authorize.ResourcePolicy; import org.dspace.content.*; +import org.dspace.content.Item; import org.dspace.core.Context; import org.dspace.app.xmlui.wing.WingException; import org.dspace.app.xmlui.wing.element.*; @@ -36,7 +37,9 @@ public class AccessStepUtil extends AbstractDSpaceTransformer { Context context=null; protected static final Message T_name =message("xmlui.Submission.submit.AccessStep.name"); - protected static final Message T_reason = message("xmlui.Submission.submit.AccessStep.reason"); + protected static final Message T_name_help = message("xmlui.Submission.submit.AccessStep.name_help"); + protected static final Message T_reason = message("xmlui.Submission.submit.AccessStep.reason"); + protected static final Message T_reason_help = message("xmlui.Submission.submit.AccessStep.reason_help"); protected static final Message T_radios_embargo = message("xmlui.Submission.submit.AccessStep.embargo_visible"); protected static final Message T_groups = message("xmlui.Submission.submit.AccessStep.list_assigned_groups"); protected static final Message T_item_will_be_visible = message("xmlui.Submission.submit.AccessStep.open_access"); @@ -46,7 +49,9 @@ public class AccessStepUtil extends AbstractDSpaceTransformer { protected static final Message T_error_duplicated_policy = message("xmlui.Submission.submit.AccessStep.error_duplicated_policy"); // Policies Table + protected static final Message T_no_policies = message("xmlui.Submission.submit.AccessStep.no_policies"); protected static final Message T_head_policies_table = message("xmlui.Submission.submit.AccessStep.table_policies"); + protected static final Message T_policies_help = message("xmlui.Submission.submit.AccessStep.policies_help"); protected static final Message T_column0 =message("xmlui.Submission.submit.AccessStep.column0"); protected static final Message T_column1 =message("xmlui.Submission.submit.AccessStep.column1"); protected static final Message T_column2 =message("xmlui.Submission.submit.AccessStep.column2"); @@ -54,6 +59,7 @@ public class AccessStepUtil extends AbstractDSpaceTransformer { protected static final Message T_column4 =message("xmlui.Submission.submit.AccessStep.column4"); protected static final Message T_table_submit_edit =message("xmlui.Submission.submit.AccessStep.table_edit_button"); protected static final Message T_table_submit_delete =message("xmlui.Submission.submit.AccessStep.table_delete_button"); + protected static final Message T_policy = message("xmlui.Submission.submit.AccessStep.review_policy_line"); private static final Message T_label_date_help = message("xmlui.administrative.authorization.AccessStep.label_date_help"); @@ -67,14 +73,16 @@ public class AccessStepUtil extends AbstractDSpaceTransformer { private boolean isAdvancedFormEnabled=false; public AccessStepUtil(Context c){ - isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); + isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); context=c; } public void addName(String name_, List form, int errorFlag) throws WingException { if(isAdvancedFormEnabled){ Text name = form.addItem().addText("name"); + name.setSize(0, 30); name.setLabel(T_name); + name.setHelp(T_name_help); if(name_!=null && errorFlag != org.dspace.submit.step.AccessStep.STATUS_COMPLETE) name.setValue(name_); @@ -84,6 +92,7 @@ public class AccessStepUtil extends AbstractDSpaceTransformer { public void addReason(String reason_, List form, int errorFlag) throws WingException { TextArea reason = form.addItem("reason", null).addTextArea("reason"); reason.setLabel(T_reason); + reason.setHelp(T_reason_help); if(!isAdvancedFormEnabled){ if(globalReason!=null) @@ -106,7 +115,7 @@ public class AccessStepUtil extends AbstractDSpaceTransformer { Group[] loadedGroups = null; // retrieve groups - String name = ConfigurationManager.getProperty("xmlui.submission.restrictstep.groups"); + String name = ConfigurationManager.getProperty("webui.submission.restrictstep.groups"); if(name!=null){ Group uiGroup = Group.findByName(context, name); if(uiGroup!=null) @@ -118,13 +127,13 @@ public class AccessStepUtil extends AbstractDSpaceTransformer { // if no group selected for default set anonymous if(groupID==null || groupID.equals("")) groupID= "0"; + // when we're just loading the main step, also default to anonymous + if (errorFlag == AccessStep.STATUS_COMPLETE) { + groupID = "0"; + } for (Group group : loadedGroups){ - if(Integer.parseInt(groupID) == group.getID() && errorFlag != org.dspace.submit.step.AccessStep.STATUS_COMPLETE){ - groupSelect.addOption(true, group.getID(), group.getName()); - - }else{ - groupSelect.addOption(false, group.getID(), group.getName()); - } + boolean selectGroup = Integer.parseInt(groupID) == group.getID(); + groupSelect.addOption(selectGroup, group.getID(), group.getName()); } if (errorFlag == AccessStep.STATUS_DUPLICATED_POLICY || errorFlag == AccessStep.EDIT_POLICY_STATUS_DUPLICATED_POLICY @@ -212,70 +221,131 @@ public class AccessStepUtil extends AbstractDSpaceTransformer { startDate.setHelp(T_label_date_help); } - public void addTablePolicies(Division div, DSpaceObject dso) throws WingException, SQLException { - if(isAdvancedFormEnabled){ - java.util.List<ResourcePolicy> resourcePolicies = AuthorizeManager.findPoliciesByDSOAndType(context, dso, ResourcePolicy.TYPE_CUSTOM); - - int cols = resourcePolicies.size(); - if(cols==0) cols=1; - Table policies = div.addTable("policies", 6, cols); - policies.setHead(T_head_policies_table); - Row header = policies.addRow(Row.ROLE_HEADER); - - header.addCellContent(T_column0); // name - header.addCellContent(T_column1); // action - header.addCellContent(T_column2); // group - header.addCellContent(T_column3); // start_date - header.addCellContent(T_column4); // end_date + public void addTablePolicies(Division parent, DSpaceObject dso, Collection owningCollection) throws WingException, SQLException { + if (!isAdvancedFormEnabled) { + return; + } + Division div = parent.addDivision("access-existing-policies"); + div.setHead(T_head_policies_table); + div.addPara(T_policies_help.parameterize(owningCollection)); + + java.util.List<ResourcePolicy> resourcePolicies = AuthorizeManager.findPoliciesByDSOAndType(context, dso, ResourcePolicy.TYPE_CUSTOM); + + if (resourcePolicies.isEmpty()) + { + div.addPara(T_no_policies); + return; + } + + int cols = resourcePolicies.size(); + if(cols==0) cols=1; + Table policies = div.addTable("policies", 6, cols); + Row header = policies.addRow(Row.ROLE_HEADER); + + header.addCellContent(T_column0); // name + header.addCellContent(T_column1); // action + header.addCellContent(T_column2); // group + header.addCellContent(T_column3); // start_date + header.addCellContent(T_column4); // end_date + + + for (ResourcePolicy rp : resourcePolicies){ + int id = rp.getID(); + + String name = ""; + if(rp.getRpName()!=null) name=rp.getRpName(); + + String action = rp.getActionText(); + + // if it is the default policy for the Submitter don't show it. + if(dso instanceof org.dspace.content.Item){ + org.dspace.content.Item item = (org.dspace.content.Item)dso; + if(rp.getEPersonID()!=-1 && rp.getEPersonID()!=0){ + if(item.getSubmitter().getID()==rp.getEPersonID()) + continue; + } + } + + String group = ""; + if(rp.getGroup()!=null) + group = rp.getGroup().getName(); + + Row row = policies.addRow(); + + row.addCellContent(name); + row.addCellContent(action); + row.addCellContent(group); + + // start + String startDate = ""; + if(rp.getStartDate() != null){ + startDate = DateFormatUtils.format(rp.getStartDate(), "yyyy-MM-dd"); + } + row.addCellContent(startDate); + + // endDate + String endDate = ""; + if(rp.getEndDate() != null){ + endDate = DateFormatUtils.format(rp.getEndDate(), "yyyy-MM-dd"); + } + row.addCellContent(endDate); + + Button edit = row.addCell().addButton("submit_edit_edit_policies_"+id); + edit.setValue(T_table_submit_edit); + + Button delete = row.addCell().addButton("submit_delete_edit_policies_"+id); + delete.setValue(T_table_submit_delete); + } + } + public void addListPolicies(List parent, DSpaceObject dso, Collection owningCollection) throws WingException, SQLException { + if (!isAdvancedFormEnabled) { + return; + } + parent.addLabel(T_head_policies_table); - for (ResourcePolicy rp : resourcePolicies){ - int id = rp.getID(); + java.util.List<ResourcePolicy> resourcePolicies = AuthorizeManager.findPoliciesByDSOAndType(context, dso, ResourcePolicy.TYPE_CUSTOM); + if (resourcePolicies.isEmpty()) { + parent.addItem(T_no_policies); + return; + } - String name = ""; - if(rp.getRpName()!=null) name=rp.getRpName(); - String action = rp.getActionText(); + for (ResourcePolicy rp : resourcePolicies){ + int id = rp.getID(); - // if it is the default policy for the Submitter don't show it. - if(dso instanceof org.dspace.content.Item){ - org.dspace.content.Item item = (org.dspace.content.Item)dso; - if(rp.getEPersonID()!=-1 && rp.getEPersonID()!=0){ - if(item.getSubmitter().getID()==rp.getEPersonID()) - continue; - } - } + String name = ""; + if(rp.getRpName()!=null) name=rp.getRpName(); - String group = ""; - if(rp.getGroup()!=null) - group = rp.getGroup().getName(); + String action = rp.getActionText(); - Row row = policies.addRow(); + // if it is the default policy for the Submitter don't show it. + if(dso instanceof org.dspace.content.Item){ + org.dspace.content.Item item = (org.dspace.content.Item)dso; + if(rp.getEPersonID()!=-1 && rp.getEPersonID()!=0){ + if(item.getSubmitter().getID()==rp.getEPersonID()) + continue; + } + } - row.addCellContent(name); - row.addCellContent(action); - row.addCellContent(group); + String group = ""; + if(rp.getGroup()!=null) + group = rp.getGroup().getName(); - // start - String startDate = ""; - if(rp.getStartDate() != null){ - startDate = DateFormatUtils.format(rp.getStartDate(), "yyyy-MM-dd"); - } - row.addCellContent(startDate); + // start + String startDate = ""; + if(rp.getStartDate() != null){ + startDate = DateFormatUtils.format(rp.getStartDate(), "yyyy-MM-dd"); + } - // endDate - String endDate = ""; - if(rp.getEndDate() != null){ - endDate = DateFormatUtils.format(rp.getEndDate(), "yyyy-MM-dd"); - } - row.addCellContent(endDate); + // endDate + String endDate = ""; + if(rp.getEndDate() != null){ + endDate = DateFormatUtils.format(rp.getEndDate(), "yyyy-MM-dd"); + } - Button edit = row.addCell().addButton("submit_edit_edit_policies_"+id); - edit.setValue(T_table_submit_edit); + parent.addItem(T_policy.parameterize(name, action, group, startDate, endDate)); + } - Button delete = row.addCell().addButton("submit_delete_edit_policies_"+id); - delete.setValue(T_table_submit_delete); - } - } - } + } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/CCLicenseStep.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/CCLicenseStep.java index 7a04abad325e32e26209a78dec5a3d004e11b42a..52db4f8e2e2ad73f6ac07b5560730263ed180482 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/CCLicenseStep.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/CCLicenseStep.java @@ -75,6 +75,9 @@ public class CCLicenseStep extends AbstractSubmissionStep protected static final Message T_save_changes = message("xmlui.Submission.submit.CCLicenseStep.save_changes"); protected static final Message T_ccws_error = message("xmlui.Submission.submit.CCLicenseStep.ccws_error"); + /** CC specific variables */ + private String ccLocale; + /** * Establish our required parameters, abstractStep will enforce these. @@ -83,6 +86,9 @@ public class CCLicenseStep extends AbstractSubmissionStep { this.requireSubmission = true; this.requireStep = true; + this.ccLocale = ConfigurationManager.getProperty("cc.license.locale"); + /** Default locale to 'en' */ + this.ccLocale = (this.ccLocale != null) ? this.ccLocale : "en"; } @@ -118,7 +124,7 @@ public class CCLicenseStep extends AbstractSubmissionStep Select selectList = list.addItem().addSelect("licenseclass_chooser"); selectList.setLabel(T_license); selectList.setEvtBehavior("submitOnChange"); - Iterator<CCLicense> iterator = cclookup.getLicenses(ConfigurationManager.getProperty("default.locale")).iterator(); + Iterator<CCLicense> iterator = cclookup.getLicenses(ccLocale).iterator(); // build select List - first choice always 'choose a license', last always 'No license' selectList.addOption(T_select_change.getKey(), T_select_change); while (iterator.hasNext()) { @@ -132,12 +138,12 @@ public class CCLicenseStep extends AbstractSubmissionStep selectList.addOption(T_no_license.getKey(), T_no_license); if (selectedLicense != null) { // output the license fields chooser for the license class type - if (cclookup.getLicenseFields(selectedLicense) == null ) { + if (cclookup.getLicenseFields(selectedLicense, ccLocale) == null ) { // do nothing } else { - Iterator outerIterator = cclookup.getLicenseFields(selectedLicense).iterator(); + Iterator outerIterator = cclookup.getLicenseFields(selectedLicense, ccLocale).iterator(); while (outerIterator.hasNext()) { CCLicenseField cclicensefield = (CCLicenseField)outerIterator.next(); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/CompletedStep.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/CompletedStep.java index 8861edad18bdc300dcc769e5054303aef7895f37..472443bc78a8a0c3c1dd217dd3af0e3659b9bc72 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/CompletedStep.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/CompletedStep.java @@ -21,7 +21,7 @@ import org.dspace.authorize.AuthorizeException; import org.xml.sax.SAXException; /** - * This is a conformation page informing the user that they have + * This is a confirmation page informing the user that they have * completed the submission of the item. It tells them what to * expect next, i.e. the workflow, and gives the option to go home * or start another submission. diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditBitstreamPolicies.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditBitstreamPolicies.java index 7606697d9401ab920c5ccbe398c5ab6100706f8d..14cd003ac6a3ebc17915241f69f981e28e44768d 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditBitstreamPolicies.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditBitstreamPolicies.java @@ -68,23 +68,23 @@ public class EditBitstreamPolicies extends AbstractStep AccessStepUtil asu = new AccessStepUtil(context); // list Policies already added - asu.addTablePolicies(div, submissionInfo.getBitstream()); + asu.addTablePolicies(div, submissionInfo.getBitstream(), collection); List form = div.addList("submit-edit-policy", List.TYPE_FORM); form.setHead(T_head); - asu.addName(request.getParameter("name"), form, errorFlag); - asu.addListGroups(request.getParameter("group_id"), form, errorFlag, collection); // radio buttons: Item will be visible / Embargo Access + date asu.addAccessRadios(request.getParameter("open_access_radios"), request.getParameter("embargo_until_date"), form, errorFlag, submissionInfo.getBitstream()); + asu.addName(request.getParameter("name"), form, errorFlag); + // Reason asu.addReason(request.getParameter("reason"), form, errorFlag); // Add Policy Button - boolean isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); + boolean isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); if(isAdvancedFormEnabled){ Button addPolicy = form.addItem().addButton(org.dspace.submit.step.AccessStep.FORM_ACCESS_BUTTON_ADD); addPolicy.setValue(T_submit_add_policy); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditFileStep.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditFileStep.java index 4378c28a026ae0717e6516b6134e9bf2ce45b035..5c1d5f894428c453195eb6a1248f399ff820193a 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditFileStep.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditFileStep.java @@ -136,7 +136,7 @@ public class EditFileStep extends AbstractStep description.setValue(bitstream.getDescription()); // if AdvancedAccessPolicy=false: add simmpleFormEmbargo in UploadStep - boolean isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); + boolean isAdvancedFormEnabled= ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); if(!isAdvancedFormEnabled){ AccessStepUtil asu = new AccessStepUtil(context); // this step is possible only in case of AdvancedForm diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditPolicyStep.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditPolicyStep.java index cdaed7ae3fc33340ab9524422de797e4f3bbcb3f..47653a184cfa9a65252b06c1f905bd7c881db109 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditPolicyStep.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/EditPolicyStep.java @@ -25,7 +25,6 @@ import org.xml.sax.SAXException; import java.io.IOException; import java.sql.SQLException; -import java.util.Date; import java.util.Map; @@ -83,8 +82,6 @@ public class EditPolicyStep extends AbstractStep AccessStepUtil asu = new AccessStepUtil(context); - asu.addName(resourcePolicy.getRpName(), edit, errorFlag); - asu.addListGroups(Integer.toString(resourcePolicy.getGroupID()), edit, errorFlag, collection); // radio buttons: Item will be visible / Embargo Access + date @@ -99,6 +96,8 @@ public class EditPolicyStep extends AbstractStep } asu.addAccessRadios(selectedRadio, dateValue, edit, errorFlag, null); + asu.addName(resourcePolicy.getRpName(), edit, errorFlag); + // Reason asu.addReason(resourcePolicy.getRpDescription(), edit, errorFlag); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/LicenseStep.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/LicenseStep.java index 03011b3f258bd8068bc00a3e6a141e51d67d2216..cb914fc5d55867f770e56d2da7624d1aaca8dec1 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/LicenseStep.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/LicenseStep.java @@ -83,7 +83,7 @@ public class LicenseStep extends AbstractSubmissionStep UIException, SQLException, IOException, AuthorizeException { - // Get the full text for the actuial licese + // Get the full text for the actual licese Collection collection = submission.getCollection(); String actionURL = contextPath + "/handle/"+collection.getHandle() + "/submit/" + knot.getId() + ".continue"; String licenseText = LicenseUtils.getLicenseText(context @@ -112,7 +112,7 @@ public class LicenseStep extends AbstractSubmissionStep decision.setLabel(T_decision_label); decision.addOption("accept",T_decision_checkbox); - // If user did not check "I accept" checkbox + // If user did not check the "I accept" checkbox if(this.errorFlag==org.dspace.submit.step.LicenseStep.STATUS_LICENSE_REJECTED) { log.info(LogManager.getHeader(context, "reject_license", submissionInfo.getSubmissionLogInfo())); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/SelectCollectionStep.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/SelectCollectionStep.java index 720943d6bfe70f7024a5ada9c9c03eaff342f8a9..ec178f775492cb44d4dd8773dfa99ade44fcfcb2 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/SelectCollectionStep.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/SelectCollectionStep.java @@ -28,6 +28,8 @@ import org.dspace.core.Constants; import org.dspace.handle.HandleManager; import org.xml.sax.SAXException; +import org.dspace.app.util.CollectionDropDown; + /** * Allow the user to select a collection they wish to submit an item to, * this step is sort-of but not officialy part of the item submission @@ -70,23 +72,23 @@ public class SelectCollectionStep extends AbstractSubmissionStep public void addBody(Body body) throws SAXException, WingException, UIException, SQLException, IOException, AuthorizeException { - Collection[] collections; // List of possible collections. - String actionURL = contextPath + "/submit/" + knot.getId() + ".continue"; - DSpaceObject dso = HandleManager.resolveToObject(context, handle); - - if (dso instanceof Community) - { - collections = Collection.findAuthorized(context, ((Community) dso), Constants.ADD); - } - else - { - collections = Collection.findAuthorized(context, null, Constants.ADD); - } + Collection[] collections; // List of possible collections. + String actionURL = contextPath + "/submit/" + knot.getId() + ".continue"; + DSpaceObject dso = HandleManager.resolveToObject(context, handle); + + if (dso instanceof Community) + { + collections = Collection.findAuthorized(context, ((Community) dso), Constants.ADD); + } + else + { + collections = Collection.findAuthorized(context, null, Constants.ADD); + } - // Basic form with a drop down list of all the collections - // you can submit too. + // Basic form with a drop down list of all the collections + // you can submit too. Division div = body.addInteractiveDivision("select-collection",actionURL,Division.METHOD_POST,"primary submission"); - div.setHead(T_submission_head); + div.setHead(T_submission_head); List list = div.addList("select-collection", List.TYPE_FORM); list.setHead(T_head); @@ -98,8 +100,7 @@ public class SelectCollectionStep extends AbstractSubmissionStep select.addOption("",T_collection_default); for (Collection collection : collections) { - String name = collection.getMetadata("name"); - select.addOption(collection.getHandle(),name); + select.addOption(collection.getHandle(), CollectionDropDown.collectionPath(collection)); } Button submit = list.addItem().addButton("submit"); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadWithEmbargoStep.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadWithEmbargoStep.java index f1f1429e4b9c407cc11bcc9d80617ad81b086369..e87630eb8211116279e34815ed8ae4e7878c0bd8 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadWithEmbargoStep.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/submission/submit/UploadWithEmbargoStep.java @@ -156,7 +156,7 @@ public class UploadWithEmbargoStep extends AbstractSubmissionStep editPolicy=null; } - isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("xmlui.submission.restrictstep.enableAdvancedForm", false); + isAdvancedFormEnabled=ConfigurationManager.getBooleanProperty("webui.submission.restrictstep.enableAdvancedForm", false); } public void addPageMeta(PageMeta pageMeta) throws WingException, AuthorizeException, IOException, SAXException, SQLException { diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/viewArtifacts/Navigation.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/viewArtifacts/Navigation.java index ff4ba4eb61ee54c91397ecacc1611f1e5e9a8577..df142ef7913ab8858988487e13434c7853e67c03 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/viewArtifacts/Navigation.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/viewArtifacts/Navigation.java @@ -26,10 +26,12 @@ import org.dspace.content.Community; import org.dspace.content.DSpaceObject; import org.dspace.content.Item; import org.dspace.core.ConfigurationManager; +import org.dspace.core.I18nUtil; import org.xml.sax.SAXException; import java.io.IOException; import java.io.Serializable; +import java.util.Locale; import java.sql.SQLException; /** @@ -128,18 +130,38 @@ public class Navigation extends AbstractDSpaceTransformer implements CacheablePr pageMeta.addMetadata("page","contactURL").addContent(contextPath + "/contact"); pageMeta.addMetadata("page","feedbackURL").addContent(contextPath + "/feedback"); + // Add the locale metadata including language-dependent labels + Locale[] locales = I18nUtil.getSupportedLocales(); + for (int i=0; i < locales.length; i++) + { + pageMeta.addMetadata("page", "supportedLocale").addContent(locales[i].toString()); + // now add the appropriate labels + pageMeta.addMetadata("supportedLocale", locales[i].toString()).addContent(locales[i].getDisplayName(locales[i])); + } + + pageMeta.addMetadata("page","currentLocale").addContent(context.getCurrentLocale().toString()); + DSpaceObject dso = HandleUtil.obtainHandle(objectModel); if (dso != null) { if (dso instanceof Item) { + pageMeta.addMetadata("focus","containerType").addContent("type:item"); pageMeta.addMetadata("focus","object").addContent("hdl:"+dso.getHandle()); this.getObjectManager().manageObject(dso); dso = ((Item) dso).getOwningCollection(); } - - if (dso instanceof Collection || dso instanceof Community) + + if (dso instanceof Collection) + { + pageMeta.addMetadata("focus","containerType").addContent("type:collection"); + pageMeta.addMetadata("focus","container").addContent("hdl:"+dso.getHandle()); + this.getObjectManager().manageObject(dso); + } + + if (dso instanceof Community) { + pageMeta.addMetadata("focus","containerType").addContent("type:community"); pageMeta.addMetadata("focus","container").addContent("hdl:"+dso.getHandle()); this.getObjectManager().manageObject(dso); } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/xmlworkflow/ClaimTasksAction.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/xmlworkflow/ClaimTasksAction.java index d2336c84e4b3cb93ed0f39945e4318afa2d04234..aa6d4a37e655da98605534c9c17c27bc80d4c31b 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/xmlworkflow/ClaimTasksAction.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/aspect/xmlworkflow/ClaimTasksAction.java @@ -26,9 +26,7 @@ import org.dspace.xmlworkflow.storedcomponents.XmlWorkflowItem; import java.util.Map; /** - * User: kevin (kevin at atmire.com) - * Date: 7-sep-2011 - * Time: 14:23:34 + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class ClaimTasksAction extends AbstractAction { @Override diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/BitstreamReader.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/BitstreamReader.java index 54921acb1ff412a01c0c613722201dcb1fb27268..7a84db6dbb80d59026f82cecd79b60865b56ffb5 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/BitstreamReader.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/BitstreamReader.java @@ -29,6 +29,7 @@ import org.apache.cocoon.environment.http.HttpEnvironment; import org.apache.cocoon.environment.http.HttpResponse; import org.apache.cocoon.reading.AbstractReader; import org.apache.cocoon.util.ByteRange; +import org.apache.commons.lang.StringUtils; import org.dspace.app.xmlui.utils.AuthenticationUtil; import org.dspace.app.xmlui.utils.ContextUtil; import org.dspace.authorize.AuthorizeException; @@ -93,7 +94,12 @@ import org.dspace.core.LogManager; * <map:parameter name="name" value="{2}"/> * </map:read> * + * Added request-item support. + * Original Concept, JSPUI version: Universidade do Minho at www.uminho.pt + * Sponsorship of XMLUI version: Instituto Oceanográfico de España at www.ieo.es + * * @author Scott Phillips + * @author Adán Román Ruiz at arvo.es (added request item support) */ public class BitstreamReader extends AbstractReader implements Recyclable @@ -271,10 +277,11 @@ public class BitstreamReader extends AbstractReader implements Recyclable isAuthorized = false; log.info(LogManager.getHeader(context, "view_bitstream", "handle=" + item.getHandle() + ",withdrawn=true")); } - + // It item-request is enabled to all request we redirect to restricted-resource immediately without login request + String requestItemType = ConfigurationManager.getProperty("request.item.type"); if (!isAuthorized) { - if(context.getCurrentUser() != null){ + if(context.getCurrentUser() != null || StringUtils.equalsIgnoreCase("all", requestItemType)){ // A user is logged in, but they are not authorized to read this bitstream, // instead of asking them to login again we'll point them to a friendly error // message that tells them the bitstream is restricted. @@ -293,7 +300,8 @@ public class BitstreamReader extends AbstractReader implements Recyclable return; } else{ - + if(ConfigurationManager.getProperty("request.item.type")==null|| + ConfigurationManager.getProperty("request.item.type").equalsIgnoreCase("logged")){ // The user does not have read access to this bitstream. Interrupt this current request // and then forward them to the login page so that they can be authenticated. Once that is // successful, their request will be resumed. @@ -306,6 +314,7 @@ public class BitstreamReader extends AbstractReader implements Recyclable objectModel.get(HttpEnvironment.HTTP_RESPONSE_OBJECT); httpResponse.sendRedirect(redictURL); return; + } } } @@ -570,7 +579,7 @@ public class BitstreamReader extends AbstractReader implements Recyclable { // do nothing } - response.setHeader("Content-Disposition", "attachment;filename=" + name); + response.setHeader("Content-Disposition", "attachment;filename=" + '"' + name + '"'); } ByteRange byteRange = null; diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceCocoonServletFilter.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceCocoonServletFilter.java index 17cb705e33ca6013090261a5560f57e1d91f0d98..b8c576fb93b276db5b7839e60facc5ce45652ba5 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceCocoonServletFilter.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceCocoonServletFilter.java @@ -9,6 +9,7 @@ package org.dspace.app.xmlui.cocoon; import java.io.File; import java.io.IOException; +import java.net.SocketException; import java.net.URL; import java.net.URLConnection; @@ -257,22 +258,34 @@ public class DSpaceCocoonServletFilter implements Filter realResponse.sendRedirect(locationWithTrailingSlash); } // if force ssl is on and the user has authenticated and the request is not secure redirect to https - else if ((ConfigurationManager.getBooleanProperty("xmlui.force.ssl")) && (realRequest.getSession().getAttribute("dspace.current.user.id")!=null) && (!realRequest.isSecure())) { - StringBuffer location = new StringBuffer("https://"); - location.append(ConfigurationManager.getProperty("dspace.hostname")).append(realRequest.getContextPath()).append(realRequest.getServletPath()).append( - realRequest.getQueryString() == null ? "" - : ("?" + realRequest.getQueryString())); - realResponse.sendRedirect(location.toString()); + else if ((ConfigurationManager.getBooleanProperty("xmlui.force.ssl")) + && (AuthenticationUtil.isLoggedIn(realRequest)) + && (!realRequest.isSecure())) + { + StringBuffer location = new StringBuffer("https://"); + location.append(ConfigurationManager.getProperty("dspace.hostname")) + .append(realRequest.getContextPath()) + .append(realRequest.getServletPath()) + .append(realRequest.getQueryString() == null ? "" + : ("?" + realRequest.getQueryString())); + realResponse.sendRedirect(location.toString()); } else { // invoke the next filter arg2.doFilter(realRequest, realResponse); } - - } catch (RuntimeException e) { - ContextUtil.abortContext(realRequest); - LOG.error("Serious Runtime Error Occurred Processing Request!", e); - throw e; + } catch (IOException e) { + ContextUtil.abortContext(realRequest); + if (LOG.isDebugEnabled()) { + LOG.debug("The connection was reset", e); + } + else { + LOG.error("Client closed the connection before file download was complete"); + } + } catch (RuntimeException e) { + ContextUtil.abortContext(realRequest); + LOG.error("Serious Runtime Error Occurred Processing Request!", e); + throw e; } catch (Exception e) { ContextUtil.abortContext(realRequest); LOG.error("Serious Error Occurred Processing Request!", e); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceLocaleAction.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceLocaleAction.java index 814f1f5efabddd660dd50073c2fd0bb9f7f20bc1..1e184f927fb221bc36d8f267b8497c9fae494aba 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceLocaleAction.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceLocaleAction.java @@ -16,8 +16,9 @@ import org.apache.cocoon.environment.Redirector; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.i18n.I18nUtils; import org.apache.cocoon.i18n.I18nUtils.LocaleValidator; - +import org.dspace.app.xmlui.utils.ContextUtil; import org.dspace.core.ConfigurationManager; +import org.dspace.core.Context; import org.dspace.core.I18nUtil; import java.util.ArrayList; @@ -40,7 +41,7 @@ import java.util.Map; * 7. Blank * 8. Fail * - * Only those locales which are listed in xmlui.supported.locales will be identified, + * Only those locales which are listed in webui.supported.locales will be identified, * if no acceptable locales are found then the default locale will be used. * * @author Scott Phillips @@ -98,13 +99,16 @@ public class DSpaceLocaleAction extends ServiceableAction implements Configurabl } I18nUtils.storeLocale(objectModel, - "locale-attribute", - localeStr, - false, - false, - false, - false); - + "locale-attribute", + localeStr, + false, + true, + false, + false); + + Context context = ContextUtil.obtainContext(objectModel); + context.setCurrentLocale(locale); + // Set up a map for sitemap parameters Map<String, String> map = new HashMap<String, String>(); map.put("language", locale.getLanguage()); @@ -117,7 +121,7 @@ public class DSpaceLocaleAction extends ServiceableAction implements Configurabl /** * This validator class works with cocoon's i18nutils class to test if locales are valid. - * For dspace we define a locale as valid if it is listed in xmlui.supported.locales config + * For dspace we define a locale as valid if it is listed in webui.supported.locales config * parameter. */ public static class DSpaceLocaleValidator implements LocaleValidator { @@ -130,11 +134,11 @@ public class DSpaceLocaleAction extends ServiceableAction implements Configurabl */ public DSpaceLocaleValidator() { - if (ConfigurationManager.getProperty("xmlui.supported.locales") != null) + if (ConfigurationManager.getProperty("webui.supported.locales") != null) { supportedLocales = new ArrayList<Locale>(); - String supportedLocalesConfig = ConfigurationManager.getProperty("xmlui.supported.locales"); + String supportedLocalesConfig = ConfigurationManager.getProperty("webui.supported.locales"); String[] parts = supportedLocalesConfig.split(","); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/MetadataExportReader.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/MetadataExportReader.java index e5fb571ec77987d2a2fae0bc6873b589c613ca22..32bd29cb011156446b8d9f114957fe9dabac2b86 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/MetadataExportReader.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/MetadataExportReader.java @@ -142,7 +142,7 @@ public class MetadataExportReader extends AbstractReader implements Recyclable * */ - if(this.request.getSession().getAttribute("dspace.current.user.id")!=null) { + if(AuthenticationUtil.isLoggedIn(request)) { String redictURL = request.getContextPath() + "/restricted-resource"; HttpServletResponse httpResponse = (HttpServletResponse) objectModel.get(HttpEnvironment.HTTP_RESPONSE_OBJECT); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/UsageLoggerAction.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/UsageLoggerAction.java index 5297287ecf1eba5acd98f7edb2013a2d210d70c0..771b46b5eba150cca79553f6671c5dea3e908662 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/UsageLoggerAction.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/cocoon/UsageLoggerAction.java @@ -31,11 +31,7 @@ import java.util.Map; import javax.servlet.http.HttpServletRequest; /** - * Created by IntelliJ IDEA. - * User: kevinvandevelde - * Date: 22-dec-2008 - * Time: 15:00:55 - * To change this template use File | Settings | File Templates. + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class UsageLoggerAction extends AbstractAction { @@ -239,7 +235,7 @@ public class UsageLoggerAction extends AbstractAction { } - // The named bitstream was not found and we exausted our the maximum path depth that + // The named bitstream was not found and we exausted the maximum path depth that // we search. return null; } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/configuration/XMLUISpringLoader.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/configuration/XMLUISpringLoader.java index 2820de7402c422de7cfd94971158cf0a8276c41f..763608c8f1f57d9ba83a729cc4b8ae024479690c 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/configuration/XMLUISpringLoader.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/configuration/XMLUISpringLoader.java @@ -14,9 +14,7 @@ import java.io.File; import java.net.MalformedURLException; /** - * User: kevin (kevin at atmire.com) - * Date: 3-aug-2011 - * Time: 11:26:34 + * @author Kevin Van de Velde (kevin at atmire dot com) */ public class XMLUISpringLoader implements SpringLoader { @@ -38,4 +36,4 @@ public class XMLUISpringLoader implements SpringLoader { return new String[0]; } } -} \ No newline at end of file +} diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/AbstractAdapter.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/AbstractAdapter.java index 91d1df294b39b131dcb22c1c83743720592f02ae..022b0b4b1dc0b322b2c0dad5515c088a5c84f6fd 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/AbstractAdapter.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/AbstractAdapter.java @@ -680,11 +680,11 @@ public abstract class AbstractAdapter AttributesImpl attributes = new AttributesImpl(); for (AttributeMap attributeMap : attributeMaps) { - boolean diffrentNamespaces = false; + boolean differentNamespaces = false; Namespace attributeNamespace = attributeMap.getNamespace(); if (attributeNamespace != null && !(attributeNamespace.URI.equals(elementNamespace.URI))) { - diffrentNamespaces = true; + differentNamespaces = true; } // copy each one over. @@ -695,7 +695,7 @@ public abstract class AbstractAdapter continue; } - if (diffrentNamespaces) + if (differentNamespaces) { attributes.addAttribute(attributeNamespace.URI, attr.getKey(), qName(attributeNamespace, attr.getKey()), "CDATA", attr.getValue()); diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/ContainerAdapter.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/ContainerAdapter.java index b379ad619878a9f317bf037d6059a3aca717fd0f..eee0bb6080a27274b5ac565421dba8e26f56b0f4 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/ContainerAdapter.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/ContainerAdapter.java @@ -273,21 +273,20 @@ public class ContainerAdapter extends AbstractAdapter createField("dc","rights","license",null,rights_license); createField("dc","title",null,null,title); - boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache"); + boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show"); - //To improve scalability, XMLUI only adds item counts if they are cached - if (useCache) - { - try - { //try to determine Collection size (i.e. # of items) - int size = new ItemCounter(this.dspaceContext).getCount(collection); - createField("dc","format","extent",null, String.valueOf(size)); - } - catch(ItemCountException e) - { - throw new IOException("Could not obtain Collection item-count", e); - } - } + if (showCount) + { + try + { // try to determine Collection size (i.e. # of items) + int size = new ItemCounter(this.dspaceContext).getCount(collection); + createField("dc","format","extent",null, String.valueOf(size)); + } + catch (ItemCountException e) + { + throw new IOException("Could not obtain Collection item count", e); + } + } } else if (dso.getType() == Constants.COMMUNITY) { @@ -307,26 +306,25 @@ public class ContainerAdapter extends AbstractAdapter createField("dc","rights",null,null,rights); createField("dc","title",null,null,title); - boolean useCache = ConfigurationManager.getBooleanProperty("webui.strengths.cache"); + boolean showCount = ConfigurationManager.getBooleanProperty("webui.strengths.show"); - //To improve scalability, XMLUI only adds item counts if they are cached - if (useCache) - { - try - { //try to determine Community size (i.e. # of items) - int size = new ItemCounter(this.dspaceContext).getCount(community); - createField("dc","format","extent",null, String.valueOf(size)); - } - catch(ItemCountException e) - { - throw new IOException("Could not obtain Collection item-count", e); - } - } + if (showCount) + { + try + { // try to determine Community size (i.e. # of items) + int size = new ItemCounter(this.dspaceContext).getCount(community); + createField("dc","format","extent",null, String.valueOf(size)); + } + catch (ItemCountException e) + { + throw new IOException("Could not obtain Collection item count", e); + } + } } // /////////////////////////////// - // End the DIM element - endElement(DIM,"dim"); + // End the DIM element + endElement(DIM,"dim"); // //////////////////////////////// // End elements diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/ItemAdapter.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/ItemAdapter.java index f22019b914e426f26a83288fdf463306b7257d17..18500107a7a74bac917cce4ed50c0082d2474013 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/ItemAdapter.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/objectmanager/ItemAdapter.java @@ -8,10 +8,13 @@ package org.dspace.app.xmlui.objectmanager; import org.dspace.app.util.MetadataExposure; +import org.dspace.app.util.Util; import org.dspace.app.xmlui.wing.AttributeMap; import org.dspace.app.xmlui.wing.WingException; import org.dspace.authorize.AuthorizeException; +import org.dspace.authorize.AuthorizeManager; import org.dspace.content.Bitstream; +import org.dspace.content.BitstreamFormat; import org.dspace.content.Bundle; import org.dspace.content.DCValue; import org.dspace.content.Item; @@ -31,6 +34,7 @@ import org.xml.sax.helpers.XMLReaderFactory; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.sql.SQLException; import java.util.*; @@ -52,8 +56,13 @@ import org.dspace.content.DSpaceObject; * * There are four parts to an item's METS document: descriptive metadata, * file section, structural map, and extra sections. - * + * + * Request item-support + * Original Concept, JSPUI version: Universidade do Minho at www.uminho.pt + * Sponsorship of XMLUI version: Instituto Oceanográfico de España at www.ieo.es + * * @author Scott Phillips + * @author Adán Román Ruiz at arvo.es (for request item support) */ public class ItemAdapter extends AbstractAdapter @@ -728,7 +737,7 @@ public class ItemAdapter extends AbstractAdapter } // Render the actual file & flocate elements. - renderFile(item, bitstream, fileID, groupID, admIDs); + renderFileWithAllowed(item, bitstream, fileID, groupID, admIDs); // Remember all the viewable content bitstreams for later in the // structMap. @@ -947,9 +956,8 @@ public class ItemAdapter extends AbstractAdapter Bundle[] bundles = item.getBundles(); // Filename of original will be filename of the derived bitstream - // minus the extension (last 4 chars - .jpg or .txt) - String originalFilename = derived.getName().substring(0, - derived.getName().length() - 4); + // minus the extension (ie everything from and including the last "." character) + String originalFilename = derived.getName().substring(0, derived.getName().lastIndexOf(".")); // First find "original" bundle for (int i = 0; i < bundles.length; i++) @@ -973,4 +981,141 @@ public class ItemAdapter extends AbstractAdapter // Didn't find it return null; } + /** + * Generate a METS file element for a given bitstream. + * + * @param item + * If the bitstream is associated with an item provide the item + * otherwise leave null. + * @param bitstream + * The bitstream to build a file element for. + * @param fileID + * The unique file id for this file. + * @param groupID + * The group id for this file, if it is derived from another file + * then they should share the same groupID. + * @param admID + * The IDs of the administrative metadata sections which pertain + * to this file + */ + + // FIXME: this method is a copy of the one inherited. However the + // original method is final so we must rename it. + protected void renderFileWithAllowed(Item item, Bitstream bitstream, String fileID, String groupID, String admID) throws SAXException + { + AttributeMap attributes; + + // ////////////////////////////// + // Determine the file attributes + BitstreamFormat format = bitstream.getFormat(); + String mimeType = null; + if (format != null) + { + mimeType = format.getMIMEType(); + } + String checksumType = bitstream.getChecksumAlgorithm(); + String checksum = bitstream.getChecksum(); + long size = bitstream.getSize(); + + // //////////////////////////////// + // Start the actual file + attributes = new AttributeMap(); + attributes.put("ID", fileID); + attributes.put("GROUPID",groupID); + if (admID != null && admID.length()>0) + { + attributes.put("ADMID", admID); + } + if (mimeType != null && mimeType.length()>0) + { + attributes.put("MIMETYPE", mimeType); + } + if (checksumType != null && checksum != null) + { + attributes.put("CHECKSUM", checksum); + attributes.put("CHECKSUMTYPE", checksumType); + } + attributes.put("SIZE", String.valueOf(size)); + startElement(METS,"file",attributes); + + + // //////////////////////////////////// + // Determine the file location attributes + String name = bitstream.getName(); + String description = bitstream.getDescription(); + + + // If possible reference this bitstream via a handle, however this may + // be null if a handle has not yet been assigned. In this case reference the + // item its internal id. In the last case where the bitstream is not associated + // with an item (such as a community logo) then reference the bitstreamID directly. + String identifier = null; + if (item != null && item.getHandle() != null) + { + identifier = "handle/" + item.getHandle(); + } + else if (item != null) + { + identifier = "item/" + item.getID(); + } + else + { + identifier = "id/" + bitstream.getID(); + } + + + String url = contextPath + "/bitstream/"+identifier+"/"; + + // If we can put the pretty name of the bitstream on the end of the URL + try + { + if (bitstream.getName() != null) + { + url += Util.encodeBitstreamName(bitstream.getName(), "UTF-8"); + } + } + catch (UnsupportedEncodingException uee) + { + // just ignore it, we don't have to have a pretty + // name on the end of the URL because the sequence id will + // locate it. However it means that links in this file might + // not work.... + } + + url += "?sequence="+bitstream.getSequenceID(); + + // Test if we are allowed to see this item + String isAllowed = "n"; + try { + if (AuthorizeManager.authorizeActionBoolean(context, bitstream, Constants.READ)) { + isAllowed = "y"; + } + } catch (SQLException e) {/* Do nothing */} + + url += "&isAllowed=" + isAllowed; + + // ////////////////////// + // Start the file location + attributes = new AttributeMap(); + AttributeMap attributesXLINK = new AttributeMap(); + attributesXLINK.setNamespace(XLINK); + attributes.put("LOCTYPE", "URL"); + attributesXLINK.put("type","locator"); + attributesXLINK.put("title", name); + if (description != null) + { + attributesXLINK.put("label", description); + } + attributesXLINK.put("href", url); + startElement(METS,"FLocat",attributes,attributesXLINK); + + + // /////////////////////// + // End file location + endElement(METS,"FLocate"); + + // //////////////////////////////// + // End the file + endElement(METS,"file"); + } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/utils/AuthenticationUtil.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/utils/AuthenticationUtil.java index f72f548bd93c6fe24a6819e14ad38acc3520506e..61682e2ec5b1e8c63677ca34b271bc9e59bad5cb 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/utils/AuthenticationUtil.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/utils/AuthenticationUtil.java @@ -306,7 +306,7 @@ public class AuthenticationUtil throws SQLException, AuthorizeException { // Only allow loginAs if the administrator has allowed it. - if (!ConfigurationManager.getBooleanProperty("xmlui.user.assumelogin", false)) + if (!ConfigurationManager.getBooleanProperty("webui.user.assumelogin", false)) { return; } @@ -613,5 +613,14 @@ public class AuthenticationUtil // Otherwise return the real request. return realHttpRequest; } - + + /** + * Has this user authenticated? + * @param request + * @return true if request is in a session having a user ID. + */ + public static boolean isLoggedIn(HttpServletRequest request) + { + return (null != request.getSession().getAttribute(EFFECTIVE_USER_ID)); + } } diff --git a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/utils/DSpaceValidity.java b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/utils/DSpaceValidity.java index 446bdec686666d3ca18cd78400d1da71a8023e3b..2a43196a1276e33826f0eaa31a04a3cd234dad04 100644 --- a/dspace-xmlui/src/main/java/org/dspace/app/xmlui/utils/DSpaceValidity.java +++ b/dspace-xmlui/src/main/java/org/dspace/app/xmlui/utils/DSpaceValidity.java @@ -108,7 +108,7 @@ public class DSpaceValidity implements SourceValidity /** * Set the time delay for how long this cache will be assumed * to be valid. When it is assumed valid no other checks will be - * made to consider it's validity, and once the time has expired + * made to consider its validity, and once the time has expired * a full validation will occur on the next cache hit. If the * cache proves to be validated on this hit then the assumed * validity timer is reset. @@ -390,7 +390,7 @@ public class DSpaceValidity implements SourceValidity /** - * This method is used during serializion. When tomcat is shutdown cocoon's in-memory + * This method is used during serializion. When Tomcat is shutdown, Cocoon's in-memory * cache is serialized and written to disk to later be read back into memory on start * up. When this class is read back into memory the readObject(stream) method will be * called. @@ -448,7 +448,7 @@ public class DSpaceValidity implements SourceValidity } else { - // This is an error, state. We are being asked whether we are valid before + // This is an error state. We are being asked whether we are valid before // we have been initialized. return SourceValidity.INVALID; } diff --git a/dspace-xmlui/src/main/resources/aspects/ArtifactBrowser/sitemap.xmap b/dspace-xmlui/src/main/resources/aspects/ArtifactBrowser/sitemap.xmap index ab058d09b30328a82c6364ad1d6168c10ba965ea..873036d7c20c74a70dedc41b9bd731b25782f351 100644 --- a/dspace-xmlui/src/main/resources/aspects/ArtifactBrowser/sitemap.xmap +++ b/dspace-xmlui/src/main/resources/aspects/ArtifactBrowser/sitemap.xmap @@ -35,7 +35,7 @@ and searching the repository. <map:transformer name="FeedbackSent" src="org.dspace.app.xmlui.aspect.artifactbrowser.FeedbackSent"/> <map:transformer name="Contact" src="org.dspace.app.xmlui.aspect.artifactbrowser.Contact"/> <map:transformer name="RestrictedItem" src="org.dspace.app.xmlui.aspect.artifactbrowser.RestrictedItem"/> - <map:transformer name="FrontPageSearch" src="org.dspace.app.xmlui.aspect.artifactbrowser.FrontPageSearch"/> + <map:transformer name="FrontPageFeeds" src="org.dspace.app.xmlui.aspect.artifactbrowser.FrontPageFeeds"/> <map:transformer name="Statistics" src="org.dspace.app.xmlui.aspect.artifactbrowser.StatisticsViewer"/> </map:transformers> @@ -67,7 +67,7 @@ and searching the repository. <map:generate/> <!-- - Add the basic navigation content to everypage. This includes: + Add the basic navigation content to every page. This includes: 1) Metadata about the current page (really just what the current context path is) @@ -94,7 +94,7 @@ and searching the repository. <map:transform type="Include" src="file://{dspace.dir}/config/news-xmlui.xml" /> </map:act> - <map:transform type="FrontPageSearch"/> + <map:transform type="FrontPageFeeds"/> <map:transform type="CommunityBrowser"> <map:parameter name="depth" value="1"/> </map:transform> diff --git a/dspace-xmlui/src/main/resources/aspects/BrowseArtifacts/sitemap.xmap b/dspace-xmlui/src/main/resources/aspects/BrowseArtifacts/sitemap.xmap index 39f9c682fd5b616043e0520fe9ead0db6cc7c115..f02bb9f3690c82b15726922985ab31d32a1791b4 100644 --- a/dspace-xmlui/src/main/resources/aspects/BrowseArtifacts/sitemap.xmap +++ b/dspace-xmlui/src/main/resources/aspects/BrowseArtifacts/sitemap.xmap @@ -23,6 +23,8 @@ collections / items / and bitstreams. <map:transformer name="CommunityBrowser" src="org.dspace.app.xmlui.aspect.artifactbrowser.CommunityBrowser"/> <map:transformer name="CommunityRecentSubmissions" src="org.dspace.app.xmlui.aspect.artifactbrowser.CommunityRecentSubmissions"/> <map:transformer name="CollectionRecentSubmissions" src="org.dspace.app.xmlui.aspect.artifactbrowser.CollectionRecentSubmissions"/> + <map:transformer name="CommunityBrowse" src="org.dspace.app.xmlui.aspect.browseArtifacts.CommunityBrowse"/> + <map:transformer name="CollectionBrowse" src="org.dspace.app.xmlui.aspect.browseArtifacts.CollectionBrowse"/> <map:transformer name="ConfigurableBrowse" src="org.dspace.app.xmlui.aspect.artifactbrowser.ConfigurableBrowse"/> <map:transformer name="StaticPage" src="org.dspace.app.xmlui.aspect.browseArtifacts.StaticPage"/> </map:transformers> @@ -30,6 +32,7 @@ collections / items / and bitstreams. <map:matchers default="wildcard"> <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="ContainerHomePageSelector" src="org.dspace.app.xmlui.aspect.viewArtifacts.ContainerHomePageMatcher"/> </map:matchers> </map:components> @@ -81,13 +84,17 @@ collections / items / and bitstreams. <map:match type="HandleTypeMatcher" pattern="community"> <map:match pattern="handle/*/*"> + <map:transform type="CommunityBrowse"/> <map:transform type="CommunityRecentSubmissions"/> </map:match> </map:match> <map:match type="HandleTypeMatcher" pattern="collection"> <map:match pattern="handle/*/*"> - <map:transform type="CollectionRecentSubmissions"/> + <map:match type="ContainerHomePageSelector" pattern="metadata"> + <map:transform type="CollectionBrowse"/> + <map:transform type="CollectionRecentSubmissions"/> + </map:match> </map:match> </map:match> diff --git a/dspace-xmlui/src/main/resources/aspects/Discovery/i18n/messages.xml b/dspace-xmlui/src/main/resources/aspects/Discovery/i18n/messages.xml index dfb93ab461c88759ba8cd92c571a45e071bf69a0..75da2366635b6a4490c55325859810ae6fae9e3d 100644 --- a/dspace-xmlui/src/main/resources/aspects/Discovery/i18n/messages.xml +++ b/dspace-xmlui/src/main/resources/aspects/Discovery/i18n/messages.xml @@ -41,6 +41,11 @@ <!-- Site Leve Recently Added Content --> <message key="xmlui.ArtifactBrowser.SiteViewer.head_recent_submissions">Recently Added</message> + <message key="xmlui.ArtifactBrowser.AbstractRecentSubmissionTransformer.recent_submissions_more">View more</message> + <message key="xmlui.Discovery.RecentSubmissions.RecentSubmissionTransformer.head">{0}: Recent submissions</message> + <message key="xmlui.Discovery.RecentSubmissions.RecentSubmissionTransformer.trail">Recent submissions</message> + <message key="xmlui.Discovery.RecentSubmissions.RecentSubmissionTransformer.recent.head">Recently added</message> + <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_type_filter">Kind</message> <message key="xmlui.ArtifactBrowser.AdvancedSearch.type_publisher_filter">Publisher</message> @@ -148,4 +153,6 @@ <message key="xmlui.Discovery.AbstractSearch.head2">Communities or Collections matching your query</message> <message key="xmlui.Discovery.AbstractSearch.head3">Items matching your query</message> + <message key="xmlui.Discovery.SimpleSearch.did_you_mean">Did you mean: </message> + </catalogue> diff --git a/dspace-xmlui/src/main/resources/aspects/Discovery/sitemap.xmap b/dspace-xmlui/src/main/resources/aspects/Discovery/sitemap.xmap index 9ab23dff9d2238dba703017bc01fcf7c97b751b1..d4a895e808425588db52845f5819e6c63cca464b 100644 --- a/dspace-xmlui/src/main/resources/aspects/Discovery/sitemap.xmap +++ b/dspace-xmlui/src/main/resources/aspects/Discovery/sitemap.xmap @@ -26,7 +26,7 @@ and searching the repository. <map:transformer name="SimpleSearch" src="org.dspace.app.xmlui.aspect.discovery.SimpleSearch"/> <map:transformer name="BrowseFacet" src="org.dspace.app.xmlui.aspect.discovery.BrowseFacet"/> <map:transformer name="SearchFacetFilter" src="org.dspace.app.xmlui.aspect.discovery.SearchFacetFilter"/> - <map:transformer name="FrontPageSearch" src="org.dspace.app.xmlui.aspect.discovery.SiteViewer"/> + <map:transformer name="FrontPageFeeds" src="org.dspace.app.xmlui.aspect.discovery.SiteViewer"/> <map:transformer name="SiteRecentSubmissions" src="org.dspace.app.xmlui.aspect.discovery.SiteRecentSubmissions"/> <map:transformer name="SidebarFacetsTransformer" src="org.dspace.app.xmlui.aspect.discovery.SidebarFacetsTransformer"/> @@ -42,6 +42,7 @@ and searching the repository. <map:transformer name="RelatedItems" src="org.dspace.app.xmlui.aspect.discovery.RelatedItems"/> <map:transformer name="RestrictedItem" src="org.dspace.app.xmlui.aspect.artifactbrowser.RestrictedItem"/> + <map:transformer name="RecentSubmissionTransformer" src="org.dspace.app.xmlui.aspect.discovery.recentSubmissions.RecentSubmissionTransformer"/> </map:transformers> <map:actions> @@ -51,6 +52,7 @@ and searching the repository. <map:matchers default="wildcard"> <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="ContainerHomePageSelector" src="org.dspace.app.xmlui.aspect.viewArtifacts.ContainerHomePageMatcher"/> </map:matchers> <map:selectors> <map:selector name="AuthenticatedSelector" src="org.dspace.app.xmlui.aspect.general.AuthenticatedSelector"/> @@ -64,7 +66,7 @@ and searching the repository. <map:generate/> <!-- - Add the basic navigation content to everypage. This includes: + Add the basic navigation content to every page. This includes: 1) Metadata about the current page (really just what the current context path is) @@ -81,13 +83,21 @@ and searching the repository. --> <map:match pattern=""> <map:transform type="SidebarFacetsTransformer"/> - <map:transform type="FrontPageSearch"/> + <map:transform type="FrontPageFeeds"/> <map:transform type="SiteRecentSubmissions"/> <map:serialize type="xml"/> </map:match> + <map:match pattern="recent-submissions"> + <map:transform type="RecentSubmissionTransformer"> + <map:parameter name="isHomePage" value="false"/> + </map:transform> + + <map:serialize type="xml"/> + </map:match> + <!-- List all communities & collections in DSpace <map:match pattern="community-list"> @@ -149,11 +159,29 @@ and searching the repository. <map:serialize type="xml"/> </map:match> - <map:match pattern="handle/*/*/search-filter"> <map:transform type="SearchFacetFilter"/> <map:serialize type="xml"/> </map:match> + + <map:match pattern="handle/*/*/recent-submissions"> + <map:transform type="RecentSubmissionTransformer"> + <map:parameter name="isHomePage" value="false"/> + </map:transform> + <map:serialize type="xml"/> + </map:match> + + <map:match pattern="handle/*/*"> + <map:match type="HandleTypeMatcher" pattern="collection"> + <map:match type="ContainerHomePageSelector" pattern="discoveryRecentSubmissions"> + <map:transform type="SidebarFacetsTransformer"/> + <map:transform type="RecentSubmissionTransformer"> + <map:parameter name="isHomePage" value="true"/> + </map:transform> + <map:serialize type="xml"/> + </map:match> + </map:match> + </map:match> </map:match> </map:match> diff --git a/dspace-xmlui/src/main/resources/aspects/Feedback/sitemap.xmap b/dspace-xmlui/src/main/resources/aspects/Feedback/sitemap.xmap index 703309e6f1524c4490204037961fc03df17233a6..4e29b1f31396b0d9f140ee2e4616d63ef9016678 100644 --- a/dspace-xmlui/src/main/resources/aspects/Feedback/sitemap.xmap +++ b/dspace-xmlui/src/main/resources/aspects/Feedback/sitemap.xmap @@ -44,7 +44,7 @@ and searching the repository. <map:generate/> <!-- - Add the basic navigation content to everypage. This includes: + Add the basic navigation content to every page. This includes: 1) Metadata about the current page (really just what the current context path is) diff --git a/dspace-xmlui/src/main/resources/aspects/SearchArtifacts/sitemap.xmap b/dspace-xmlui/src/main/resources/aspects/SearchArtifacts/sitemap.xmap index 4bd741813a34bcce18b3835c0ac475d34427662b..fed81a0a2802a2541f476bed96a72cbbc4fbfcf7 100644 --- a/dspace-xmlui/src/main/resources/aspects/SearchArtifacts/sitemap.xmap +++ b/dspace-xmlui/src/main/resources/aspects/SearchArtifacts/sitemap.xmap @@ -24,7 +24,7 @@ and searching the repository. <map:transformer name="Navigation" src="org.dspace.app.xmlui.aspect.searchArtifacts.Navigation"/> <map:transformer name="SimpleSearch" src="org.dspace.app.xmlui.aspect.artifactbrowser.SimpleSearch"/> <map:transformer name="AdvancedSearch" src="org.dspace.app.xmlui.aspect.artifactbrowser.AdvancedSearch"/> - <map:transformer name="FrontPageSearch" src="org.dspace.app.xmlui.aspect.artifactbrowser.FrontPageSearch"/> + <map:transformer name="FrontPageFeeds" src="org.dspace.app.xmlui.aspect.artifactbrowser.FrontPageFeeds"/> <map:transformer name="CommunitySearch" src="org.dspace.app.xmlui.aspect.artifactbrowser.CommunitySearch"/> <map:transformer name="CollectionSearch" src="org.dspace.app.xmlui.aspect.artifactbrowser.CollectionSearch"/> @@ -64,7 +64,7 @@ and searching the repository. <map:generate/> <!-- - Add the basic navigation content to everypage. This includes: + Add the basic navigation content to every page. This includes: 1) Metadata about the current page (really just what the current context path is) @@ -81,7 +81,7 @@ and searching the repository. along with a list of top level communities in DSpace. --> <map:match pattern=""> - <map:transform type="FrontPageSearch"/> + <map:transform type="FrontPageFeeds"/> </map:match> diff --git a/dspace-xmlui/src/main/resources/aspects/Statistics/sitemap.xmap b/dspace-xmlui/src/main/resources/aspects/Statistics/sitemap.xmap index c3b9a011b28ef6a7f7ca6f256c330cfb097ac5e8..4f4027cddf1e43512d7c24b9990ccccdd3fecb7a 100644 --- a/dspace-xmlui/src/main/resources/aspects/Statistics/sitemap.xmap +++ b/dspace-xmlui/src/main/resources/aspects/Statistics/sitemap.xmap @@ -183,12 +183,6 @@ </map:match> </map:match> - <map:match pattern="dso-display"> - <map:act type="SearchResultLogAction"/> - </map:match> - - - <map:match pattern="search"> <map:transform type="IncludePageMeta"> <map:parameter name="javascript.static.statistics#1" value="loadJQuery.js"/> @@ -227,14 +221,27 @@ <!-- Handle specific features --> <map:match pattern="handle/*/**"> + <!-- Logging in case of a search result --> + <map:match pattern="handle/*/*"> + <!-- Make sure we have a search result by checking the parameter --> + <map:match type="request-parameter" pattern="search-result"> + <map:match type="HandleAuthorizedMatcher" pattern="READ"> + <map:match type="HandleTypeMatcher" pattern="community"> + <map:act type="SearchResultLogAction"/> + </map:match> + <map:match type="HandleTypeMatcher" pattern="collection"> + <map:act type="SearchResultLogAction"/> + </map:match> + <map:match type="HandleTypeMatcher" pattern="item"> + <map:act type="SearchResultLogAction"/> + </map:match> + </map:match> + </map:match> + </map:match> <!-- Scoped browse by features --> <map:match type="HandleAuthorizedMatcher" pattern="READ"> <map:match type="HandleTypeMatcher" pattern="community,collection"> - <map:match pattern="handle/*/*/dso-display"> - <map:act type="SearchResultLogAction"/> - </map:match> - <!-- Simple search --> <map:match pattern="handle/*/*/search"> <map:transform type="IncludePageMeta"> @@ -282,8 +289,8 @@ <!-- End match handle/*/** --> - <map:serialize type="xml"/> + <map:serialize type="xml"/> - </map:pipeline> + </map:pipeline> </map:pipelines> </map:sitemap> diff --git a/dspace-xmlui/src/main/resources/aspects/ViewArtifacts/sitemap.xmap b/dspace-xmlui/src/main/resources/aspects/ViewArtifacts/sitemap.xmap index f8cd19a3d174348a4cdecddf539d3e85fff0d12e..28e7bdf76ac1a20715860b218c116c076f9375d2 100644 --- a/dspace-xmlui/src/main/resources/aspects/ViewArtifacts/sitemap.xmap +++ b/dspace-xmlui/src/main/resources/aspects/ViewArtifacts/sitemap.xmap @@ -14,53 +14,69 @@ The ArtifactBrowser Aspect is responsible for browsing communities / collections / items / and bitstreams, viewing an individual item, and searching the repository. - --> + +<!-- Added request-item support + Original Concept, JSPUI version: Universidade do Minho at www.uminho.pt + Sponsorship of XMLUI version: Instituto Oceanográfico de España at www.ieo.es --> + <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0"> <map:components> - <map:transformers> - <map:transformer name="Navigation" src="org.dspace.app.xmlui.aspect.viewArtifacts.Navigation"/> - <map:transformer name="CommunityViewer" src="org.dspace.app.xmlui.aspect.artifactbrowser.CommunityViewer"/> - <map:transformer name="CollectionViewer" src="org.dspace.app.xmlui.aspect.artifactbrowser.CollectionViewer"/> - <map:transformer name="ItemViewer" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemViewer"/> - <map:transformer name="FeedbackForm" src="org.dspace.app.xmlui.aspect.artifactbrowser.FeedbackForm"/> - <map:transformer name="FeedbackSent" src="org.dspace.app.xmlui.aspect.artifactbrowser.FeedbackSent"/> - <map:transformer name="Contact" src="org.dspace.app.xmlui.aspect.artifactbrowser.Contact"/> - <map:transformer name="RestrictedItem" src="org.dspace.app.xmlui.aspect.artifactbrowser.RestrictedItem"/> + <map:transformers> + <map:transformer name="Navigation" src="org.dspace.app.xmlui.aspect.viewArtifacts.Navigation" /> + <map:transformer name="CommunityViewer" src="org.dspace.app.xmlui.aspect.artifactbrowser.CommunityViewer" /> + <map:transformer name="CollectionViewer" src="org.dspace.app.xmlui.aspect.artifactbrowser.CollectionViewer" /> + <map:transformer name="ItemViewer" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemViewer" /> + <map:transformer name="ItemRequestForm" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemRequestForm" /> + <map:transformer name="ItemRequestSent" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemRequestSent" /> + <map:transformer name="FeedbackForm" src="org.dspace.app.xmlui.aspect.artifactbrowser.FeedbackForm" /> + <map:transformer name="FeedbackSent" src="org.dspace.app.xmlui.aspect.artifactbrowser.FeedbackSent" /> + <map:transformer name="Contact" src="org.dspace.app.xmlui.aspect.artifactbrowser.Contact" /> + <map:transformer name="RestrictedItem" src="org.dspace.app.xmlui.aspect.artifactbrowser.RestrictedItem" /> + <map:transformer name="ItemRequestResponseDecisionForm" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemRequestResponseDecisionForm" /> + <map:transformer name="ItemRequestChangeStatusForm" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemRequestChangeStatusForm" /> + <map:transformer name="ItemRequestResponseFalseForm" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemRequestResponseFalseForm" /> + <map:transformer name="ItemRequestResponseTrueForm" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemRequestResponseTrueForm" /> + <map:transformer name="ItemRequestStatusChanged" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemRequestStatusChanged" /> <map:transformer name="Statistics" src="org.dspace.app.xmlui.aspect.artifactbrowser.StatisticsViewer"/> </map:transformers> - <map:matchers default="wildcard"> - <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:matchers> + <map:matchers default="wildcard"> + <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="ContainerHomePageSelector" src="org.dspace.app.xmlui.aspect.viewArtifacts.ContainerHomePageMatcher"/> + <map:matcher name="ConfigurationMatcher" src="org.dspace.app.xmlui.aspect.general.ConfigurationMatcher" /> + </map:matchers> + + <map:actions> + <map:action name="SendFeedbackAction" src="org.dspace.app.xmlui.aspect.artifactbrowser.SendFeedbackAction" /> + <map:action name="SendItemRequestAction" src="org.dspace.app.xmlui.aspect.artifactbrowser.SendItemRequestAction" /> + <map:action name="UsageLoggerAction" src="org.dspace.app.xmlui.cocoon.UsageLoggerAction" /> + <map:action name="NotModifiedAction" src="org.dspace.app.xmlui.aspect.general.NotModifiedAction" /> + <map:action name="ItemRequestResponseAction" src="org.dspace.app.xmlui.aspect.artifactbrowser.ItemRequestResponseAction" /> + </map:actions> - <map:actions> - <map:action name="SendFeedbackAction" src="org.dspace.app.xmlui.aspect.artifactbrowser.SendFeedbackAction"/> - <map:action name="UsageLoggerAction" src="org.dspace.app.xmlui.cocoon.UsageLoggerAction"/> - <map:action name="NotModifiedAction" src="org.dspace.app.xmlui.aspect.general.NotModifiedAction"/> - </map:actions> + <map:selectors> + <map:selector name="AuthenticatedSelector" src="org.dspace.app.xmlui.aspect.general.AuthenticatedSelector" /> + <map:selector name="IfModifiedSinceSelector" src="org.dspace.app.xmlui.aspect.general.IfModifiedSinceSelector" /> + </map:selectors> - <map:selectors> - <map:selector name="AuthenticatedSelector" src="org.dspace.app.xmlui.aspect.general.AuthenticatedSelector"/> - <map:selector name="IfModifiedSinceSelector" src="org.dspace.app.xmlui.aspect.general.IfModifiedSinceSelector"/> - </map:selectors> - </map:components> - <map:pipelines> - <map:pipeline> + </map:components> + <map:pipelines> + <map:pipeline> <map:generate/> <!-- - Add the basic navigation content to everypage. This includes: + Add the basic navigation content to every page. This includes: 1) Metadata about the current page (really just what the current context path is) @@ -91,132 +107,238 @@ and searching the repository. </map:match> - <!-- Display statistics --> - <map:match pattern="statistics"> - <map:transform type="Statistics"/> - <map:serialize type="xml"/> - </map:match> - - - <!-- restricted resource --> - <map:match pattern="restricted-resource"> - <map:transform type="RestrictedItem"/> - <map:serialize type="xml"/> - </map:match> - - - <!-- Handle specific features --> - <map:match pattern="handle/*/**"> - - <!-- Inform the user that the item they are viewing is a restricted resource --> - <map:match pattern="handle/*/*/restricted-resource"> - <map:transform type="RestrictedItem"/> - <map:serialize type="xml"/> - </map:match> - - <!-- Community, Collection, and Item Viewers --> - <map:match pattern="handle/*/*"> - <map:match type="HandleAuthorizedMatcher" pattern="READ"> - <map:match type="HandleTypeMatcher" pattern="community"> - <map:act type="UsageLoggerAction"> - <map:parameter name="type" value="community"/> - <map:parameter name="eventType" value="view"/> - </map:act> - <map:transform type="CommunityViewer"/> - <map:serialize type="xml"/> - </map:match> - <map:match type="HandleTypeMatcher" pattern="collection"> - <map:act type="UsageLoggerAction"> - <map:parameter name="type" value="collection"/> - <map:parameter name="eventType" value="view"/> - </map:act> - <map:transform type="CollectionViewer"/> - <map:serialize type="xml"/> - </map:match> - <map:match type="HandleTypeMatcher" pattern="item"> - <map:act type="UsageLoggerAction"> - <map:parameter name="type" value="item"/> - <map:parameter name="eventType" value="view"/> - </map:act> - <!-- Implement HTTP If-Modified-Since protocol (commonly used by search - - engine crawlers): return 304 NOT MODIFIED status if Item's - - last-modified date is before If-Modified-Since header. - - - - NOTE: Do NOT do this for interactive users since it might encourage - - browser to cache a view that is only shown to authenticated users. - - ONLY do this when user-agent is a spider (search-engine crawler robot) - - since they should only ever have "anonymous" access. - - - - NOTE: Cocoon always automatically sets Last-Modified: header on its - - transformed pages with the current timestamp, which we cannot override. - - It won't prevent a spider's If-Modified-Since from working, though. - --> - <map:select type="browser"> - <map:when test="spider"> - <map:select type="IfModifiedSinceSelector"> - <map:when test="true"> - <map:act type="NotModifiedAction"/> - <map:serialize/> - </map:when> - <map:otherwise> - <map:transform type="ItemViewer"/> - <map:serialize type="xml"/> - </map:otherwise> - </map:select> - </map:when> - <map:otherwise> - <map:transform type="ItemViewer"/> - <map:serialize type="xml"/> - </map:otherwise> - </map:select> - </map:match> - </map:match> - - <map:match type="HandleAuthorizedMatcher" pattern="!READ"> - <map:transform type="RestrictedItem"> - <map:parameter name="header" value="xmlui.ArtifactBrowser.RestrictedItem.auth_header"/> - <map:parameter name="message" value="xmlui.ArtifactBrowser.RestrictedItem.auth_message"/> - </map:transform> - <map:serialize type="xml"/> - </map:match> - </map:match> - - - </map:match> <!-- End match handle/*/** --> - - - <!-- - A simple feedback utility that presents the user with a form to fill out, - the results of which are emailed to the site administrator. - --> - <map:match pattern="feedback"> - <map:act type="SendFeedbackAction"> - <map:transform type="FeedbackForm"> - <map:parameter name="comments" value="{comments}"/> - <map:parameter name="email" value="{email}"/> - <map:parameter name="page" value="{page}"/> - </map:transform> - - <map:serialize type="xml"/> - </map:act> - <map:transform type="FeedbackSent"/> - <map:serialize type="xml"/> - </map:match> - - <!-- - The most basic & generic contact us page. It is expected that most - themes will override this page and replace it with a more detailed - version. - --> - <map:match pattern="contact"> - <map:transform type="Contact"/> - <map:serialize type="xml"/> - </map:match> - - - <!-- Not a URL we care about, so just pass it on. --> - <map:serialize type="xml"/> - </map:pipeline> - </map:pipelines> + <!-- Display statistics --> + <map:match pattern="statistics"> + <map:transform type="Statistics" /> + <map:serialize type="xml" /> + </map:match> + + + <!-- restricted resource --> + <map:match pattern="restricted-resource"> + <map:transform type="RestrictedItem" /> + <map:serialize type="xml" /> + </map:match> + + + <!-- Handle specific features --> + <map:match pattern="handle/*/**"> + + <!-- Inform the user that the item they are viewing is a restricted resource --> + <map:match pattern="handle/*/*/restricted-resource"> + <!-- If request copy is enabled it comes here --> + <map:match type="ConfigurationMatcher" pattern="request.item.type"> + <map:act type="SendItemRequestAction"> + <map:transform type="ItemRequestForm"> + <map:parameter name="requesterName" value="{requesterName}" /> + <map:parameter name="requesterEmail" value="{requesterEmail}" /> + <map:parameter name="allFiles" value="{allFiles}" /> + <map:parameter name="message" value="{message}" /> + <map:parameter name="bitstreamId" value="{bitstreamId}" /> + </map:transform> + <map:serialize type="xml" /> + </map:act> + <map:transform type="ItemRequestSent" /> + <map:serialize type="xml" /> + </map:match> + <!-- If request copy is disabled normal flow --> + <map:transform type="RestrictedItem"/> + <map:serialize type="xml"/> + </map:match> + + <!-- Community, Collection, and Item Viewers --> + <map:match pattern="handle/*/*"> + <map:match type="HandleAuthorizedMatcher" pattern="READ"> + <map:match type="HandleTypeMatcher" pattern="community"> + <map:act type="UsageLoggerAction"> + <map:parameter name="type" value="community" /> + <map:parameter name="eventType" value="view" /> + </map:act> + <map:transform type="CommunityViewer" /> + <map:serialize type="xml" /> + </map:match> + <map:match type="HandleTypeMatcher" pattern="collection"> + <map:act type="UsageLoggerAction"> + <map:parameter name="type" value="collection" /> + <map:parameter name="eventType" value="view" /> + </map:act> + <map:transform type="CollectionViewer" /> + <map:serialize type="xml" /> + </map:match> + <map:match type="HandleTypeMatcher" pattern="item"> + <map:act type="UsageLoggerAction"> + <map:parameter name="type" value="item" /> + <map:parameter name="eventType" value="view" /> + </map:act> + <!-- Implement HTTP If-Modified-Since protocol (commonly used by search + - engine crawlers): return 304 NOT MODIFIED status if Item's - last-modified + date is before If-Modified-Since header. - - NOTE: Do NOT do this for interactive + users since it might encourage - browser to cache a view that is only shown + to authenticated users. - ONLY do this when user-agent is a spider (search-engine + crawler robot) - since they should only ever have "anonymous" access. - - + NOTE: Cocoon always automatically sets Last-Modified: header on its - transformed + pages with the current timestamp, which we cannot override. - It won't prevent + a spider's If-Modified-Since from working, though. --> + <map:select type="browser"> + <map:when test="spider"> + <map:select type="IfModifiedSinceSelector"> + <map:when test="true"> + <map:act type="NotModifiedAction" /> + <map:serialize /> + </map:when> + <map:otherwise> + <map:transform type="ItemViewer" /> + <map:serialize type="xml" /> + </map:otherwise> + </map:select> + </map:when> + <map:otherwise> + <map:transform type="ItemViewer" /> + <map:serialize type="xml" /> + </map:otherwise> + </map:select> + </map:match> + </map:match> + + <map:match type="HandleAuthorizedMatcher" pattern="!READ"> + <map:match type="HandleTypeMatcher" pattern="community"> + <map:transform type="RestrictedItem"> + <map:parameter name="header" + value="xmlui.ArtifactBrowser.RestrictedItem.auth_header" /> + <map:parameter name="message" + value="xmlui.ArtifactBrowser.RestrictedItem.auth_message" /> + </map:transform> + <map:serialize type="xml" /> + </map:match> + <map:match type="HandleTypeMatcher" pattern="collection"> + <map:transform type="RestrictedItem"> + <map:parameter name="header" + value="xmlui.ArtifactBrowser.RestrictedItem.auth_header" /> + <map:parameter name="message" + value="xmlui.ArtifactBrowser.RestrictedItem.auth_message" /> + </map:transform> + <map:serialize type="xml" /> + </map:match> + <map:match type="HandleTypeMatcher" pattern="item"> + <!-- <map:match type="ConfigurationMatcher" pattern="request.item.type,logged"> + <map:act type="SendItemRequestAction"> + <map:parameter name="type" value="item" /> + <map:parameter name="eventType" value="view" /> + </map:act> + </map:match>--> + <map:transform type="RestrictedItem"> + <map:parameter name="header" + value="xmlui.ArtifactBrowser.RestrictedItem.auth_header" /> + <map:parameter name="message" + value="xmlui.ArtifactBrowser.RestrictedItem.auth_message" /> + </map:transform> + <map:serialize type="xml" /> + <!-- Implement HTTP If-Modified-Since protocol (commonly used by search + - engine crawlers): return 304 NOT MODIFIED status if Item's - last-modified + date is before If-Modified-Since header. - - NOTE: Do NOT do this for interactive + users since it might encourage - browser to cache a view that is only shown + to authenticated users. - ONLY do this when user-agent is a spider (search-engine + crawler robot) - since they should only ever have "anonymous" access. - - + NOTE: Cocoon always automatically sets Last-Modified: header on its - transformed + pages with the current timestamp, which we cannot override. - It won't prevent + a spider's If-Modified-Since from working, though. --> + <map:select type="browser"> + <map:when test="spider"> + <map:select type="IfModifiedSinceSelector"> + <map:when test="true"> + <map:act type="NotModifiedAction" /> + <map:serialize /> + </map:when> + <map:otherwise> + <map:transform type="ItemViewer" /> + <map:serialize type="xml" /> + </map:otherwise> + </map:select> + </map:when> + <map:otherwise> + <map:transform type="ItemViewer" /> + <map:serialize type="xml" /> + </map:otherwise> + </map:select> + </map:match> + </map:match> + </map:match> + + + </map:match> <!-- End match handle/*/** --> + + + <!-- A simple feedback utility that presents the user with a form to fill + out, the results of which are emailed to the site administrator. --> + <map:match pattern="feedback"> + <map:act type="SendFeedbackAction"> + <map:transform type="FeedbackForm"> + <map:parameter name="comments" value="{comments}" /> + <map:parameter name="email" value="{email}" /> + <map:parameter name="page" value="{page}" /> + </map:transform> + + <map:serialize type="xml" /> + </map:act> + <map:transform type="FeedbackSent" /> + <map:serialize type="xml" /> + </map:match> + + <!-- A request item flow --> + <map:match pattern="itemRequestResponse/*/"> + <map:act type="ItemRequestResponseAction"> + <map:parameter name="token" value="{1}" /> + <map:parameter name="decision" value="{decision}" /> + <map:parameter name="isSent" value="{isSent}" /> + + <map:select type="parameter"> + <map:parameter name="parameter-selector-test" value="{isSent}" /> + <map:when test="true"> + <map:transform type="ItemRequestChangeStatusForm"> + <map:parameter name="token" value="{1}" /> + <map:parameter name="name" value="{name}" /> + <map:parameter name="email" value="{email}" /> + </map:transform> + </map:when> + <map:otherwise> + <map:select type="parameter"> + <map:parameter name="parameter-selector-test" value="{decision}" /> + <map:when test="false"> + <map:transform type="ItemRequestResponseFalseForm"> + <map:parameter name="decision" value="{decision}" /> + </map:transform> + </map:when> + <map:when test="true"> + <map:transform type="ItemRequestResponseTrueForm"> + <map:parameter name="decision" value="{decision}" /> + </map:transform> + </map:when> + <map:otherwise> + <map:transform type="ItemRequestResponseDecisionForm"> + <map:parameter name="decision" value="{decision}" /> + <map:parameter name="title" value="{title}" /> + </map:transform> + </map:otherwise> + </map:select> + </map:otherwise> + </map:select> + <map:serialize type="xml" /> + </map:act> + <map:transform type="ItemRequestStatusChanged" /> + <map:serialize type="xml" /> + </map:match> + <!-- The most basic & generic contact us page. It is expected that most + themes will override this page and replace it with a more detailed version. --> + <map:match pattern="contact"> + <map:transform type="Contact" /> + <map:serialize type="xml" /> + </map:match> + + + <!-- Not a URL we care about, so just pass it on. --> + <map:serialize type="xml" /> + + </map:pipeline> + </map:pipelines> </map:sitemap> diff --git a/dspace-xmlui/src/main/resources/aspects/XMLWorkflow/i18n/messages.xml b/dspace-xmlui/src/main/resources/aspects/XMLWorkflow/i18n/messages.xml index 35919523e70a289e442a607a114a60c0a5ef90a4..e151b45bd93c72d9ccddf2c6c9b85f40d2d2ec09 100644 --- a/dspace-xmlui/src/main/resources/aspects/XMLWorkflow/i18n/messages.xml +++ b/dspace-xmlui/src/main/resources/aspects/XMLWorkflow/i18n/messages.xml @@ -25,7 +25,7 @@ <message key="xmlui.XMLWorkflow.workflow.ClaimAction.info1">Actions you may perform on this task:</message> <message key="xmlui.XMLWorkflow.workflow.ClaimAction.take_help">Assign this task to yourself.</message> <message key="xmlui.XMLWorkflow.workflow.ClaimAction.take_submit">Take task</message> - <message key="xmlui.XMLWorkflow.workflow.ClaimAction.leave_help">Leave this task in the pool for another to take.</message> + <message key="xmlui.XMLWorkflow.workflow.ClaimAction.leave_help">Leave this task in the pool for another user to take.</message> <message key="xmlui.XMLWorkflow.workflow.ClaimAction.leave_submit">Leave task</message> <message key="xmlui.XMLWorkflow.workflow.ClaimAction.back">Back to overview</message> <message key="xmlui.XMLWorkflow.workflow.ClaimAction.title">Accept/Reject Task</message> diff --git a/dspace-xmlui/src/main/webapp/i18n/messages.xml b/dspace-xmlui/src/main/webapp/i18n/messages.xml index 7595cfe0cf9f73445b4d514b626b1abf68acb1a5..318313780d1edb8f1e7a92997097162e49ae7520 100644 --- a/dspace-xmlui/src/main/webapp/i18n/messages.xml +++ b/dspace-xmlui/src/main/webapp/i18n/messages.xml @@ -238,10 +238,6 @@ <message key="xmlui.ArtifactBrowser.FeedbackSent.head">Feedback sent</message> <message key="xmlui.ArtifactBrowser.FeedbackSent.para1">Your comments have been received.</message> - <!-- org.dspace.app.xmlui.artifactbrowser.FrontPageSearch.java --> - <message key="xmlui.ArtifactBrowser.FrontPageSearch.head">Search DSpace</message> - <message key="xmlui.ArtifactBrowser.FrontPageSearch.para1">Enter some text in the box below to search DSpace.</message> - <!-- org.dspace.app.xmlui.artifactbrowser.ItemViewer.java --> <message key="xmlui.ArtifactBrowser.ItemViewer.trail">View Item</message> <message key="xmlui.ArtifactBrowser.ItemViewer.head_parent_collections">This item appears in the following Collection(s)</message> @@ -313,6 +309,78 @@ <message key="xmlui.ItemExportDownloadReader.auth_header">This export archive is restricted.</message> <message key="xmlui.ItemExportDownloadReader.auth_message">The export archive you are attempting to access is a restricted resource and requires credentials to view. Please login below to access the export archive.</message> + + <!-- REQUEST COPY --> + <!-- org.dspace.app.xmlui.artifactbrowser.ItemRequestForm.java --> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.title">Request a copy of the document</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.trail">Request a copy of the document</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.head">Request a copy of the document</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.para1">Enter the following information to request a copy of the document from the responsible person</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.requesterEmail">Your e-mail address</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.requesterEmail_help">This email address is used for sending the document.</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.requesterEmail.error">Address is required</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.message">Message</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.message.error">Message is required</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.files">Files</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.allFiles">All files (of this document) in restricted access.</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.notAllFiles">Only The requested file.</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.requesterName">Name</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.requesterName.error">Name is required</message> + <message key="xmlui.ArtifactBrowser.ItemRequestForm.submit">Request copy</message> + + <!-- org.dspace.app.xmlui.artifactbrowser.ItemRequestSent.java --> + <message key="xmlui.ArtifactBrowser.ItemRequestSent.title">Your request has been sent.</message> + <message key="xmlui.ArtifactBrowser.ItemRequestSent.trail">Your request has been sent.</message> + <message key="xmlui.ArtifactBrowser.ItemRequestSent.head">Your request has been sent.</message> + <message key="xmlui.ArtifactBrowser.ItemRequestSent.para1">Your request has been sent to the author or responsible person.</message> + + <!-- org.dspace.app.xmlui.artifactbrowser.ItemRequestResponseDecisionForm.java --> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.title">Document copy request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.trail">Document copy request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.head">Document copy request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.para1">IF YOU ARE THE AUTHOR (OR AN AUTHOR) OF DOCUMENT "{0}" use the buttons to answer the user's request.</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.para2">This repository will propose an appropriate model reply, which you may edit.</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.send">Send copy</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseDecisionForm.dontSend">Don't send copy</message> + + <!-- org.dspace.app.xmlui.artifactbrowser.ItemRequestResponseTrueForm.java --> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.title">Document copy request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.trail">Document copy request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.head">Document copy request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.para1">This is the text to be sent to the applicant.</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.message">Message</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.subject">Subject</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.mail">Send</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseFalseForm.back">Back</message> + + <!-- org.dspace.app.xmlui.artifactbrowser.ItemRequestResponseFalseForm.java --> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.title">Document copy request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.trail">Document copy request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.head">Document copy request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.para1">This is the text to be sent to the applicant (together with the document).</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.message">Message</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.subject">Subject</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.mail">Send</message> + <message key="xmlui.ArtifactBrowser.ItemRequestResponseTrueForm.back">Back</message> + + <!-- org.dspace.app.xmlui.artifactbrowser.ItemRequestChangeStatusForm.java --> + <message key="xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.title">Change permissions request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.trail">Change permissions request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.head">Change permissions request</message> + <message key="xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.para1">You may use this occasion to reconsider the access restrictions on the document (to avoid having to respond to these requests), if there is no reason to keep it restricted. To do so, after inserting your name and e-mail (for authentication), click the button "Change to Open Access".</message> + <message key="xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.name">Name</message> + <message key="xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.email">E-mail</message> + <message key="xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.name.error">The name is required</message> + <message key="xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.email.error">The e-mail address is required</message> + <message key="xmlui.ArtifactBrowser.ItemRequestChangeStatusForm.changeToOpen">Change to open access</message> + + <!-- org.dspace.app.xmlui.artifactbrowser.ItemRequestResponseFalseForm.java --> + <message key="xmlui.ArtifactBrowser.ItemRequestStatusChanged.title">Request sent</message> + <message key="xmlui.ArtifactBrowser.ItemRequestStatusChanged.trail">Request sent</message> + <message key="xmlui.ArtifactBrowser.ItemRequestStatusChanged.head">Your request to change permissions has been sent</message> + <message key="xmlui.ArtifactBrowser.ItemRequestStatusChanged.para1">Your request has been sent to the administrator</message> + <message key="xmlui.ArtifactBrowser.ItemRequestStatusChanged.para2">Thanks</message> + <!--!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EPerson Aspect @@ -531,7 +599,7 @@ <!-- org.dspace.app.xmlui.Submission.submissions --> <message key="xmlui.Submission.Submissions.title">Submissions & Workflow</message> <message key="xmlui.Submission.Submissions.trail">Submissions</message> - <message key="xmlui.Submission.Submissions.head">Submissions & Workflow Tasks</message> + <message key="xmlui.Submission.Submissions.head">Submissions & Workflow tasks</message> <message key="xmlui.Submission.Submissions.untitled"><i>Untitled</i></message> <message key="xmlui.Submission.Submissions.email">email: </message> <!-- Same transformer, workflow section --> @@ -657,20 +725,26 @@ <!-- org.dspace.app.xmlui.Submission.submit.AccessStep --> <message key="xmlui.Submission.submit.AccessStep.head">Access Settings</message> <message key="xmlui.Submission.submit.AccessStep.access_settings">Visible to a group of selected users (no selection needed for Anonymous)</message> - <message key="xmlui.Submission.submit.AccessStep.open_access">Item will be visible once accepted into archive</message> - <message key="xmlui.Submission.submit.AccessStep.embargo">Embargo Access until Specific Date</message> - <message key="xmlui.Submission.submit.AccessStep.embargo_visible">Visible/Embargoed</message> - <message key="xmlui.Submission.submit.AccessStep.name">Name</message> + <message key="xmlui.Submission.submit.AccessStep.open_access">Allow access once item is accepted into archive</message> + <message key="xmlui.Submission.submit.AccessStep.embargo">Embargo until specific date</message> + <message key="xmlui.Submission.submit.AccessStep.embargo_visible">Access for selected group</message> + <message key="xmlui.Submission.submit.AccessStep.name">Policy name</message> + <message key="xmlui.Submission.submit.AccessStep.name_help">A short, descriptive name for the policy (up to 30 characters). May be shown to end users. Example: "Staff-only". Optional but recommended.</message> <message key="xmlui.Submission.submit.AccessStep.description">Description</message> - <message key="xmlui.Submission.submit.AccessStep.reason">Reason</message> + <message key="xmlui.Submission.submit.AccessStep.reason">Embargo reason</message> + <message key="xmlui.Submission.submit.AccessStep.reason_help">The reason for the embargo, typically for internal use only. Optional.</message> <message key="xmlui.Submission.submit.AccessStep.submit_add_policy">Confirm Policy & add another</message> - <message key="xmlui.Submission.submit.AccessStep.list_assigned_groups">Groups</message> + <message key="xmlui.Submission.submit.AccessStep.list_assigned_groups">Group</message> <message key="xmlui.Submission.submit.AccessStep.error_format_date">Error format date</message> <message key="xmlui.Submission.submit.AccessStep.error_missing_date">When Embargo selected, date is required</message> <message key="xmlui.Submission.submit.AccessStep.error_duplicated_policy">An identical policy for this group and this action is already in place.</message> - <message key="xmlui.Submission.submit.AccessStep.table_policies">Policies List</message> - <message key="xmlui.Submission.submit.AccessStep.private_settings">Private Item</message> + <message key="xmlui.Submission.submit.AccessStep.table_policies">Group policies</message> + <message key="xmlui.Submission.submit.AccessStep.policies_help">Policies listed in this section override any default policies for the collection you're submitting to. If you wish to set an embargo but the target collection allows access for any user, you must set a policy that allows access for the Anonymous group only from a specific date onwards.</message> + <message key="xmlui.Submission.submit.AccessStep.no_policies">No group policies have been set up for this item.</message> + <message key="xmlui.Submission.submit.AccessStep.new_policy_head">Embargo</message> + <message key="xmlui.Submission.submit.AccessStep.private_settings">Private item</message> <message key="xmlui.Submission.submit.AccessStep.private_settings_help">If selected, the item won't be searchable</message> + <message key="xmlui.Submission.submit.AccessStep.private_settings_label">Private</message> <message key="xmlui.Submission.submit.AccessStep.column0">Name</message> <message key="xmlui.Submission.submit.AccessStep.column1">Action</message> <message key="xmlui.Submission.submit.AccessStep.column2">Group</message> @@ -678,7 +752,11 @@ <message key="xmlui.Submission.submit.AccessStep.column4">End Date</message> <message key="xmlui.Submission.submit.AccessStep.table_edit_button">Edit</message> <message key="xmlui.Submission.submit.AccessStep.table_delete_button">Remove</message> - <message key="xmlui.administrative.authorization.AccessStep.label_date_help">Accepted format: yyyy, yyyy-mm, yyyy-mm-dd</message> + <message key="xmlui.administrative.authorization.AccessStep.label_date_help">The first day from which access is allowed. Accepted format: yyyy, yyyy-mm, yyyy-mm-dd</message> + <message key="xmlui.Submission.submit.AccessStep.review_policy_line">Name: {0}; action: {1}, group: {2}, start date: {3}, end date: {4}</message> + <message key="xmlui.Submission.submit.AccessStep.review_public_item">The item will be searchable</message> + <message key="xmlui.Submission.submit.AccessStep.review_private_item">The item will not be searchable</message> + <!-- org.dspace.app.xmlui.Submission.submit.EditPolicyStep --> @@ -757,7 +835,7 @@ <message key="xmlui.Submission.submit.EditFileStep.format_user_help">The application's name you used to create the file, and the version number (for example, "<i>ACMESoft SuperApp version 1.5</i>").</message> <!-- org.dspace.app.xmlui.Submission.submit.EditBitstreamPolicies --> - <message key="xmlui.Submission.submit.EditBitstreamPolicies.head">Edit Bitstream Access</message> + <message key="xmlui.Submission.submit.EditBitstreamPolicies.head">Bitstream Access</message> <!-- org.dspace.app.xmlui.Submission.submit.ReviewStep --> @@ -811,7 +889,7 @@ <message key="xmlui.Submission.workflow.PerformTaskStep.info1">Actions you may perform on this task:</message> <message key="xmlui.Submission.workflow.PerformTaskStep.take_help">Assign this task to yourself.</message> <message key="xmlui.Submission.workflow.PerformTaskStep.take_submit">Take task</message> - <message key="xmlui.Submission.workflow.PerformTaskStep.leave_help">Leave this task in the pool for another to take.</message> + <message key="xmlui.Submission.workflow.PerformTaskStep.leave_help">Leave this task in the pool for another user to take.</message> <message key="xmlui.Submission.workflow.PerformTaskStep.leave_submit">Leave task</message> <message key="xmlui.Submission.workflow.PerformTaskStep.approve_help">If you have reviewed the item and it is suitable for inclusion in the collection, select "Approve".</message> <message key="xmlui.Submission.workflow.PerformTaskStep.approve_submit">Approve item</message> @@ -1293,7 +1371,7 @@ <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.title">Advanced Policy Manager</message> <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.trail">Advanced Authorizations</message> <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.main_head">Advanced Policy Manager</message> - <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.main_para">Allows wildcard additions to and clearing of policies for types of content within specific collection(s). WARNING - removing READ permissions from items will make them not viewable!</message> + <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.main_para">Allows wildcard additions to and clearing of policies for items or bitstreams within specific collection(s). WARNING - removing READ permissions from items will make them not viewable!</message> <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_groupSentence">For all of the selected groups...</message> <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_actionSentence">...grant the ability to perform the following action...</message> <message key="xmlui.administrative.authorization.AdvacedAuthorizationsForm.actions_resourceSentence">...for all following object types...</message> @@ -1992,7 +2070,7 @@ <message key="xmlui.dri2xhtml.structural.contact-link">Contact Us</message> <message key="xmlui.dri2xhtml.structural.feedback-link">Send Feedback</message> - <message key="xmlui.dri2xhtml.structural.head-subtitle">DSpace/Manakin Repository</message> + <message key="xmlui.dri2xhtml.structural.head-subtitle">DSpace Repository</message> <message key="xmlui.dri2xhtml.structural.profile">Profile: </message> <message key="xmlui.dri2xhtml.structural.logout">Logout</message> @@ -2042,6 +2120,7 @@ <message key="xmlui.dri2xhtml.METS-1.0.item-files-view">View</message> <message key="xmlui.dri2xhtml.METS-1.0.item-files-description">Description</message> <message key="xmlui.dri2xhtml.METS-1.0.item-files-viewOpen">View/<wbr/>Open</message> + <message key="xmlui.dri2xhtml.METS-1.0.item-files-access-rights">Read access available for</message> <message key="xmlui.dri2xhtml.METS-1.0.item-no-files">There are no files associated with this item.</message> <message key="xmlui.dri2xhtml.METS-1.0.size-bytes">bytes</message> @@ -2077,6 +2156,8 @@ <message key="xmlui.dri2xhtml.METS-1.0.header-qdc-elements">Dublin Core elements</message> <message key="xmlui.dri2xhtml.METS-1.0.header-qdc-terms">Dublin Core terms</message> + <message key="xmlui.dri2xhtml.METS-1.0.blocked">Blocked</message> + <!-- Special pioneer model related text, wherever it might end up --> <message key="xmlui.dri2xhtml.pioneer.preview">Preview</message> diff --git a/dspace-xmlui/src/main/webapp/sitemap.xmap b/dspace-xmlui/src/main/webapp/sitemap.xmap index 963e292edad3dba3df4f63f5c6d0fe6d3f07a620..86f7de639c6b07cccaaf2e0d56216d7315b48298 100644 --- a/dspace-xmlui/src/main/webapp/sitemap.xmap +++ b/dspace-xmlui/src/main/webapp/sitemap.xmap @@ -199,6 +199,8 @@ <map:reader name="ConcatenationReader" src="org.dspace.app.xmlui.cocoon.ConcatenationReader"/> <map:reader name="JQueryLoaderReader" src="org.dspace.app.xmlui.utils.JQueryLoaderReader"/> <map:reader name="JSONControlledVocabularyReader" src="org.dspace.app.xmlui.cocoon.JSONControlledVocabularyReader"/> + + <map:reader name="HandleResolverReader" src="org.dspace.app.xmlui.aspect.handle.HandleResolverReader"/> </map:readers> <map:actions> <map:action name="locale" src="org.dspace.app.xmlui.cocoon.DSpaceLocaleAction"/> @@ -645,7 +647,33 @@ </map:match> </map:pipeline> + + <!-- pipline to run external handle server --> + <map:pipeline type="noncaching"> + <map:match pattern="handleresolver/resolve/**"> + <map:read type="HandleResolverReader"> + <map:parameter name="action" value="resolve"/> + <map:parameter name="handle" value="{1}"/> + </map:read> + </map:match> + + <!--Redirect /handleresolver/listprefixes/ to the same path but without a trailing slash--> + <map:match pattern="handleresolver/listprefixes/"> + <map:redirect-to uri="{request:contextPath}/handleresolver/listprefixes" permanent="yes"/> + </map:match> + <map:match pattern="handleresolver/listprefixes"> + <map:read type="HandleResolverReader"> + <map:parameter name="action" value="listprefixes"/> + </map:read> + </map:match> + <map:match pattern="handleresolver/listhandles/*"> + <map:read type="HandleResolverReader"> + <map:parameter name="action" value="listhandles"/> + <map:parameter name="prefix" value="{1}"/> + </map:read> + </map:match> + </map:pipeline> <map:pipeline> <!--<map:match pattern="**">--> diff --git a/dspace-xmlui/src/main/webapp/static/js/discovery/discovery-results.js b/dspace-xmlui/src/main/webapp/static/js/discovery/discovery-results.js index f47584ebe0bc947444c6ac0da36a1b0875f4d832..6ccbad01096235ca4e3d23234adfe5328aa32aa2 100644 --- a/dspace-xmlui/src/main/webapp/static/js/discovery/discovery-results.js +++ b/dspace-xmlui/src/main/webapp/static/js/discovery/discovery-results.js @@ -19,10 +19,9 @@ //Instead of redirecting us to the page, first send us to the statistics logger //By doing this we ensure that we register the query to the result var form = $('form#aspect_discovery_SimpleSearch_div_main-form'); - form.attr('action', form.attr('action').replace('/discover', '') + '/dso-display'); + form.attr('action', $this.attr('href')); //Manipulate the fq boxes to all switch to query since the logging doesn't take into account filter queries form.find('input[name="fq"]').attr('name', 'query'); - form.find('input[name="redirectUrl"]').val($this.attr('href')); form.submit(); return false; }); diff --git a/dspace-xmlui/src/main/webapp/static/js/discovery/search-controls.js b/dspace-xmlui/src/main/webapp/static/js/discovery/search-controls.js index 574d18a40e8ab2e7558b836f5dcfc5a322130007..31458564e0bbcc065ac30057ae1601c3940821a9 100644 --- a/dspace-xmlui/src/main/webapp/static/js/discovery/search-controls.js +++ b/dspace-xmlui/src/main/webapp/static/js/discovery/search-controls.js @@ -119,7 +119,7 @@ //Hide ourselves & clear our values! parentRow.find('input[type=text]", select').val(''); }else{ - if(parentRow.parents('table:first').find('tr[id^="aspect_discovery_SimpleSearch_row_used-filters-"]').length == 1) + if(parentRow.is('[id^="aspect_discovery_SimpleSearch_row_used-filters-"]') && parentRow.parents('table:first').find('tr[id^="aspect_discovery_SimpleSearch_row_used-filters-"]').length == 1) { parentRow.next().remove(); parentRow.prev().remove(); diff --git a/dspace-xmlui/src/main/webapp/static/js/search-results.js b/dspace-xmlui/src/main/webapp/static/js/search-results.js index 3443c0736b556f6413b71eade405f06961039e77..1f502344e874eec2c00140f3b9ff257ff29c93c9 100644 --- a/dspace-xmlui/src/main/webapp/static/js/search-results.js +++ b/dspace-xmlui/src/main/webapp/static/js/search-results.js @@ -22,7 +22,7 @@ //Instead of redirecting us to the page, first send us to the statistics logger //By doing this we ensure that we register the query to the result var form = $('form#aspect_statistics_StatisticsSearchResultTransformer_div_dso-display'); - form.find('input[name="redirectUrl"]').val($this.attr('href')); + form.attr('action', $this.attr('href')); form.submit(); return false; }); diff --git a/dspace-xmlui/src/main/webapp/themes/Classic/lib/style.css b/dspace-xmlui/src/main/webapp/themes/Classic/lib/style.css index 0708f7bc6c66637e37a67c309043e67249025fa8..4c600731613fa365fd1ff5fd63a28ff47f5c85a4 100644 --- a/dspace-xmlui/src/main/webapp/themes/Classic/lib/style.css +++ b/dspace-xmlui/src/main/webapp/themes/Classic/lib/style.css @@ -1003,3 +1003,11 @@ div#aspect_discovery_SimpleSearch_div_search a.previous-page-link { } /* End discovery layout DSpace 3.x*/ + +.didYouMean{ + font-size: 18px; +} + +.didYouMean a{ + font-weight: bold; +} \ No newline at end of file diff --git a/dspace-xmlui/src/main/webapp/themes/Kubrick/lib/css/style-ie7.css b/dspace-xmlui/src/main/webapp/themes/Kubrick/lib/css/style-ie7.css index 3b543e3cb3ddac7f461820a2bccc96a604832ce3..4d2030217e86cd5928bbac01c949255acfcc211b 100644 --- a/dspace-xmlui/src/main/webapp/themes/Kubrick/lib/css/style-ie7.css +++ b/dspace-xmlui/src/main/webapp/themes/Kubrick/lib/css/style-ie7.css @@ -20,7 +20,7 @@ top: -40px; left: -12px; } -#ds-header h2, +#ds-header h2 { margin:0pt; padding-top:81px; @@ -132,4 +132,4 @@ fieldset#aspect_submission_StepTransformer_field_published_before #footer { line-height: 1; -} \ No newline at end of file +} diff --git a/dspace-xmlui/src/main/webapp/themes/Kubrick/lib/css/style.css b/dspace-xmlui/src/main/webapp/themes/Kubrick/lib/css/style.css index 5ffe578a26cfb76ada13519e61504004fad6a05e..48c7ebf883c4aaba5bb7c1e10c1bdbd3eb776504 100644 --- a/dspace-xmlui/src/main/webapp/themes/Kubrick/lib/css/style.css +++ b/dspace-xmlui/src/main/webapp/themes/Kubrick/lib/css/style.css @@ -927,7 +927,7 @@ ul.ds-progress-list #aspect_submission_StepTransformer_field_submit_jump_6_1 } /* The next few entries were motivated by the item submission pages. If undesirable changes are produced elsewhere, let's use the id instead of the fieldset tag name and class ds-form-list.thick to apply these entries*/ -fieldset.ds-form-list.thick .ds-composite-component.last, +fieldset.ds-form-list.thick .ds-composite-component.last { display: block; } @@ -1983,3 +1983,7 @@ background-color: rgb(255, 255, 255); margin: 2px 2px 0px 2px; /* border: 1px solid rgb(240, 240, 210); */ } + +#ds-language-selection { +text-align: right; +} diff --git a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/css/authority-control.css b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/css/authority-control.css index a02734f2ab9912f1cfd1f6419456d21f1e4def57..7ce4b88df2c8467e3763f8572836e72812c66d6b 100644 --- a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/css/authority-control.css +++ b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/css/authority-control.css @@ -80,9 +80,4 @@ input.ds-authority-lock.is-locked input.ds-authority-lock.is-unlocked { background-image: url(../../images/authority_control/unlock24.png); } - -/* Example of authority display: this makes authors with an authority - value show up as red in the item summary view: */ -span.ds-dc_contributor_author-authority { color: #982521; } - #aspect_general_ChoiceLookupTransformer_div_lookup select {height: auto;} diff --git a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/css/style.css b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/css/style.css index da43c9284d7c43c19f6a839ec5b98357a5364544..b9c4b2ceaea4e5c064048047dcbbdcdb6bedf69d 100644 --- a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/css/style.css +++ b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/css/style.css @@ -78,12 +78,19 @@ select.multiple { #ds-user-box { right: 0; - top: 10px; + top: 17px; position: absolute; color: white; } -#ds-user-box a{ +#ds-language-selection { + right: 0; + top: 40px; + position: absolute; + color: white; +} + +#ds-user-box a, #ds-language-selection a { color: white; } @@ -1373,3 +1380,16 @@ table.discovery-filters th.new-filter-header .searchTime{ color: #999999; } + +.didYouMean{ + font-size: 18px; +} + +.didYouMean a{ + font-weight: bold; +} + +.recentSubmissionViewMore { + text-align: right; + font-size: 100%; +} diff --git a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/aspect/artifactbrowser/item-list.xsl b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/aspect/artifactbrowser/item-list.xsl index d39d4485234b4f5bcd6728713f17dc3baf48c002..4efbc00705c158cf27ded105fd39541d9083a132 100644 --- a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/aspect/artifactbrowser/item-list.xsl +++ b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/aspect/artifactbrowser/item-list.xsl @@ -84,7 +84,7 @@ <xsl:value-of select="$href"/> </xsl:attribute> <xsl:choose> - <xsl:when test="dim:field[@element='title']"> + <xsl:when test="dim:field[@element='title' and descendant::text()]"> <xsl:value-of select="dim:field[@element='title'][1]/node()"/> </xsl:when> <xsl:otherwise> @@ -158,7 +158,7 @@ <xsl:value-of select="$href"/> </xsl:attribute> <xsl:choose> - <xsl:when test="dim:field[@element='title']"> + <xsl:when test="dim:field[@element='title' and descendant::text()]"> <xsl:value-of select="dim:field[@element='title'][1]/node()"/> </xsl:when> <xsl:otherwise> @@ -243,7 +243,7 @@ <xsl:template match="mets:fileSec" mode="artifact-preview"> <xsl:param name="href"/> - <div class="thumbnail-wrapper"> + <div class="thumbnail-wrapper" style="width: {$thumbnail.maxwidth}px;"> <div class="artifact-preview"> <a class="image-link" href="{$href}"> <xsl:choose> diff --git a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/aspect/artifactbrowser/item-view.xsl b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/aspect/artifactbrowser/item-view.xsl index 36fe11641265c6655f97217014ed890adb69d1ea..55d437b8742bbc26da52634ada7d88f7385f6a8a 100644 --- a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/aspect/artifactbrowser/item-view.xsl +++ b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/aspect/artifactbrowser/item-view.xsl @@ -104,7 +104,7 @@ <xsl:when test="$clause = 1"> <xsl:choose> - <xsl:when test="count(dim:field[@element='title'][not(@qualifier)]) > 1"> + <xsl:when test="descendant::text() and (count(dim:field[@element='title'][not(@qualifier)]) > 1)"> <!-- display first title as h1 --> <h1> <xsl:value-of select="dim:field[@element='title'][not(@qualifier)][1]/node()"/> @@ -122,7 +122,7 @@ </span> </div> </xsl:when> - <xsl:when test="count(dim:field[@element='title'][not(@qualifier)]) = 1"> + <xsl:when test="dim:field[@element='title'][descendant::text()] and count(dim:field[@element='title'][not(@qualifier)]) = 1"> <h1> <xsl:value-of select="dim:field[@element='title'][not(@qualifier)][1]/node()"/> </h1> @@ -140,7 +140,7 @@ </xsl:when> <!-- Author(s) row --> - <xsl:when test="$clause = 2 and (dim:field[@element='contributor'][@qualifier='author'] or dim:field[@element='creator'] or dim:field[@element='contributor'])"> + <xsl:when test="$clause = 2 and (dim:field[@element='contributor'][@qualifier='author' and descendant::text()] or dim:field[@element='creator' and descendant::text()] or dim:field[@element='contributor' and descendant::text()])"> <div class="simple-item-view-authors"> <xsl:choose> <xsl:when test="dim:field[@element='contributor'][@qualifier='author']"> @@ -184,7 +184,7 @@ </xsl:when> <!-- identifier.uri row --> - <xsl:when test="$clause = 3 and (dim:field[@element='identifier' and @qualifier='uri'])"> + <xsl:when test="$clause = 3 and (dim:field[@element='identifier' and @qualifier='uri' and descendant::text()])"> <div class="simple-item-view-other"> <span class="bold"><i18n:text>xmlui.dri2xhtml.METS-1.0.item-uri</i18n:text>:</span> <span> @@ -208,7 +208,7 @@ </xsl:when> <!-- date.issued row --> - <xsl:when test="$clause = 4 and (dim:field[@element='date' and @qualifier='issued'])"> + <xsl:when test="$clause = 4 and (dim:field[@element='date' and @qualifier='issued' and descendant::text()])"> <div class="simple-item-view-other"> <span class="bold"><i18n:text>xmlui.dri2xhtml.METS-1.0.item-date</i18n:text>:</span> <span> @@ -259,7 +259,7 @@ </xsl:when> <!-- Description row --> - <xsl:when test="$clause = 6 and (dim:field[@element='description' and not(@qualifier)])"> + <xsl:when test="$clause = 6 and (dim:field[@element='description' and not(@qualifier) and descendant::text()])"> <div class="simple-item-view-description"> <h3 class="bold"><i18n:text>xmlui.dri2xhtml.METS-1.0.item-description</i18n:text>:</h3> <div> @@ -388,7 +388,7 @@ <xsl:template match="mets:file"> <xsl:param name="context" select="."/> <div class="file-wrapper clearfix"> - <div class="thumbnail-wrapper"> + <div class="thumbnail-wrapper" style="width: {$thumbnail.maxwidth}px;"> <a class="image-link"> <xsl:attribute name="href"> <xsl:value-of select="mets:FLocat[@LOCTYPE='URL']/@xlink:href"/> @@ -407,6 +407,16 @@ <img alt="Icon" src="{concat($theme-path, '/images/mime.png')}" style="height: {$thumbnail.maxheight}px;"/> </xsl:otherwise> </xsl:choose> + <xsl:if test="contains(mets:FLocat[@LOCTYPE='URL']/@xlink:href,'isAllowed=n')"> + <img> + <xsl:attribute name="src"> + <xsl:value-of select="$context-path"/> + <xsl:text>/static/icons/lock24.png</xsl:text> + </xsl:attribute> + <xsl:attribute name="alt">xmlui.dri2xhtml.METS-1.0.blocked</xsl:attribute> + <xsl:attribute name="attr" namespace="http://apache.org/cocoon/i18n/2.1">alt</xsl:attribute> + </img> + </xsl:if> </a> </div> <div class="file-metadata" style="height: {$thumbnail.maxheight}px;"> @@ -509,24 +519,35 @@ <xsl:variable name="rights_declaration" select="../../../mets:amdSec/mets:rightsMD[@ID = concat('rightsMD_', $file_id, '_METSRIGHTS')]/mets:mdWrap/mets:xmlData/rights:RightsDeclarationMD"/> <xsl:variable name="rights_context" select="$rights_declaration/rights:Context"/> <xsl:variable name="users"> - <xsl:for-each select="$rights_declaration/*"> - <xsl:value-of select="rights:UserName"/> - <xsl:choose> - <xsl:when test="rights:UserName/@USERTYPE = 'GROUP'"> - <xsl:text> (group)</xsl:text> - </xsl:when> - <xsl:when test="rights:UserName/@USERTYPE = 'INDIVIDUAL'"> - <xsl:text> (individual)</xsl:text> - </xsl:when> - </xsl:choose> - <xsl:if test="position() != last()">, </xsl:if> - </xsl:for-each> + <xsl:choose> + <xsl:when test="not ($rights_context)"> + <xsl:text>administrators only</xsl:text> + </xsl:when> + <xsl:otherwise> + <xsl:for-each select="$rights_declaration/*"> + <xsl:value-of select="rights:UserName"/> + <xsl:choose> + <xsl:when test="rights:UserName/@USERTYPE = 'GROUP'"> + <xsl:text> (group)</xsl:text> + </xsl:when> + <xsl:when test="rights:UserName/@USERTYPE = 'INDIVIDUAL'"> + <xsl:text> (individual)</xsl:text> + </xsl:when> + </xsl:choose> + <xsl:if test="position() != last()">, </xsl:if> <!-- TODO fix ending comma --> + </xsl:for-each> + </xsl:otherwise> + </xsl:choose> </xsl:variable> + <xsl:variable name="alt-text"><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-access-rights</i18n:text> <xsl:value-of select="$users"/></xsl:variable> <xsl:choose> - <xsl:when test="not ($rights_context/@CONTEXTCLASS = 'GENERAL PUBLIC') and ($rights_context/rights:Permissions/@DISPLAY = 'true')"> + <xsl:when test="(not ($rights_context/@CONTEXTCLASS = 'GENERAL PUBLIC') and ($rights_context/rights:Permissions/@DISPLAY = 'true')) or not ($rights_context)"> <a href="{mets:FLocat[@LOCTYPE='URL']/@xlink:href}"> - <img width="64" height="64" src="{concat($theme-path,'/images/Crystal_Clear_action_lock3_64px.png')}" title="Read access available for {$users}"/> + <img width="64" height="64" src="{concat($theme-path,'/images/Crystal_Clear_action_lock3_64px.png')}"> + <xsl:attribute name="title"><xsl:value-of select="$alt-text"/></xsl:attribute> + <xsl:attribute name="alt"><xsl:value-of select="$alt-text"/></xsl:attribute> + </img> <!-- icon source: http://commons.wikimedia.org/wiki/File:Crystal_Clear_action_lock3.png --> </a> </xsl:when> diff --git a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/core/page-structure.xsl b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/core/page-structure.xsl index fb9c3eb8e09cbb61e82cae4f1589da57b17fa9c4..d96844eaa36a0bfde1f9db5ac4c7536fea7383a2 100644 --- a/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/core/page-structure.xsl +++ b/dspace-xmlui/src/main/webapp/themes/Mirage/lib/xsl/core/page-structure.xsl @@ -167,7 +167,7 @@ </xsl:if> </xsl:attribute> </meta> - <!-- Add stylsheets --> + <!-- Add stylesheets --> <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='stylesheet']"> <link rel="stylesheet" type="text/css"> <xsl:attribute name="media"> @@ -289,7 +289,10 @@ <xsl:text>About This Repository</xsl:text> </xsl:when> <xsl:when test="not($page_title)"> - <xsl:text> </xsl:text> + <i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text> + </xsl:when> + <xsl:when test="$page_title = ''"> + <i18n:text>xmlui.dri2xhtml.METS-1.0.no-title</i18n:text> </xsl:when> <xsl:otherwise> <xsl:copy-of select="$page_title/node()" /> @@ -324,7 +327,9 @@ <xsl:text>/</xsl:text> </xsl:attribute> <span id="ds-header-logo"> </span> - <span id="ds-header-logo-text">mirage</span> + <span id="ds-header-logo-text"> + <i18n:text>xmlui.dri2xhtml.structural.head-subtitle</i18n:text> + </span> </a> <h1 class="pagetitle visuallyhidden"> <xsl:choose> @@ -339,10 +344,6 @@ </xsl:choose> </h1> - <h2 class="static-pagetitle visuallyhidden"> - <i18n:text>xmlui.dri2xhtml.structural.head-subtitle</i18n:text> - </h2> - <xsl:choose> <xsl:when test="/dri:document/dri:meta/dri:userMeta/@authenticated = 'yes'"> @@ -385,12 +386,13 @@ </div> </xsl:otherwise> </xsl:choose> - + + <xsl:call-template name="languageSelection" /> + </div> </div> </xsl:template> - <!-- The header (distinct from the HTML head element) contains the title, subtitle, login box and various placeholders for header images --> <xsl:template name="buildTrail"> @@ -483,17 +485,10 @@ alt="{$ccLicenseName}" title="{$ccLicenseName}" > - <img> - <xsl:attribute name="src"> - <xsl:value-of select="concat($theme-path,'/images/cc-ship.gif')"/> - </xsl:attribute> - <xsl:attribute name="alt"> - <xsl:value-of select="$ccLicenseName"/> - </xsl:attribute> - <xsl:attribute name="style"> - <xsl:text>float:left; margin:0em 1em 0em 0em; border:none;</xsl:text> - </xsl:attribute> - </img> + <xsl:call-template name="cc-logo"> + <xsl:with-param name="ccLicenseName" select="$ccLicenseName"/> + <xsl:with-param name="ccLicenseUri" select="$ccLicenseUri"/> + </xsl:call-template> </a> <span> <xsl:attribute name="style"> @@ -506,6 +501,66 @@ </xsl:if> </xsl:template> + <xsl:template name="cc-logo"> + <xsl:param name="ccLicenseName"/> + <xsl:param name="ccLicenseUri"/> + <xsl:variable name="ccLogo"> + <xsl:choose> + <xsl:when test="starts-with($ccLicenseUri, + 'http://creativecommons.org/licenses/by/')"> + <xsl:value-of select="'cc-by.png'" /> + </xsl:when> + <xsl:when test="starts-with($ccLicenseUri, + 'http://creativecommons.org/licenses/by-sa/')"> + <xsl:value-of select="'cc-by-sa.png'" /> + </xsl:when> + <xsl:when test="starts-with($ccLicenseUri, + 'http://creativecommons.org/licenses/by-nd/')"> + <xsl:value-of select="'cc-by-nd.png'" /> + </xsl:when> + <xsl:when test="starts-with($ccLicenseUri, + 'http://creativecommons.org/licenses/by-nc/')"> + <xsl:value-of select="'cc-by-nc.png'" /> + </xsl:when> + <xsl:when test="starts-with($ccLicenseUri, + 'http://creativecommons.org/licenses/by-nc-sa/')"> + <xsl:value-of select="'cc-by-nc-sa.png'" /> + </xsl:when> + <xsl:when test="starts-with($ccLicenseUri, + 'http://creativecommons.org/licenses/by-nc-nd/')"> + <xsl:value-of select="'cc-by-nc-nd.png'" /> + </xsl:when> + <xsl:when test="starts-with($ccLicenseUri, + 'http://creativecommons.org/publicdomain/zero/')"> + <xsl:value-of select="'cc-zero.png'" /> + </xsl:when> + <xsl:when test="starts-with($ccLicenseUri, + 'http://creativecommons.org/publicdomain/mark/')"> + <xsl:value-of select="'cc-mark.png'" /> + </xsl:when> + <xsl:otherwise> + <xsl:value-of select="'cc-generic.png'" /> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + <xsl:variable name="ccLogoImgSrc"> + <xsl:value-of select="$theme-path"/> + <xsl:text>/images/creativecommons/</xsl:text> + <xsl:value-of select="$ccLogo"/> + </xsl:variable> + <img> + <xsl:attribute name="src"> + <xsl:value-of select="$ccLogoImgSrc"/> + </xsl:attribute> + <xsl:attribute name="alt"> + <xsl:value-of select="$ccLicenseName"/> + </xsl:attribute> + <xsl:attribute name="style"> + <xsl:text>float:left; margin:0em 1em 0em 0em; border:none;</xsl:text> + </xsl:attribute> + </img> + </xsl:template> + <!-- Like the header, the footer contains various miscellaneous text, links, and image placeholders --> <xsl:template name="buildFooter"> <div id="ds-footer-wrapper"> diff --git a/dspace-xmlui/src/main/webapp/themes/Reference/lib/style.css b/dspace-xmlui/src/main/webapp/themes/Reference/lib/style.css index e9b80193cb8b8e56c961003c5556bb9f922511ad..dbf9c126ea5eda0c120523423624d21f20aa6406 100644 --- a/dspace-xmlui/src/main/webapp/themes/Reference/lib/style.css +++ b/dspace-xmlui/src/main/webapp/themes/Reference/lib/style.css @@ -1235,11 +1235,6 @@ input.ds-authority-lock.is-locked input.ds-authority-lock.is-unlocked { background-image: url(../images/unlock24.png); } - -/* Example of authority display: this makes authors with an authority - value show up as red in the item summary view: */ -span.ds-dc_contributor_author-authority { color: #982521; } - /* Prevent display of COinS span - nonspacing break in span to fix closing tag also causes a newline in some browsers */ span.Z3988 { @@ -1454,4 +1449,12 @@ ul.vocabulary div.vocabulary-node-icon.vocabulary-closed{ div.vocabulary-container li.error{ color: #c22121; } -/* Controlled vocabulary support css END*/ \ No newline at end of file +/* Controlled vocabulary support css END*/ + +.didYouMean{ + font-size: 18px; +} + +.didYouMean a{ + font-weight: bold; +} \ No newline at end of file diff --git a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/COinS.xsl b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/COinS.xsl index cd20fd19cf0395ac9ebb9a89147d89d9c1235560..13b8f3aafe34831e566c641fc35df33f8209e8e2 100644 --- a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/COinS.xsl +++ b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/COinS.xsl @@ -65,12 +65,12 @@ <xsl:text>ctx_ver=Z39.88-2004&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&</xsl:text> <xsl:for-each select=".//dim:field[@element = 'identifier']"> <xsl:text>rft_id=</xsl:text> - <xsl:value-of select="encoder:encode(string(.))"/> + <xsl:value-of select="encoder:encode(string(.), 'UTF-8')"/> <xsl:text>&</xsl:text> </xsl:for-each> <xsl:text>rfr_id=info%3Asid%2Fdspace.org%3Arepository&</xsl:text> <xsl:for-each select=".//dim:field[@element != 'description' and @mdschema !='dc' and @qualifier != 'provenance']"> - <xsl:value-of select="concat('rft.', @element,'=',encoder:encode(string(.))) "/> + <xsl:value-of select="concat('rft.', @element,'=',encoder:encode(string(.), 'UTF-8')) "/> <xsl:if test="position()!=last()"> <xsl:text>&</xsl:text> </xsl:if> diff --git a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/collection-view.xsl b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/collection-view.xsl index 271e218eb6f88d812c800f5b2ac7abae33edb189..00c8f1a7e765035ba6e9536fdcb01c96afb1e342 100644 --- a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/collection-view.xsl +++ b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/collection-view.xsl @@ -69,11 +69,9 @@ <xsl:if test="string-length(dim:field[@element='rights'][not(@qualifier)])>0"> <div class="detail-view-rights-and-license"> - <xsl:if test="string-length(dim:field[@element='rights'][not(@qualifier)])>0"> - <p class="copyright-text"> - <xsl:copy-of select="dim:field[@element='rights'][not(@qualifier)]/node()"/> - </p> - </xsl:if> + <p class="copyright-text"> + <xsl:copy-of select="dim:field[@element='rights'][not(@qualifier)]/node()"/> + </p> </div> </xsl:if> </xsl:template> diff --git a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/discovery.xsl b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/discovery.xsl index d5437fd8708f95db05805506c8ecf41104d77bc8..f462e1550c956d557c52e828366bcf5c17b7757f 100644 --- a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/discovery.xsl +++ b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/discovery.xsl @@ -22,8 +22,8 @@ <xsl:output indent="yes"/> <!-- - These templaes are devoted to rendering the search results for discovery. - Since discovery used hit highlighting seperate templates are required ! + These templates are devoted to rendering the search results for Discovery. + Since Discovery uses hit highlighting separate templates are required ! --> @@ -119,7 +119,7 @@ <div class="artifact-title"> <a href="{$metsDoc/mets:METS/@OBJID}"> <xsl:choose> - <xsl:when test="dri:list[@n=(concat($handle, ':dc.title'))]"> + <xsl:when test="dri:list[@n=(concat($handle, ':dc.title')) and descendant::text()]"> <xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.title'))]/dri:item"/> </xsl:when> <xsl:otherwise> @@ -146,7 +146,7 @@ <div class="artifact-title"> <a href="{$metsDoc/mets:METS/@OBJID}"> <xsl:choose> - <xsl:when test="dri:list[@n=(concat($handle, ':dc.title'))]"> + <xsl:when test="dri:list[@n=(concat($handle, ':dc.title')) and descendant::text()]"> <xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.title'))]/dri:item"/> </xsl:when> <xsl:otherwise> @@ -191,7 +191,7 @@ </xsl:choose> </xsl:attribute> <xsl:choose> - <xsl:when test="dri:list[@n=(concat($handle, ':dc.title'))]"> + <xsl:when test="dri:list[@n=(concat($handle, ':dc.title')) and descendant::text()]"> <xsl:apply-templates select="dri:list[@n=(concat($handle, ':dc.title'))]/dri:item"/> </xsl:when> <xsl:otherwise> @@ -295,4 +295,4 @@ </div> </xsl:template> -</xsl:stylesheet> \ No newline at end of file +</xsl:stylesheet> diff --git a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/item-view.xsl b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/item-view.xsl index fabb53c18930bbfabbe2cbaf64db61135d12f491..91367957c2bffdc392df45bf3436673b7a074f24 100644 --- a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/item-view.xsl +++ b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/aspect/artifactbrowser/item-view.xsl @@ -464,6 +464,16 @@ <xsl:value-of select="mets:FLocat[@LOCTYPE='URL']/@xlink:title"/> </xsl:otherwise> </xsl:choose> + <xsl:if test="contains(mets:FLocat[@LOCTYPE='URL']/@xlink:href,'isAllowed=n')"> + <img> + <xsl:attribute name="src"> + <xsl:value-of select="$context-path"/> + <xsl:text>/static/icons/lock24.png</xsl:text> + </xsl:attribute> + <xsl:attribute name="alt">xmlui.dri2xhtml.METS-1.0.blocked</xsl:attribute> + <xsl:attribute name="attr" namespace="http://apache.org/cocoon/i18n/2.1">alt</xsl:attribute> + </img> + </xsl:if> </a> </td> <!-- File size always comes in bytes and thus needs conversion --> diff --git a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/core/global-variables.xsl b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/core/global-variables.xsl index 405911326b6e0fde018dcd48b58f81712e4fe6b7..31f624febd59b88549154bd5871a6b9fb6379675 100644 --- a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/core/global-variables.xsl +++ b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/core/global-variables.xsl @@ -50,4 +50,18 @@ --> <xsl:variable name="theme-path" select="concat($context-path,'/themes/',/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='theme'][@qualifier='path'])"/> + <!-- + Full URI of the current page. Composed of scheme, server name and port and request URI. + --> + <xsl:variable name="current-uri"> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='scheme']"/> + <xsl:text>://</xsl:text> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='serverName']"/> + <xsl:text>:</xsl:text> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='serverPort']"/> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath']"/> + <xsl:text>/</xsl:text> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='URI']"/> + </xsl:variable> + </xsl:stylesheet> diff --git a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/core/page-structure.xsl b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/core/page-structure.xsl index fd2924a938b44cd6be5d9fe006ed8f93790d2b16..f681332dd8fdc546dfdea7dbb5150eb8256b540b 100644 --- a/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/core/page-structure.xsl +++ b/dspace-xmlui/src/main/webapp/themes/dri2xhtml-alt/core/page-structure.xsl @@ -113,7 +113,7 @@ </xsl:if> </xsl:attribute> </meta> - <!-- Add stylsheets --> + <!-- Add stylesheets --> <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='stylesheet']"> <link rel="stylesheet" type="text/css"> <xsl:attribute name="media"> @@ -354,6 +354,7 @@ </xsl:otherwise> </xsl:choose> + <xsl:call-template name="languageSelection" /> </div> </xsl:template> @@ -583,4 +584,23 @@ </xsl:if> </xsl:variable> + <!-- Display language selection if more than 1 language is supported --> + <xsl:template name="languageSelection"> + <xsl:if test="count(/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='page'][@qualifier='supportedLocale']) > 1"> + <div id="ds-language-selection"> + <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='page'][@qualifier='supportedLocale']"> + <xsl:variable name="locale" select="."/> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="$current-uri"/> + <xsl:text>?locale-attribute=</xsl:text> + <xsl:value-of select="$locale"/> + </xsl:attribute> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='supportedLocale'][@qualifier=$locale]"/> + </a> + </xsl:for-each> + </div> + </xsl:if> + </xsl:template> + </xsl:stylesheet> diff --git a/dspace-xmlui/src/main/webapp/themes/dri2xhtml/DIM-Handler.xsl b/dspace-xmlui/src/main/webapp/themes/dri2xhtml/DIM-Handler.xsl index 49fc0f7a190f8471249cb49d45e4922ff2e196c0..4d31d5383271612e152e8d5fe793e4a50f17fed0 100644 --- a/dspace-xmlui/src/main/webapp/themes/dri2xhtml/DIM-Handler.xsl +++ b/dspace-xmlui/src/main/webapp/themes/dri2xhtml/DIM-Handler.xsl @@ -807,13 +807,12 @@ </div> </xsl:if> - <xsl:if test="string-length(dim:field[@element='rights'][not(@qualifier)])>0 or string-length(dim:field[@element='rights'][@qualifier='license'])>0"> + <xsl:if test="string-length(dim:field[@element='rights'][not(@qualifier)])>0"> <div class="detail-view-rights-and-license"> - <xsl:if test="string-length(dim:field[@element='rights'][not(@qualifier)])>0"> - <p class="copyright-text"> - <xsl:copy-of select="dim:field[@element='rights'][not(@qualifier)]/node()"/> - </p> - </xsl:if> + <p class="copyright-text"> + <xsl:copy-of select="dim:field[@element='rights'][not(@qualifier)]/node()"/> + </p> + </div> </xsl:if> </xsl:template> @@ -1007,7 +1006,7 @@ <xsl:text>ctx_ver=Z39.88-2004&rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&</xsl:text> <xsl:for-each select=".//dim:field[@element = 'identifier']"> <xsl:text>rft_id=</xsl:text> - <xsl:value-of select="encoder:encode(string(.))"/> + <xsl:value-of select="encoder:encode(string(.), 'UTF-8')"/> <xsl:text>&</xsl:text> </xsl:for-each> <xsl:text>rfr_id=info%3Asid%2Fdspace.org%3Arepository&</xsl:text> @@ -1018,10 +1017,10 @@ <xsl:choose> <xsl:when test="@element = 'contributor' and @qualifier='author'"> - <xsl:value-of select="concat('rft.', 'creator','=',encoder:encode(string(.))) "/> + <xsl:value-of select="concat('rft.', 'creator','=',encoder:encode(string(.), 'UTF-8')) "/> </xsl:when> <xsl:otherwise> - <xsl:value-of select="concat('rft.', @element,'=',encoder:encode(string(.))) "/> + <xsl:value-of select="concat('rft.', @element,'=',encoder:encode(string(.), 'UTF-8')) "/> </xsl:otherwise> </xsl:choose> diff --git a/dspace-xmlui/src/main/webapp/themes/dri2xhtml/General-Handler.xsl b/dspace-xmlui/src/main/webapp/themes/dri2xhtml/General-Handler.xsl index e362f2d45bd3853125db87d3092ee19e389df557..348f74c6ad2f100551600bc5ca8dc6dc655e17c5 100644 --- a/dspace-xmlui/src/main/webapp/themes/dri2xhtml/General-Handler.xsl +++ b/dspace-xmlui/src/main/webapp/themes/dri2xhtml/General-Handler.xsl @@ -111,6 +111,16 @@ <xsl:value-of select="mets:FLocat[@LOCTYPE='URL']/@xlink:title"/> </xsl:otherwise> </xsl:choose> + <xsl:if test="contains(mets:FLocat[@LOCTYPE='URL']/@xlink:href,'isAllowed=n')"> + <img> + <xsl:attribute name="src"> + <xsl:value-of select="$context-path"/> + <xsl:text>/static/icons/lock24.png</xsl:text> + </xsl:attribute> + <xsl:attribute name="alt">xmlui.dri2xhtml.METS-1.0.blocked</xsl:attribute> + <xsl:attribute name="attr" namespace="http://apache.org/cocoon/i18n/2.1">alt</xsl:attribute> + </img> + </xsl:if> </a> </td> <!-- File size always comes in bytes and thus needs conversion --> @@ -212,11 +222,15 @@ <xsl:if test="position() != last()">, </xsl:if> </xsl:for-each> </xsl:variable> + <xsl:variable name="alt-text"><i18n:text>xmlui.dri2xhtml.METS-1.0.item-files-access-rights</i18n:text> <xsl:value-of select="$users"/></xsl:variable> <xsl:choose> <xsl:when test="not ($rights_context/@CONTEXTCLASS = 'GENERAL PUBLIC') and ($rights_context/rights:Permissions/@DISPLAY = 'true')"> <a href="{mets:FLocat[@LOCTYPE='URL']/@xlink:href}"> - <img width="64" height="64" src="{concat($theme-path,'/images/Crystal_Clear_action_lock3_64px.png')}" title="Read access available for {$users}"/> + <img width="64" height="64" src="{concat($theme-path,'/images/Crystal_Clear_action_lock3_64px.png')}"> + <xsl:attribute name="title"><xsl:value-of select="$alt-text"/></xsl:attribute> + <xsl:attribute name="alt"><xsl:value-of select="$alt-text"/></xsl:attribute> + </img> <!-- icon source: http://commons.wikimedia.org/wiki/File:Crystal_Clear_action_lock3.png --> </a> </xsl:when> diff --git a/dspace-xmlui/src/main/webapp/themes/dri2xhtml/structural.xsl b/dspace-xmlui/src/main/webapp/themes/dri2xhtml/structural.xsl index 823195ea5d47b2e3aedf41c6a4c08b7fb157bc8b..72058c8e2571da4d4374d50807efbfaa9d4d9550 100644 --- a/dspace-xmlui/src/main/webapp/themes/dri2xhtml/structural.xsl +++ b/dspace-xmlui/src/main/webapp/themes/dri2xhtml/structural.xsl @@ -48,6 +48,19 @@ --> <xsl:variable name="theme-path" select="concat($context-path,'/themes/',/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='theme'][@qualifier='path'])"/> + <!-- + Full URI of the current page. Composed of scheme, server name and port and request URI. + --> + <xsl:variable name="current-uri"> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='scheme']"/> + <xsl:text>://</xsl:text> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='serverName']"/> + <xsl:text>:</xsl:text> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='serverPort']"/> + <xsl:text>/</xsl:text> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='request'][@qualifier='URI']"/> + </xsl:variable> + <!-- Requested Page URI. Some functions may alter behavior of processing depending if URI matches a pattern. Specifically, adding a static page will need to override the DRI, to directly add content. @@ -148,7 +161,7 @@ </xsl:if> </xsl:attribute> </meta> - <!-- Add stylsheets --> + <!-- Add stylesheets --> <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='stylesheet']"> <link rel="stylesheet" type="text/css"> <xsl:attribute name="media"> @@ -373,6 +386,9 @@ <i18n:text>xmlui.dri2xhtml.structural.logout</i18n:text> </a> </p> + <p> + <xsl:call-template name="languageSelection" /> + </p> </div> </xsl:when> <xsl:otherwise> @@ -386,6 +402,9 @@ <i18n:text>xmlui.dri2xhtml.structural.login</i18n:text> </a> </p> + <p> + <xsl:call-template name="languageSelection" /> + </p> </div> </xsl:otherwise> </xsl:choose> @@ -3798,5 +3817,24 @@ <xsl:apply-templates select="$metsDoc/mets:METS/mets:fileSec" mode="artifact-preview"/> </xsl:template> + + <!-- Display language selection if more than 1 language is supported --> + <xsl:template name="languageSelection"> + <xsl:if test="count(/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='page'][@qualifier='supportedLocale']) > 1"> + <div id="ds-language-selection"> + <xsl:for-each select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='page'][@qualifier='supportedLocale']"> + <xsl:variable name="locale" select="."/> + <a> + <xsl:attribute name="href"> + <xsl:value-of select="$current-uri"/> + <xsl:text>?locale-attribute=</xsl:text> + <xsl:value-of select="$locale"/> + </xsl:attribute> + <xsl:value-of select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='supportedLocale'][@qualifier=$locale]"/> + </a> + </xsl:for-each> + </div> + </xsl:if> + </xsl:template> </xsl:stylesheet> diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/cookies.js b/dspace-xmlui/src/main/webapp/themes/mobile/lib/cookies.js old mode 100755 new mode 100644 diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/detectmobile.LICENSE b/dspace-xmlui/src/main/webapp/themes/mobile/lib/detectmobile.LICENSE old mode 100755 new mode 100644 diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/detectmobile.js b/dspace-xmlui/src/main/webapp/themes/mobile/lib/detectmobile.js old mode 100755 new mode 100644 diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/images/default-thumbnail.png b/dspace-xmlui/src/main/webapp/themes/mobile/lib/images/default-thumbnail.png old mode 100755 new mode 100644 diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.css b/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.css old mode 100755 new mode 100644 index 38dd39c58065ce566dbfbc569bbca2d0b28c9030..439777671da897497a779791d025fad9b9d10791 --- a/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.css +++ b/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.css @@ -24,18 +24,20 @@ font-size: 90%; /* elements for new metadata display */ div#metadata-wrapper { -background: #FFF; -border: none; -padding: 2px; +background: #F2F2F2; +border: 1px solid #BDBDBD; +-moz-border-radius: 5px; +border-radius: 5px; +padding: 1px; } div.metadata-view { clear: both; -background: #FFF; -border: none; -padding: 5px; -line-height: 1.4em; -font-size: 1.2em; +background: #F2F2F2; +border: 1px solid #d8d8d8; +-moz-border-radius: 5px; +border-radius: 5px; +padding: 2px 5px; } div.file-wrapper { @@ -108,6 +110,9 @@ ul.pagination-links { display:none; } +div#addthis { +margin-top: -10px; +} div.pagination { position: relative; @@ -167,7 +172,6 @@ table { clear: both; width: 100%; text-align: left; -margin-left: -35px; padding: 5px; } @@ -316,27 +320,23 @@ display:none; } div#aspect_artifactbrowser_CommunityBrowser_div_comunity-browser { +margin-top: -18px; margin-bottom: 40px; } /* aligning elements on front-page */ div#browse-front-page { +margin-top: -15px; margin-bottom: 10px; } -#aspect_artifactbrowser_CollectionViewer_div_collection-browse li, -#aspect_artifactbrowser_CommunityViewer_div_community-browse li, -div#browse-front-page a { -float: left; -margin-right: 1%; -} - div#file_news_div_news { margin-top: -5px; margin-bottom: -5px; } form#search { +margin-top: -15px; margin-bottom: 25px; } @@ -345,64 +345,3 @@ font-size: 18px; margin-bottom: 1px; } -#aspect_artifactbrowser_CollectionSearch_p_search-query, -#aspect_artifactbrowser_CommunitySearch_p_search-query, -h3 { -background: #EEEFF1; -border-top: 4px solid #2E3435; -color: #2E3435; -font-size: 1.125em; -line-height: 1.5625em; -margin: 20px 0px 20px 0px; -font-weight: bold; -padding: 0.2em 0.2em 1em 0.5em; -clear: both; -} - -#aspect_artifactbrowser_CollectionSearch_field_query, -#aspect_artifactbrowser_CommunitySearch_field_query, -#search-box .ui-input-search { -width: 80%; -float: left; -margin-right: 1%; -height: 43px; -} -#aspect_artifactbrowser_CollectionSearch_p_search-query .ui-submit, -#aspect_artifactbrowser_CollectionSearch_field_query .ui-submit, -#aspect_artifactbrowser_CommunitySearch_p_search-query .ui-submit, -#search-box .ui-submit { float: left; } -#search-box h3 { margin-top: 10px; } - -#aspect_artifactbrowser_CollectionSearch_p_search-query input, -#aspect_artifactbrowser_CommunitySearch_p_search-query input, -#aspect_artifactbrowser_CommunitySearch_p_search-query .ui-submit { -margin-top: 40px; -} - -* { border-radius: 0px !important; } - -.ui-body-c .ui-link, -.ui-body-c .ui-link:visited, -a { text-decoration: none; color: #F57900 } - -.ui-body-c .ui-link:hover, -a:hover { color: #A04700; } - -#ds-language-selection a { font-size: 0.6em; float: left; padding: 5px; } -#ds-language-selection { float: right; } - -#ds-trail li { float: left; display: inline; padding: 5px; } - -.ui-content { clear: both; } - -#addthis-box a { - float: right; - display: inline; -} -#addthis-box { - font-weight: bold; - width: 190px; - position: absolute; - right: 20px; -} - diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.js b/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.js deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.ori b/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.ori deleted file mode 100755 index bc33d416eee0210dbec87c1fb3cc08e427eda428..0000000000000000000000000000000000000000 --- a/dspace-xmlui/src/main/webapp/themes/mobile/lib/m-tweaks.ori +++ /dev/null @@ -1,348 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -/* - - This file was created to add mobile-friendly properties for DSpace elements - that sc-mobile.min.css cannot control. - - Last update by Elias Tzoc <tzoce@miamioh.edu> - September 30, 2013 - -*/ - - -/* setting up general margin properties */ -div#ds-body { -margin-top: -20px; -font-size: 90%; -} - -/* elements for new metadata display */ -div#metadata-wrapper { -background: #F2F2F2; -border: 1px solid #BDBDBD; --moz-border-radius: 5px; -border-radius: 5px; -padding: 1px; -} - -div.metadata-view { -clear: both; -background: #F2F2F2; -border: 1px solid #d8d8d8; --moz-border-radius: 5px; -border-radius: 5px; -padding: 2px 5px; -} - -div.file-wrapper { -height: 57px; -padding: 5px; -background: #fafafa; -border: 1px solid #BDBDBD; --moz-border-radius: 5px; -border-radius: 5px; -margin-bottom: 1px; -} - -div.file-metadata { -float:left; -margin-left: 5px; -line-height: 17px; -} - -div.thumbnail-wrapper { -float: left; -} - -div.thumbnail-wrapper img { -height: 55px; -border: 1px solid #ccc; -} - -div.artifact-description { -margin-top: -20px; -} - -div#featured-items { -display:none; -} - -div#aspect_artifactbrowser_ItemViewer_div_item-view h2 { -font-size: 20px; -margin-bottom: -1px; -} - -span.bold { -font-weight: bolder; -} - -form#aspect_artifactbrowser_SimpleSearch_div_general-query { -display:none; -} - -/* removing search for browsing collection/community pages */ -form#aspect_artifactbrowser_ConfigurableBrowse_div_browse-navigation p { -display: none; -} - -/* removing custom options for browsing in browse by author, title, and subject */ -form#aspect_artifactbrowser_ConfigurableBrowse_div_browse-controls { -display: none; -} - -/* formatting pagination elements */ -div.pagination-masked { -position: relative; -margin-left: 0px; -margin-top: 55px; -margin-bottom: 55px; -border-bottom: 1px solid #F2F2F2; -text-align: center; -} - -ul.pagination-links { -display:none; -} - -div#addthis { -margin-top: -10px; -} - -div.pagination { -position: relative; -margin-left: 0px; -margin-top: 75px; -margin-bottom: 55px; -border-bottom: 1px solid #F2F2F2; -} - -a.previous-page-link { -position: absolute; -left: 0px; -bottom: 3px; -width: 50px; -margin-top: 75px; -text-align: center; -padding: 10px; -color: #000; -background: #E6E6E6; -border: 1px solid #ccc; --moz-border-radius: 5px; -border-radius: 5px; -text-decoration: none; -} - -a.next-page-link { -position: absolute; -right: -1px; -bottom: 3px; -width: 50px; -text-align: center; -padding: 10px; -background: #E6E6E6; -border: 1px solid #ccc; --moz-border-radius: 5px; -border-radius: 5px; -text-decoration: none; -} - -p.pagination-info { -position: absolute; -text-align: center; -width: 100%; -margin: 0 auto; -float:right; -text-align: center; -padding: 10px 0px; -background: #E6E6E6; -color: #000; -border: 1px solid #ccc; --moz-border-radius: 5px; -border-radius: 5px; -} - -/* table properties for results page */ -table { -clear: both; -width: 100%; -text-align: left; -margin-left: -35px; -padding: 5px; -} - -tr.ds-table-header-row { -display: none; -} - -div#aspect_artifactbrowser_CommunityViewer_div_community-view h3 { -margin-bottom: 15px; -} - -/* resizing default ul.listview */ -ul.ui-listview { -padding: 0px 15px; -} - -/* modifying ul.listview borders */ -ul.ui-listview li { -margin-bottom: 1px; -border: 1px solid #ccc; --moz-border-radius: 10px; -border-radius: 10px; -} - -ul.ds-artifact-list { -background: #fafafa; -list-style-type: none; -margin-top: 0px; -border: 1px solid #ccc; --moz-border-radius: 5px; -border-radius: 5px; -} - -ul.ds-artifact-list li { -margin-left: -25px; -margin-top: 30px; -margin-right: 15px; -margin-bottom: 15px; -border-bottom: 0px solid #ccc; -} - -ul.ds-referenceSet-list { -background: #fafafa; -list-style-type: none; -margin-top: 0px; -border: 1px solid #ccc; --moz-border-radius: 5px; -border-radius: 5px; -} - -ul.ds-referenceSet-list li { -margin-left: -30px; -margin-top: 5px; -margin-bottom: 5px; -border-bottom: 0px solid #ccc; -} - -div.artifact-info { -margin-top: 0px; -margin-bottom: 10px; -} - -div#aspect_artifactbrowser_CollectionViewer_div_collection-recent-submission { -margin-top: -15px; -} - -div#aspect_artifactbrowser_SimpleSearch_div_search-results h3 { -display:inline; -} - -p#aspect_artifactbrowser_SimpleSearch_p_result-query { -margin-top: -15px; -} - -/* removing complex or advanced elements */ -form#aspect_artifactbrowser_CommunityViewer_div_community-search a { -display:none; -} -form#aspect_artifactbrowser_CollectionViewer_div_collection-search a { -display:none; -} -div#aspect_artifactbrowser_SimpleSearch_div_search h3 { -display:none; -} -div#aspect_artifactbrowser_ItemViewer_div_item-view p { -display: none; -} - -form#aspect_artifactbrowser_CommunityViewer_div_community-search { -margin-top: -15px; -margin-bottom: 40px; -} - -form#aspect_artifactbrowser_CollectionViewer_div_collection-search { -margin-top: -15px; -margin-bottom: 40px; -} - -/* new mobile-optimized advanced search */ -#aspect_artifactbrowser_AdvancedSearch_list_search-query { -margin-left: -25px; -} - -#aspect_artifactbrowser_AdvancedSearch_table_search-query .ui-select .ui-btn { -width: 110px; -} - -table#aspect_artifactbrowser_AdvancedSearch_table_search-query, -table#aspect_artifactbrowser_AdvancedSearch_table_search-controls { -margin-left: 0px; -} - -/* A-Z browse on author, title and subject pages */ -ul#aspect_artifactbrowser_ConfigurableBrowse_list_jump-list { -margin-top: -15px; -padding-left: 0px; -padding-top: 0px; -list-style-type:none; -height: 75px; -min-width: 200px; -} - -ul#aspect_artifactbrowser_ConfigurableBrowse_list_jump-list a { -text-decoration: none; -padding: 5px 0px; -} - -ul#aspect_artifactbrowser_ConfigurableBrowse_list_jump-list li { -float:left; -min-width:9.9%; -height: 22px; -text-align:center; -background: #E6E6E6; -margin-bottom: 2px; -margin-right: 1px; -margin-left: 1px; -border: 1px solid #ccc; --moz-border-radius: 5px; -border-radius: 5px; -font-size: 110%; -} - -/* removes extra line and margin control for community browser page */ -div#aspect_artifactbrowser_CommunityBrowser_div_comunity-browser p { -display:none; -} - -div#aspect_artifactbrowser_CommunityBrowser_div_comunity-browser { -margin-top: -18px; -margin-bottom: 40px; -} - -/* aligning elements on front-page */ -div#browse-front-page { -margin-top: -15px; -margin-bottom: 10px; -} - -div#file_news_div_news { -margin-top: -5px; -margin-bottom: -5px; -} - -form#search { -margin-top: -15px; -margin-bottom: 25px; -} - -h3.ds-list-head { -font-size: 18px; -margin-bottom: 1px; -} - diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.LICENSE b/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.LICENSE old mode 100755 new mode 100644 diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.css b/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.css index 6b9293f39927abfdc743331337c2168d9a47da72..c3f4ecb6509eb1d721694909b1e84ffb068b9848 100644 --- a/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.css +++ b/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.css @@ -1,32 +1,36 @@ /* -* jQuery Mobile Framework 1.1.2 9a15f1aaf99faa7913103f5ea19ef6959b73d763 -* http://jquerymobile.com -* -* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors -* Released under the MIT license. -* http://jquery.org/license -* + + Original file was created and downloaded from http://jquerymobile.com/themeroller/ + jQuery Mobile Framework 1.1.1 1981b3f5ec22675ae47df8f0bdf9622e7780e90e + + Copyright 2012 jQuery Foundation and other contributors + Dual licensed under the MIT or GPL Version 2 licenses. + http://jquery.org/license + + This uncompressed file can be used to import/upgrade the CSS properties at http://jquerymobile.com/themeroller/ + */ + /* Swatches */ /* A -----------------------------------------------------------------------------------------------------------*/ .ui-bar-a { - border: 1px solid #ffffff /*{a-bar-border}*/; - background: #ffffff /*{a-bar-background-color}*/; - color: #000000 /*{a-bar-color}*/; + border: 1px solid #424242 /*{a-bar-border}*/; + background: #9b1f23 /*{a-bar-background-color}*/; + color: #ffffff /*{a-bar-color}*/; font-weight: bold; - text-shadow: 0 /*{a-bar-shadow-x}*/ 1px /*{a-bar-shadow-y}*/ 1px /*{a-bar-shadow-radius}*/ #eeeeee /*{a-bar-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #FFFFFF /*{a-bar-background-start}*/), to( #e5e5e5 /*{a-bar-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #FFFFFF /*{a-bar-background-start}*/, #e5e5e5 /*{a-bar-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #FFFFFF /*{a-bar-background-start}*/, #e5e5e5 /*{a-bar-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #FFFFFF /*{a-bar-background-start}*/, #e5e5e5 /*{a-bar-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #FFFFFF /*{a-bar-background-start}*/, #e5e5e5 /*{a-bar-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #FFFFFF /*{a-bar-background-start}*/, #e5e5e5 /*{a-bar-background-end}*/); + text-shadow: 0 /*{a-bar-shadow-x}*/ 1px /*{a-bar-shadow-y}*/ 1px /*{a-bar-shadow-radius}*/ #444444 /*{a-bar-shadow-color}*/; + background-image: -webkit-gradient(linear, left top, left bottom, from( #9b1f23 /*{a-bar-background-start}*/), to( #660000 /*{a-bar-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #9b1f23 /*{a-bar-background-start}*/, #660000 /*{a-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #9b1f23 /*{a-bar-background-start}*/, #660000 /*{a-bar-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #9b1f23 /*{a-bar-background-start}*/, #660000 /*{a-bar-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #9b1f23 /*{a-bar-background-start}*/, #660000 /*{a-bar-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #9b1f23 /*{a-bar-background-start}*/, #660000 /*{a-bar-background-end}*/); } .ui-bar-a .ui-link-inherit { - color: #000000 /*{a-bar-color}*/; + color: #ffffff /*{a-bar-color}*/; } .ui-bar-a a.ui-link { @@ -51,20 +55,20 @@ .ui-bar-a select, .ui-bar-a textarea, .ui-bar-a button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; } .ui-body-a, .ui-overlay-a { - border: 1px solid #d6d6d6 /*{a-body-border}*/; + border: 1px solid #aaaaaa /*{a-body-border}*/; color: #333333 /*{a-body-color}*/; - text-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ #ffffff /*{a-body-shadow-color}*/; + text-shadow: 0 /*{a-body-shadow-x}*/ 0px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ #ffffff /*{a-body-shadow-color}*/; background: #ffffff /*{a-body-background-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #FFFFFF /*{a-body-background-start}*/), to( #f9f9f9 /*{a-body-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #FFFFFF /*{a-body-background-start}*/, #f9f9f9 /*{a-body-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #FFFFFF /*{a-body-background-start}*/, #f9f9f9 /*{a-body-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #FFFFFF /*{a-body-background-start}*/, #f9f9f9 /*{a-body-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #FFFFFF /*{a-body-background-start}*/, #f9f9f9 /*{a-body-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #FFFFFF /*{a-body-background-start}*/, #f9f9f9 /*{a-body-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #ffffff /*{a-body-background-start}*/), to( #ffffff /*{a-body-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #ffffff /*{a-body-background-start}*/, #ffffff /*{a-body-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #ffffff /*{a-body-background-start}*/, #ffffff /*{a-body-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #ffffff /*{a-body-background-start}*/, #ffffff /*{a-body-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #ffffff /*{a-body-background-start}*/, #ffffff /*{a-body-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #ffffff /*{a-body-background-start}*/, #ffffff /*{a-body-background-end}*/); } .ui-overlay-a { background-image: none; @@ -75,86 +79,86 @@ .ui-body-a select, .ui-body-a textarea, .ui-body-a button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; } .ui-body-a .ui-link-inherit { color: #333333 /*{a-body-color}*/; } .ui-body-a .ui-link { - color: #bc4b20 /*{a-body-link-color}*/; + color: #c1272d /*{a-body-link-color}*/; font-weight: bold; } .ui-body-a .ui-link:visited { - color: #2489CE /*{a-body-link-visited}*/; + color: #c1272d /*{a-body-link-visited}*/; } .ui-body-a .ui-link:hover { - color: #2489CE /*{a-body-link-hover}*/; + color: #dd2c33 /*{a-body-link-hover}*/; } .ui-body-a .ui-link:active { - color: #2489CE /*{a-body-link-active}*/; + color: #c1272d /*{a-body-link-active}*/; } .ui-btn-up-a { - border: 1px solid #d6d6d6 /*{a-bup-border}*/; - background: #d6d6d6 /*{a-bup-background-color}*/; + border: 1px solid #cccccc /*{a-bup-border}*/; + background: #e6e6e6 /*{a-bup-background-color}*/; font-weight: bold; - color: #333333 /*{a-bup-color}*/; + color: #2F3E46 /*{a-bup-color}*/; text-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 0 /*{a-bup-shadow-radius}*/ #ffffff /*{a-bup-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #dadada /*{a-bup-background-start}*/), to( #d1d1d1 /*{a-bup-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #dadada /*{a-bup-background-start}*/, #d1d1d1 /*{a-bup-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #dadada /*{a-bup-background-start}*/, #d1d1d1 /*{a-bup-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #dadada /*{a-bup-background-start}*/, #d1d1d1 /*{a-bup-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #dadada /*{a-bup-background-start}*/, #d1d1d1 /*{a-bup-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #dadada /*{a-bup-background-start}*/, #d1d1d1 /*{a-bup-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #e6e6e6 /*{a-bup-background-start}*/), to( #e6e6e6 /*{a-bup-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #e6e6e6 /*{a-bup-background-start}*/, #e6e6e6 /*{a-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #e6e6e6 /*{a-bup-background-start}*/, #e6e6e6 /*{a-bup-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #e6e6e6 /*{a-bup-background-start}*/, #e6e6e6 /*{a-bup-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #e6e6e6 /*{a-bup-background-start}*/, #e6e6e6 /*{a-bup-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #e6e6e6 /*{a-bup-background-start}*/, #e6e6e6 /*{a-bup-background-end}*/); } .ui-btn-up-a:visited, .ui-btn-up-a a.ui-link-inherit { - color: #333333 /*{a-bup-color}*/; + color: #2F3E46 /*{a-bup-color}*/; } .ui-btn-hover-a { - border: 1px solid #d6d6d6 /*{a-bhover-border}*/; - background: #d6d6d6 /*{a-bhover-background-color}*/; + border: 1px solid #bbbbbb /*{a-bhover-border}*/; + background: #dfdfdf /*{a-bhover-background-color}*/; font-weight: bold; - color: #000000 /*{a-bhover-color}*/; + color: #2F3E46 /*{a-bhover-color}*/; text-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 0 /*{a-bhover-shadow-radius}*/ #ffffff /*{a-bhover-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #e9e9e9 /*{a-bhover-background-start}*/), to( #c2c2c2 /*{a-bhover-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #e9e9e9 /*{a-bhover-background-start}*/, #c2c2c2 /*{a-bhover-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #e9e9e9 /*{a-bhover-background-start}*/, #c2c2c2 /*{a-bhover-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #e9e9e9 /*{a-bhover-background-start}*/, #c2c2c2 /*{a-bhover-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #e9e9e9 /*{a-bhover-background-start}*/, #c2c2c2 /*{a-bhover-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #e9e9e9 /*{a-bhover-background-start}*/, #c2c2c2 /*{a-bhover-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #f6f6f6 /*{a-bhover-background-start}*/), to( #e0e0e0 /*{a-bhover-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #f6f6f6 /*{a-bhover-background-start}*/, #e0e0e0 /*{a-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #f6f6f6 /*{a-bhover-background-start}*/, #e0e0e0 /*{a-bhover-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #f6f6f6 /*{a-bhover-background-start}*/, #e0e0e0 /*{a-bhover-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #f6f6f6 /*{a-bhover-background-start}*/, #e0e0e0 /*{a-bhover-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #f6f6f6 /*{a-bhover-background-start}*/, #e0e0e0 /*{a-bhover-background-end}*/); } .ui-btn-hover-a:visited, .ui-btn-hover-a:hover, .ui-btn-hover-a a.ui-link-inherit { - color: #000000 /*{a-bhover-color}*/; + color: #2F3E46 /*{a-bhover-color}*/; } .ui-btn-down-a { border: 1px solid #bbbbbb /*{a-bdown-border}*/; background: #d6d6d6 /*{a-bdown-background-color}*/; font-weight: bold; - color: #333333 /*{a-bdown-color}*/; + color: #2F3E46 /*{a-bdown-color}*/; text-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 0 /*{a-bdown-shadow-radius}*/ #ffffff /*{a-bdown-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #bebebe /*{a-bdown-background-start}*/), to( #ededed /*{a-bdown-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #bebebe /*{a-bdown-background-start}*/, #ededed /*{a-bdown-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #bebebe /*{a-bdown-background-start}*/, #ededed /*{a-bdown-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #bebebe /*{a-bdown-background-start}*/, #ededed /*{a-bdown-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #bebebe /*{a-bdown-background-start}*/, #ededed /*{a-bdown-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #bebebe /*{a-bdown-background-start}*/, #ededed /*{a-bdown-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #d0d0d0 /*{a-bdown-background-start}*/), to( #dfdfdf /*{a-bdown-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #d0d0d0 /*{a-bdown-background-start}*/, #dfdfdf /*{a-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #d0d0d0 /*{a-bdown-background-start}*/, #dfdfdf /*{a-bdown-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #d0d0d0 /*{a-bdown-background-start}*/, #dfdfdf /*{a-bdown-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #d0d0d0 /*{a-bdown-background-start}*/, #dfdfdf /*{a-bdown-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #d0d0d0 /*{a-bdown-background-start}*/, #dfdfdf /*{a-bdown-background-end}*/); } .ui-btn-down-a:visited, .ui-btn-down-a:hover, .ui-btn-down-a a.ui-link-inherit { - color: #333333 /*{a-bdown-color}*/; + color: #2F3E46 /*{a-bdown-color}*/; } .ui-btn-up-a, .ui-btn-hover-a, .ui-btn-down-a { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; text-decoration: none; } @@ -163,20 +167,20 @@ -----------------------------------------------------------------------------------------------------------*/ .ui-bar-b { - border: 1px solid #ffffff /*{b-bar-border}*/; - background: #ffffff /*{b-bar-background-color}*/; - color: #000000 /*{b-bar-color}*/; + border: 1px solid #424242 /*{b-bar-border}*/; + background: #9b1f23 /*{b-bar-background-color}*/; + color: #ffffff /*{b-bar-color}*/; font-weight: bold; - text-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 1px /*{b-bar-shadow-radius}*/ #eeeeee /*{b-bar-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #FFFFFF /*{b-bar-background-start}*/), to( #e5e5e5 /*{b-bar-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #FFFFFF /*{b-bar-background-start}*/, #e5e5e5 /*{b-bar-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #FFFFFF /*{b-bar-background-start}*/, #e5e5e5 /*{b-bar-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #FFFFFF /*{b-bar-background-start}*/, #e5e5e5 /*{b-bar-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #FFFFFF /*{b-bar-background-start}*/, #e5e5e5 /*{b-bar-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #FFFFFF /*{b-bar-background-start}*/, #e5e5e5 /*{b-bar-background-end}*/); + text-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 1px /*{b-bar-shadow-radius}*/ #444444 /*{b-bar-shadow-color}*/; + background-image: -webkit-gradient(linear, left top, left bottom, from( #9b1f23 /*{b-bar-background-start}*/), to( #660000 /*{b-bar-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #9b1f23 /*{b-bar-background-start}*/, #660000 /*{b-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #9b1f23 /*{b-bar-background-start}*/, #660000 /*{b-bar-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #9b1f23 /*{b-bar-background-start}*/, #660000 /*{b-bar-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #9b1f23 /*{b-bar-background-start}*/, #660000 /*{b-bar-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #9b1f23 /*{b-bar-background-start}*/, #660000 /*{b-bar-background-end}*/); } .ui-bar-b .ui-link-inherit { - color: #000000 /*{b-bar-color}*/; + color: #ffffff /*{b-bar-color}*/; } .ui-bar-b a.ui-link { @@ -201,20 +205,20 @@ .ui-bar-b select, .ui-bar-b textarea, .ui-bar-b button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; } .ui-body-b, .ui-overlay-b { - border: 1px solid #d6d6d6 /*{b-body-border}*/; + border: 1px solid #aaaaaa /*{b-body-border}*/; color: #333333 /*{b-body-color}*/; - text-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ #ffffff /*{b-body-shadow-color}*/; + text-shadow: 0 /*{b-body-shadow-x}*/ 0px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ #ffffff /*{b-body-shadow-color}*/; background: #ffffff /*{b-body-background-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #FFFFFF /*{b-body-background-start}*/), to( #f9f9f9 /*{b-body-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #FFFFFF /*{b-body-background-start}*/, #f9f9f9 /*{b-body-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #FFFFFF /*{b-body-background-start}*/, #f9f9f9 /*{b-body-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #FFFFFF /*{b-body-background-start}*/, #f9f9f9 /*{b-body-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #FFFFFF /*{b-body-background-start}*/, #f9f9f9 /*{b-body-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #FFFFFF /*{b-body-background-start}*/, #f9f9f9 /*{b-body-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #ffffff /*{b-body-background-start}*/), to( #ffffff /*{b-body-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #ffffff /*{b-body-background-start}*/, #ffffff /*{b-body-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #ffffff /*{b-body-background-start}*/, #ffffff /*{b-body-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #ffffff /*{b-body-background-start}*/, #ffffff /*{b-body-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #ffffff /*{b-body-background-start}*/, #ffffff /*{b-body-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #ffffff /*{b-body-background-start}*/, #ffffff /*{b-body-background-end}*/); } .ui-overlay-b { background-image: none; @@ -225,110 +229,108 @@ .ui-body-b select, .ui-body-b textarea, .ui-body-b button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; } .ui-body-b .ui-link-inherit { color: #333333 /*{b-body-color}*/; } .ui-body-b .ui-link { - color: #bc4b20 /*{b-body-link-color}*/; + color: #c1272d /*{b-body-link-color}*/; font-weight: bold; } .ui-body-b .ui-link:visited { - color: #2489CE /*{b-body-link-visited}*/; + color: #c1272d /*{b-body-link-visited}*/; } .ui-body-b .ui-link:hover { - color: #2489CE /*{b-body-link-hover}*/; + color: #dd2c33 /*{b-body-link-hover}*/; } .ui-body-b .ui-link:active { - color: #2489CE /*{b-body-link-active}*/; + color: #c1272d /*{b-body-link-active}*/; } .ui-btn-up-b { - border: 1px solid #d6d6d6 /*{b-bup-border}*/; - background: #d6d6d6 /*{b-bup-background-color}*/; + border: 1px solid #cccccc /*{b-bup-border}*/; + background: #e6e6e6 /*{b-bup-background-color}*/; font-weight: bold; - color: #333333 /*{b-bup-color}*/; + color: #2F3E46 /*{b-bup-color}*/; text-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 0 /*{b-bup-shadow-radius}*/ #ffffff /*{b-bup-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #dadada /*{b-bup-background-start}*/), to( #d1d1d1 /*{b-bup-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #dadada /*{b-bup-background-start}*/, #d1d1d1 /*{b-bup-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #dadada /*{b-bup-background-start}*/, #d1d1d1 /*{b-bup-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #dadada /*{b-bup-background-start}*/, #d1d1d1 /*{b-bup-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #dadada /*{b-bup-background-start}*/, #d1d1d1 /*{b-bup-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #dadada /*{b-bup-background-start}*/, #d1d1d1 /*{b-bup-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #e6e6e6 /*{b-bup-background-start}*/), to( #e6e6e6 /*{b-bup-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #e6e6e6 /*{b-bup-background-start}*/, #e6e6e6 /*{b-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #e6e6e6 /*{b-bup-background-start}*/, #e6e6e6 /*{b-bup-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #e6e6e6 /*{b-bup-background-start}*/, #e6e6e6 /*{b-bup-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #e6e6e6 /*{b-bup-background-start}*/, #e6e6e6 /*{b-bup-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #e6e6e6 /*{b-bup-background-start}*/, #e6e6e6 /*{b-bup-background-end}*/); } .ui-btn-up-b:visited, .ui-btn-up-b a.ui-link-inherit { - color: #333333 /*{b-bup-color}*/; + color: #2F3E46 /*{b-bup-color}*/; } .ui-btn-hover-b { - border: 1px solid #d6d6d6 /*{b-bhover-border}*/; - background: #d6d6d6 /*{b-bhover-background-color}*/; + border: 1px solid #bbbbbb /*{b-bhover-border}*/; + background: #dfdfdf /*{b-bhover-background-color}*/; font-weight: bold; - color: #000000 /*{b-bhover-color}*/; + color: #2F3E46 /*{b-bhover-color}*/; text-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 0 /*{b-bhover-shadow-radius}*/ #ffffff /*{b-bhover-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #e9e9e9 /*{b-bhover-background-start}*/), to( #c2c2c2 /*{b-bhover-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #e9e9e9 /*{b-bhover-background-start}*/, #c2c2c2 /*{b-bhover-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #e9e9e9 /*{b-bhover-background-start}*/, #c2c2c2 /*{b-bhover-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #e9e9e9 /*{b-bhover-background-start}*/, #c2c2c2 /*{b-bhover-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #e9e9e9 /*{b-bhover-background-start}*/, #c2c2c2 /*{b-bhover-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #e9e9e9 /*{b-bhover-background-start}*/, #c2c2c2 /*{b-bhover-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #f6f6f6 /*{b-bhover-background-start}*/), to( #e0e0e0 /*{b-bhover-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #f6f6f6 /*{b-bhover-background-start}*/, #e0e0e0 /*{b-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #f6f6f6 /*{b-bhover-background-start}*/, #e0e0e0 /*{b-bhover-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #f6f6f6 /*{b-bhover-background-start}*/, #e0e0e0 /*{b-bhover-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #f6f6f6 /*{b-bhover-background-start}*/, #e0e0e0 /*{b-bhover-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #f6f6f6 /*{b-bhover-background-start}*/, #e0e0e0 /*{b-bhover-background-end}*/); } .ui-btn-hover-b:visited, .ui-btn-hover-b:hover, .ui-btn-hover-b a.ui-link-inherit { - color: #000000 /*{b-bhover-color}*/; + color: #2F3E46 /*{b-bhover-color}*/; } .ui-btn-down-b { border: 1px solid #bbbbbb /*{b-bdown-border}*/; background: #d6d6d6 /*{b-bdown-background-color}*/; font-weight: bold; - color: #333333 /*{b-bdown-color}*/; + color: #2F3E46 /*{b-bdown-color}*/; text-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 0 /*{b-bdown-shadow-radius}*/ #ffffff /*{b-bdown-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #bebebe /*{b-bdown-background-start}*/), to( #ededed /*{b-bdown-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #bebebe /*{b-bdown-background-start}*/, #ededed /*{b-bdown-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #bebebe /*{b-bdown-background-start}*/, #ededed /*{b-bdown-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #bebebe /*{b-bdown-background-start}*/, #ededed /*{b-bdown-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #bebebe /*{b-bdown-background-start}*/, #ededed /*{b-bdown-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #bebebe /*{b-bdown-background-start}*/, #ededed /*{b-bdown-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #d0d0d0 /*{b-bdown-background-start}*/), to( #dfdfdf /*{b-bdown-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #d0d0d0 /*{b-bdown-background-start}*/, #dfdfdf /*{b-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #d0d0d0 /*{b-bdown-background-start}*/, #dfdfdf /*{b-bdown-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #d0d0d0 /*{b-bdown-background-start}*/, #dfdfdf /*{b-bdown-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #d0d0d0 /*{b-bdown-background-start}*/, #dfdfdf /*{b-bdown-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #d0d0d0 /*{b-bdown-background-start}*/, #dfdfdf /*{b-bdown-background-end}*/); } .ui-btn-down-b:visited, .ui-btn-down-b:hover, .ui-btn-down-b a.ui-link-inherit { - color: #333333 /*{b-bdown-color}*/; + color: #2F3E46 /*{b-bdown-color}*/; } .ui-btn-up-b, .ui-btn-hover-b, .ui-btn-down-b { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; text-decoration: none; } - - /* C -----------------------------------------------------------------------------------------------------------*/ .ui-bar-c { - border: 1px solid #ffffff /*{c-bar-border}*/; - background: #ffffff /*{c-bar-background-color}*/; - color: #000000 /*{c-bar-color}*/; + border: 1px solid #424242 /*{c-bar-border}*/; + background: #9b1f23 /*{c-bar-background-color}*/; + color: #ffffff /*{c-bar-color}*/; font-weight: bold; - text-shadow: 0 /*{c-bar-shadow-x}*/ 1px /*{c-bar-shadow-y}*/ 1px /*{c-bar-shadow-radius}*/ #eeeeee /*{c-bar-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #FFFFFF /*{c-bar-background-start}*/), to( #e5e5e5 /*{c-bar-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #FFFFFF /*{c-bar-background-start}*/, #e5e5e5 /*{c-bar-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #FFFFFF /*{c-bar-background-start}*/, #e5e5e5 /*{c-bar-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #FFFFFF /*{c-bar-background-start}*/, #e5e5e5 /*{c-bar-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #FFFFFF /*{c-bar-background-start}*/, #e5e5e5 /*{c-bar-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #FFFFFF /*{c-bar-background-start}*/, #e5e5e5 /*{c-bar-background-end}*/); + text-shadow: 0 /*{c-bar-shadow-x}*/ 1px /*{c-bar-shadow-y}*/ 1px /*{c-bar-shadow-radius}*/ #444444 /*{c-bar-shadow-color}*/; + background-image: -webkit-gradient(linear, left top, left bottom, from( #9b1f23 /*{c-bar-background-start}*/), to( #660000 /*{c-bar-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #9b1f23 /*{c-bar-background-start}*/, #660000 /*{c-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #9b1f23 /*{c-bar-background-start}*/, #660000 /*{c-bar-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #9b1f23 /*{c-bar-background-start}*/, #660000 /*{c-bar-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #9b1f23 /*{c-bar-background-start}*/, #660000 /*{c-bar-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #9b1f23 /*{c-bar-background-start}*/, #660000 /*{c-bar-background-end}*/); } .ui-bar-c .ui-link-inherit { - color: #000000 /*{c-bar-color}*/; + color: #ffffff /*{c-bar-color}*/; } .ui-bar-c a.ui-link { @@ -353,20 +355,20 @@ .ui-bar-c select, .ui-bar-c textarea, .ui-bar-c button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; } .ui-body-c, .ui-overlay-c { - border: 1px solid #d6d6d6 /*{c-body-border}*/; + border: 1px solid #aaaaaa /*{c-body-border}*/; color: #333333 /*{c-body-color}*/; - text-shadow: 0 /*{c-body-shadow-x}*/ 1px /*{c-body-shadow-y}*/ 0 /*{c-body-shadow-radius}*/ #ffffff /*{c-body-shadow-color}*/; + text-shadow: 0 /*{c-body-shadow-x}*/ 0px /*{c-body-shadow-y}*/ 0 /*{c-body-shadow-radius}*/ #ffffff /*{c-body-shadow-color}*/; background: #ffffff /*{c-body-background-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #FFFFFF /*{c-body-background-start}*/), to( #f9f9f9 /*{c-body-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #FFFFFF /*{c-body-background-start}*/, #f9f9f9 /*{c-body-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #FFFFFF /*{c-body-background-start}*/, #f9f9f9 /*{c-body-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #FFFFFF /*{c-body-background-start}*/, #f9f9f9 /*{c-body-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #FFFFFF /*{c-body-background-start}*/, #f9f9f9 /*{c-body-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #FFFFFF /*{c-body-background-start}*/, #f9f9f9 /*{c-body-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #ffffff /*{c-body-background-start}*/), to( #ffffff /*{c-body-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #ffffff /*{c-body-background-start}*/, #ffffff /*{c-body-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #ffffff /*{c-body-background-start}*/, #ffffff /*{c-body-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #ffffff /*{c-body-background-start}*/, #ffffff /*{c-body-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #ffffff /*{c-body-background-start}*/, #ffffff /*{c-body-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #ffffff /*{c-body-background-start}*/, #ffffff /*{c-body-background-end}*/); } .ui-overlay-c { background-image: none; @@ -377,86 +379,86 @@ .ui-body-c select, .ui-body-c textarea, .ui-body-c button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; } .ui-body-c .ui-link-inherit { color: #333333 /*{c-body-color}*/; } .ui-body-c .ui-link { - color: #bc4b20 /*{c-body-link-color}*/; + color: #c1272d /*{c-body-link-color}*/; font-weight: bold; } .ui-body-c .ui-link:visited { - color: #2489CE /*{c-body-link-visited}*/; + color: #c1272d /*{c-body-link-visited}*/; } .ui-body-c .ui-link:hover { - color: #2489CE /*{c-body-link-hover}*/; + color: #dd2c33 /*{c-body-link-hover}*/; } .ui-body-c .ui-link:active { - color: #2489CE /*{c-body-link-active}*/; + color: #c1272d /*{c-body-link-active}*/; } .ui-btn-up-c { - border: 1px solid #d6d6d6 /*{c-bup-border}*/; - background: #d6d6d6 /*{c-bup-background-color}*/; + border: 1px solid #cccccc /*{c-bup-border}*/; + background: #e6e6e6 /*{c-bup-background-color}*/; font-weight: bold; - color: #333333 /*{c-bup-color}*/; + color: #2F3E46 /*{c-bup-color}*/; text-shadow: 0 /*{c-bup-shadow-x}*/ 1px /*{c-bup-shadow-y}*/ 0 /*{c-bup-shadow-radius}*/ #ffffff /*{c-bup-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #dadada /*{c-bup-background-start}*/), to( #d1d1d1 /*{c-bup-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #dadada /*{c-bup-background-start}*/, #d1d1d1 /*{c-bup-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #dadada /*{c-bup-background-start}*/, #d1d1d1 /*{c-bup-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #dadada /*{c-bup-background-start}*/, #d1d1d1 /*{c-bup-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #dadada /*{c-bup-background-start}*/, #d1d1d1 /*{c-bup-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #dadada /*{c-bup-background-start}*/, #d1d1d1 /*{c-bup-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #e6e6e6 /*{c-bup-background-start}*/), to( #e6e6e6 /*{c-bup-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #e6e6e6 /*{c-bup-background-start}*/, #e6e6e6 /*{c-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #e6e6e6 /*{c-bup-background-start}*/, #e6e6e6 /*{c-bup-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #e6e6e6 /*{c-bup-background-start}*/, #e6e6e6 /*{c-bup-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #e6e6e6 /*{c-bup-background-start}*/, #e6e6e6 /*{c-bup-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #e6e6e6 /*{c-bup-background-start}*/, #e6e6e6 /*{c-bup-background-end}*/); } .ui-btn-up-c:visited, .ui-btn-up-c a.ui-link-inherit { - color: #333333 /*{c-bup-color}*/; + color: #2F3E46 /*{c-bup-color}*/; } .ui-btn-hover-c { - border: 1px solid #d6d6d6 /*{c-bhover-border}*/; - background: #d6d6d6 /*{c-bhover-background-color}*/; + border: 1px solid #bbbbbb /*{c-bhover-border}*/; + background: #dfdfdf /*{c-bhover-background-color}*/; font-weight: bold; - color: #000000 /*{c-bhover-color}*/; + color: #2F3E46 /*{c-bhover-color}*/; text-shadow: 0 /*{c-bhover-shadow-x}*/ 1px /*{c-bhover-shadow-y}*/ 0 /*{c-bhover-shadow-radius}*/ #ffffff /*{c-bhover-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #e9e9e9 /*{c-bhover-background-start}*/), to( #c2c2c2 /*{c-bhover-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #e9e9e9 /*{c-bhover-background-start}*/, #c2c2c2 /*{c-bhover-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #e9e9e9 /*{c-bhover-background-start}*/, #c2c2c2 /*{c-bhover-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #e9e9e9 /*{c-bhover-background-start}*/, #c2c2c2 /*{c-bhover-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #e9e9e9 /*{c-bhover-background-start}*/, #c2c2c2 /*{c-bhover-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #e9e9e9 /*{c-bhover-background-start}*/, #c2c2c2 /*{c-bhover-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #f6f6f6 /*{c-bhover-background-start}*/), to( #e0e0e0 /*{c-bhover-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); } .ui-btn-hover-c:visited, .ui-btn-hover-c:hover, .ui-btn-hover-c a.ui-link-inherit { - color: #000000 /*{c-bhover-color}*/; + color: #2F3E46 /*{c-bhover-color}*/; } .ui-btn-down-c { border: 1px solid #bbbbbb /*{c-bdown-border}*/; background: #d6d6d6 /*{c-bdown-background-color}*/; font-weight: bold; - color: #333333 /*{c-bdown-color}*/; + color: #2F3E46 /*{c-bdown-color}*/; text-shadow: 0 /*{c-bdown-shadow-x}*/ 1px /*{c-bdown-shadow-y}*/ 0 /*{c-bdown-shadow-radius}*/ #ffffff /*{c-bdown-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #bebebe /*{c-bdown-background-start}*/), to( #ededed /*{c-bdown-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #bebebe /*{c-bdown-background-start}*/, #ededed /*{c-bdown-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #bebebe /*{c-bdown-background-start}*/, #ededed /*{c-bdown-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #bebebe /*{c-bdown-background-start}*/, #ededed /*{c-bdown-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #bebebe /*{c-bdown-background-start}*/, #ededed /*{c-bdown-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #bebebe /*{c-bdown-background-start}*/, #ededed /*{c-bdown-background-end}*/); + background-image: -webkit-gradient(linear, left top, left bottom, from( #d0d0d0 /*{c-bdown-background-start}*/), to( #dfdfdf /*{c-bdown-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); } .ui-btn-down-c:visited, .ui-btn-down-c:hover, .ui-btn-down-c a.ui-link-inherit { - color: #333333 /*{c-bdown-color}*/; + color: #2F3E46 /*{c-bdown-color}*/; } .ui-btn-up-c, .ui-btn-hover-c, .ui-btn-down-c { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; text-decoration: none; } @@ -473,23 +475,23 @@ a.ui-link-inherit { } -/* Active class used as the "on" state across all themes +/* Bctive class used as the "on" state across all themes -----------------------------------------------------------------------------------------------------------*/ .ui-btn-active { - border: 1px solid #bc4b20 /*{global-active-border}*/; - background: #de4517 /*{global-active-background-color}*/; + border: 1px solid #9b1f23 /*{global-active-border}*/; + background: #9b1f23 /*{global-active-background-color}*/; font-weight: bold; color: #ffffff /*{global-active-color}*/; cursor: pointer; - text-shadow: 0 /*{global-active-shadow-x}*/ 1px /*{global-active-shadow-y}*/ 1px /*{global-active-shadow-radius}*/ #bc4b20 /*{global-active-shadow-color}*/; + text-shadow: 0 /*{global-active-shadow-x}*/ 1px /*{global-active-shadow-y}*/ 1px /*{global-active-shadow-radius}*/ #444444 /*{global-active-shadow-color}*/; text-decoration: none; - background-image: -webkit-gradient(linear, left top, left bottom, from( #de4517 /*{global-active-background-start}*/), to( #de4517 /*{global-active-background-end}*/)); /* Saf4 , Chrome */ - background-image: -webkit-linear-gradient( #de4517 /*{global-active-background-start}*/, #de4517 /*{global-active-background-end}*/); /* Chrome 10 , Saf5.1 */ - background-image: -moz-linear-gradient( #de4517 /*{global-active-background-start}*/, #de4517 /*{global-active-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #de4517 /*{global-active-background-start}*/, #de4517 /*{global-active-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #de4517 /*{global-active-background-start}*/, #de4517 /*{global-active-background-end}*/); /* Opera 11.10 */ - background-image: linear-gradient( #de4517 /*{global-active-background-start}*/, #de4517 /*{global-active-background-end}*/); - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; + background-image: -webkit-gradient(linear, left top, left bottom, from( #aa2226 /*{global-active-background-start}*/), to( #8b1b1f /*{global-active-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; } .ui-btn-active:visited, .ui-btn-active:hover, @@ -511,61 +513,61 @@ a.ui-link-inherit { -----------------------------------------------------------------------------------------------------------*/ .ui-corner-tl { - -moz-border-radius-topleft: 0 /*{global-radii-blocks}*/; - -webkit-border-top-left-radius: 0 /*{global-radii-blocks}*/; - border-top-left-radius: 0 /*{global-radii-blocks}*/; + -moz-border-radius-topleft: .6em /*{global-radii-blocks}*/; + -webkit-border-top-left-radius: .6em /*{global-radii-blocks}*/; + border-top-left-radius: .6em /*{global-radii-blocks}*/; } .ui-corner-tr { - -moz-border-radius-topright: 0 /*{global-radii-blocks}*/; - -webkit-border-top-right-radius: 0 /*{global-radii-blocks}*/; - border-top-right-radius: 0 /*{global-radii-blocks}*/; + -moz-border-radius-topright: .6em /*{global-radii-blocks}*/; + -webkit-border-top-right-radius: .6em /*{global-radii-blocks}*/; + border-top-right-radius: .6em /*{global-radii-blocks}*/; } .ui-corner-bl { - -moz-border-radius-bottomleft: 0 /*{global-radii-blocks}*/; - -webkit-border-bottom-left-radius: 0 /*{global-radii-blocks}*/; - border-bottom-left-radius: 0 /*{global-radii-blocks}*/; + -moz-border-radius-bottomleft: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-left-radius: .6em /*{global-radii-blocks}*/; + border-bottom-left-radius: .6em /*{global-radii-blocks}*/; } .ui-corner-br { - -moz-border-radius-bottomright: 0 /*{global-radii-blocks}*/; - -webkit-border-bottom-right-radius: 0 /*{global-radii-blocks}*/; - border-bottom-right-radius: 0 /*{global-radii-blocks}*/; + -moz-border-radius-bottomright: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/; + border-bottom-right-radius: .6em /*{global-radii-blocks}*/; } .ui-corner-top { - -moz-border-radius-topleft: 0 /*{global-radii-blocks}*/; - -webkit-border-top-left-radius: 0 /*{global-radii-blocks}*/; - border-top-left-radius: 0 /*{global-radii-blocks}*/; - -moz-border-radius-topright: 0 /*{global-radii-blocks}*/; - -webkit-border-top-right-radius: 0 /*{global-radii-blocks}*/; - border-top-right-radius: 0 /*{global-radii-blocks}*/; + -moz-border-radius-topleft: .6em /*{global-radii-blocks}*/; + -webkit-border-top-left-radius: .6em /*{global-radii-blocks}*/; + border-top-left-radius: .6em /*{global-radii-blocks}*/; + -moz-border-radius-topright: .6em /*{global-radii-blocks}*/; + -webkit-border-top-right-radius: .6em /*{global-radii-blocks}*/; + border-top-right-radius: .6em /*{global-radii-blocks}*/; } .ui-corner-bottom { - -moz-border-radius-bottomleft: 0 /*{global-radii-blocks}*/; - -webkit-border-bottom-left-radius: 0 /*{global-radii-blocks}*/; - border-bottom-left-radius: 0 /*{global-radii-blocks}*/; - -moz-border-radius-bottomright: 0 /*{global-radii-blocks}*/; - -webkit-border-bottom-right-radius: 0 /*{global-radii-blocks}*/; - border-bottom-right-radius: 0 /*{global-radii-blocks}*/; + -moz-border-radius-bottomleft: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-left-radius: .6em /*{global-radii-blocks}*/; + border-bottom-left-radius: .6em /*{global-radii-blocks}*/; + -moz-border-radius-bottomright: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/; + border-bottom-right-radius: .6em /*{global-radii-blocks}*/; } .ui-corner-right { - -moz-border-radius-topright: 0 /*{global-radii-blocks}*/; - -webkit-border-top-right-radius: 0 /*{global-radii-blocks}*/; - border-top-right-radius: 0 /*{global-radii-blocks}*/; - -moz-border-radius-bottomright: 0 /*{global-radii-blocks}*/; - -webkit-border-bottom-right-radius: 0 /*{global-radii-blocks}*/; - border-bottom-right-radius: 0 /*{global-radii-blocks}*/; + -moz-border-radius-topright: .6em /*{global-radii-blocks}*/; + -webkit-border-top-right-radius: .6em /*{global-radii-blocks}*/; + border-top-right-radius: .6em /*{global-radii-blocks}*/; + -moz-border-radius-bottomright: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/; + border-bottom-right-radius: .6em /*{global-radii-blocks}*/; } .ui-corner-left { - -moz-border-radius-topleft: 0 /*{global-radii-blocks}*/; - -webkit-border-top-left-radius: 0 /*{global-radii-blocks}*/; - border-top-left-radius: 0 /*{global-radii-blocks}*/; - -moz-border-radius-bottomleft: 0 /*{global-radii-blocks}*/; - -webkit-border-bottom-left-radius: 0 /*{global-radii-blocks}*/; - border-bottom-left-radius: 0 /*{global-radii-blocks}*/; + -moz-border-radius-topleft: .6em /*{global-radii-blocks}*/; + -webkit-border-top-left-radius: .6em /*{global-radii-blocks}*/; + border-top-left-radius: .6em /*{global-radii-blocks}*/; + -moz-border-radius-bottomleft: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-left-radius: .6em /*{global-radii-blocks}*/; + border-bottom-left-radius: .6em /*{global-radii-blocks}*/; } .ui-corner-all { - -moz-border-radius: 0 /*{global-radii-blocks}*/; - -webkit-border-radius: 0 /*{global-radii-blocks}*/; - border-radius: 0 /*{global-radii-blocks}*/; + -moz-border-radius: .6em /*{global-radii-blocks}*/; + -webkit-border-radius: .6em /*{global-radii-blocks}*/; + border-radius: .6em /*{global-radii-blocks}*/; } .ui-corner-none { -moz-border-radius: 0; @@ -585,24 +587,310 @@ a.ui-link-inherit { /* Interaction cues -----------------------------------------------------------------------------------------------------------*/ .ui-disabled { - filter: Alpha(Opacity=30); - opacity: .3; + opacity: .3; +} +.ui-disabled, +.ui-disabled a { + cursor: default !important; + pointer-events: none; +} +.ui-disabled .ui-btn-text { + -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=30)"; + filter: alpha(opacity=30); zoom: 1; } + +/* Icons +-----------------------------------------------------------------------------------------------------------*/ + +.ui-icon, +.ui-icon-searchfield:after { + background: #FFFFFF /*{global-icon-color}*/; + background: rgba(153,0,0,1) /*{global-icon-disc}*/; + background-image: url(images/icons-18-white.png) /*{global-icon-set}*/; + background-repeat: no-repeat; + -moz-border-radius: 9px; + -webkit-border-radius: 9px; + border-radius: 9px; +} + + +/* Blt icon color +-----------------------------------------------------------------------------------------------------------*/ + +.ui-icon-alt { + background: #fff; + background: rgba(255,255,255,.3); + background-image: url(images/icons-18-black.png); + background-repeat: no-repeat; +} + +/* HD/"retina" sprite +-----------------------------------------------------------------------------------------------------------*/ + +@media only screen and (-webkit-min-device-pixel-ratio: 1.5), + only screen and (min--moz-device-pixel-ratio: 1.5), + only screen and (min-resolution: 240dpi) { + + .ui-icon-plus, .ui-icon-minus, .ui-icon-delete, .ui-icon-arrow-r, + .ui-icon-arrow-l, .ui-icon-arrow-u, .ui-icon-arrow-d, .ui-icon-check, + .ui-icon-gear, .ui-icon-refresh, .ui-icon-forward, .ui-icon-back, + .ui-icon-grid, .ui-icon-star, .ui-icon-alert, .ui-icon-info, .ui-icon-home, .ui-icon-search, .ui-icon-searchfield:after, + .ui-icon-checkbox-off, .ui-icon-checkbox-on, .ui-icon-radio-off, .ui-icon-radio-on { + background-image: url(images/icons-36-white.png); + -moz-background-size: 776px 18px; + -o-background-size: 776px 18px; + -webkit-background-size: 776px 18px; + background-size: 776px 18px; + } + .ui-icon-alt { + background-image: url(images/icons-36-black.png); + } +} + +/* plus minus */ +.ui-icon-plus { + background-position: -0 50%; +} +.ui-icon-minus { + background-position: -36px 50%; +} + +/* delete/close */ +.ui-icon-delete { + background-position: -72px 50%; +} + +/* arrows */ +.ui-icon-arrow-r { + background-position: -108px 50%; +} +.ui-icon-arrow-l { + background-position: -144px 50%; +} +.ui-icon-arrow-u { + background-position: -180px 50%; +} +.ui-icon-arrow-d { + background-position: -216px 50%; +} + +/* misc */ +.ui-icon-check { + background-position: -252px 50%; +} +.ui-icon-gear { + background-position: -288px 50%; +} +.ui-icon-refresh { + background-position: -324px 50%; +} +.ui-icon-forward { + background-position: -360px 50%; +} +.ui-icon-back { + background-position: -396px 50%; +} +.ui-icon-grid { + background-position: -432px 50%; +} +.ui-icon-star { + background-position: -468px 50%; +} +.ui-icon-alert { + background-position: -504px 50%; +} +.ui-icon-info { + background-position: -540px 50%; +} +.ui-icon-home { + background-position: -576px 50%; +} +.ui-icon-search, +.ui-icon-searchfield:after { + background-position: -612px 50%; +} +.ui-icon-checkbox-off { + background-position: -684px 50%; +} +.ui-icon-checkbox-on { + background-position: -648px 50%; +} +.ui-icon-radio-off { + background-position: -756px 50%; +} +.ui-icon-radio-on { + background-position: -720px 50%; +} + + +/* checks,radios */ +.ui-checkbox .ui-icon { + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + border-radius: 3px; +} +.ui-icon-checkbox-off, +.ui-icon-radio-off { + background-color: transparent; +} +.ui-checkbox-on .ui-icon, +.ui-radio-on .ui-icon { + background-color: #9b1f23 /*{global-active-background-color}*/; /* NOTE: this hex should match the active state color. It's repeated here for cascade */ +} + +/* loading icon */ +.ui-icon-loading { + background: url(images/ajax-loader.gif); + background-size: 46px 46px; +} + + + + +/* Structure */ + +/* links within "buttons" +-----------------------------------------------------------------------------------------------------------*/ + +a.ui-link-inherit { + text-decoration: none !important; +} + + +/* Active class used as the "on" state across all themes +-----------------------------------------------------------------------------------------------------------*/ +.ui-btn-active { + border: 1px solid #9b1f23 /*{global-active-border}*/; + background: #9b1f23 /*{global-active-background-color}*/; + font-weight: bold; + color: #ffffff /*{global-active-color}*/; + cursor: pointer; + text-shadow: 0 /*{global-active-shadow-x}*/ 1px /*{global-active-shadow-y}*/ 1px /*{global-active-shadow-radius}*/ #444444 /*{global-active-shadow-color}*/; + text-decoration: none; + background-image: -webkit-gradient(linear, left top, left bottom, from( #aa2226 /*{global-active-background-start}*/), to( #8b1b1f /*{global-active-background-end}*/)); /* Saf4+, Chrome */ + background-image: -webkit-linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); /* Chrome 10+, Saf5.1+ */ + background-image: -moz-linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); /* FF3.6 */ + background-image: -ms-linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); /* IE10 */ + background-image: -o-linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); /* Opera 11.10+ */ + background-image: linear-gradient( #aa2226 /*{global-active-background-start}*/, #8b1b1f /*{global-active-background-end}*/); + font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; +} +.ui-btn-active:visited, +.ui-btn-active:hover, +.ui-btn-active a.ui-link-inherit { + color: #ffffff /*{global-active-color}*/; +} + + +/* button inner top highlight +-----------------------------------------------------------------------------------------------------------*/ + +.ui-btn-inner { + border-top: 1px solid #fff; + border-color: rgba(255,255,255,.3); +} + + +/* corner rounding classes +-----------------------------------------------------------------------------------------------------------*/ + +.ui-corner-tl { + -moz-border-radius-topleft: .6em /*{global-radii-blocks}*/; + -webkit-border-top-left-radius: .6em /*{global-radii-blocks}*/; + border-top-left-radius: .6em /*{global-radii-blocks}*/; +} +.ui-corner-tr { + -moz-border-radius-topright: .6em /*{global-radii-blocks}*/; + -webkit-border-top-right-radius: .6em /*{global-radii-blocks}*/; + border-top-right-radius: .6em /*{global-radii-blocks}*/; +} +.ui-corner-bl { + -moz-border-radius-bottomleft: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-left-radius: .6em /*{global-radii-blocks}*/; + border-bottom-left-radius: .6em /*{global-radii-blocks}*/; +} +.ui-corner-br { + -moz-border-radius-bottomright: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/; + border-bottom-right-radius: .6em /*{global-radii-blocks}*/; +} +.ui-corner-top { + -moz-border-radius-topleft: .6em /*{global-radii-blocks}*/; + -webkit-border-top-left-radius: .6em /*{global-radii-blocks}*/; + border-top-left-radius: .6em /*{global-radii-blocks}*/; + -moz-border-radius-topright: .6em /*{global-radii-blocks}*/; + -webkit-border-top-right-radius: .6em /*{global-radii-blocks}*/; + border-top-right-radius: .6em /*{global-radii-blocks}*/; +} +.ui-corner-bottom { + -moz-border-radius-bottomleft: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-left-radius: .6em /*{global-radii-blocks}*/; + border-bottom-left-radius: .6em /*{global-radii-blocks}*/; + -moz-border-radius-bottomright: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/; + border-bottom-right-radius: .6em /*{global-radii-blocks}*/; + } +.ui-corner-right { + -moz-border-radius-topright: .6em /*{global-radii-blocks}*/; + -webkit-border-top-right-radius: .6em /*{global-radii-blocks}*/; + border-top-right-radius: .6em /*{global-radii-blocks}*/; + -moz-border-radius-bottomright: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/; + border-bottom-right-radius: .6em /*{global-radii-blocks}*/; +} +.ui-corner-left { + -moz-border-radius-topleft: .6em /*{global-radii-blocks}*/; + -webkit-border-top-left-radius: .6em /*{global-radii-blocks}*/; + border-top-left-radius: .6em /*{global-radii-blocks}*/; + -moz-border-radius-bottomleft: .6em /*{global-radii-blocks}*/; + -webkit-border-bottom-left-radius: .6em /*{global-radii-blocks}*/; + border-bottom-left-radius: .6em /*{global-radii-blocks}*/; +} +.ui-corner-all { + -moz-border-radius: .6em /*{global-radii-blocks}*/; + -webkit-border-radius: .6em /*{global-radii-blocks}*/; + border-radius: .6em /*{global-radii-blocks}*/; +} +.ui-corner-none { + -moz-border-radius: 0; + -webkit-border-radius: 0; + border-radius: 0; +} + +/* Form field separator +-----------------------------------------------------------------------------------------------------------*/ +.ui-br { + border-bottom: rgb(130,130,130); + border-bottom: rgba(130,130,130,.3); + border-bottom-width: 1px; + border-bottom-style: solid; +} + +/* Interaction cues +-----------------------------------------------------------------------------------------------------------*/ +.ui-disabled { + opacity: .3; +} .ui-disabled, .ui-disabled a { cursor: default !important; pointer-events: none; } +.ui-disabled .ui-btn-text { + -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=30)"; + filter: alpha(opacity=30); + zoom: 1; +} /* Icons -----------------------------------------------------------------------------------------------------------*/ .ui-icon, .ui-icon-searchfield:after { - background: #000000 /*{global-icon-color}*/; - background: transparent /*{global-icon-disc}*/; - background-image: url(images/icons-18-black.png) /*{global-icon-set}*/; + background: #FFFFFF /*{global-icon-color}*/; + background: rgba(153,0,0,1) /*{global-icon-disc}*/; + background-image: url(images/icons-18-white.png) /*{global-icon-set}*/; background-repeat: no-repeat; -moz-border-radius: 9px; -webkit-border-radius: 9px; @@ -731,7 +1019,7 @@ a.ui-link-inherit { } .ui-checkbox-on .ui-icon, .ui-radio-on .ui-icon { - background-color: #de4517 /*{global-active-background-color}*/; /* NOTE: this hex should match the active state color. It's repeated here for cascade */ + background-color: #9b1f23 /*{global-active-background-color}*/; /* NOTE: this hex should match the active state color. It's repeated here for cascade */ } /* loading icon */ @@ -745,61 +1033,61 @@ a.ui-link-inherit { -----------------------------------------------------------------------------------------------------------*/ .ui-btn-corner-tl { - -moz-border-radius-topleft: 0 /*{global-radii-buttons}*/; - -webkit-border-top-left-radius: 0 /*{global-radii-buttons}*/; - border-top-left-radius: 0 /*{global-radii-buttons}*/; + -moz-border-radius-topleft: 1em /*{global-radii-buttons}*/; + -webkit-border-top-left-radius: 1em /*{global-radii-buttons}*/; + border-top-left-radius: 1em /*{global-radii-buttons}*/; } .ui-btn-corner-tr { - -moz-border-radius-topright: 0 /*{global-radii-buttons}*/; - -webkit-border-top-right-radius: 0 /*{global-radii-buttons}*/; - border-top-right-radius: 0 /*{global-radii-buttons}*/; + -moz-border-radius-topright: 1em /*{global-radii-buttons}*/; + -webkit-border-top-right-radius: 1em /*{global-radii-buttons}*/; + border-top-right-radius: 1em /*{global-radii-buttons}*/; } .ui-btn-corner-bl { - -moz-border-radius-bottomleft: 0 /*{global-radii-buttons}*/; - -webkit-border-bottom-left-radius: 0 /*{global-radii-buttons}*/; - border-bottom-left-radius: 0 /*{global-radii-buttons}*/; + -moz-border-radius-bottomleft: 1em /*{global-radii-buttons}*/; + -webkit-border-bottom-left-radius: 1em /*{global-radii-buttons}*/; + border-bottom-left-radius: 1em /*{global-radii-buttons}*/; } .ui-btn-corner-br { - -moz-border-radius-bottomright: 0 /*{global-radii-buttons}*/; - -webkit-border-bottom-right-radius: 0 /*{global-radii-buttons}*/; - border-bottom-right-radius: 0 /*{global-radii-buttons}*/; + -moz-border-radius-bottomright: 1em /*{global-radii-buttons}*/; + -webkit-border-bottom-right-radius: 1em /*{global-radii-buttons}*/; + border-bottom-right-radius: 1em /*{global-radii-buttons}*/; } .ui-btn-corner-top { - -moz-border-radius-topleft: 0 /*{global-radii-buttons}*/; - -webkit-border-top-left-radius: 0 /*{global-radii-buttons}*/; - border-top-left-radius: 0 /*{global-radii-buttons}*/; - -moz-border-radius-topright: 0 /*{global-radii-buttons}*/; - -webkit-border-top-right-radius: 0 /*{global-radii-buttons}*/; - border-top-right-radius: 0 /*{global-radii-buttons}*/; + -moz-border-radius-topleft: 1em /*{global-radii-buttons}*/; + -webkit-border-top-left-radius: 1em /*{global-radii-buttons}*/; + border-top-left-radius: 1em /*{global-radii-buttons}*/; + -moz-border-radius-topright: 1em /*{global-radii-buttons}*/; + -webkit-border-top-right-radius: 1em /*{global-radii-buttons}*/; + border-top-right-radius: 1em /*{global-radii-buttons}*/; } .ui-btn-corner-bottom { - -moz-border-radius-bottomleft: 0 /*{global-radii-buttons}*/; - -webkit-border-bottom-left-radius: 0 /*{global-radii-buttons}*/; - border-bottom-left-radius: 0 /*{global-radii-buttons}*/; - -moz-border-radius-bottomright: 0 /*{global-radii-buttons}*/; - -webkit-border-bottom-right-radius: 0 /*{global-radii-buttons}*/; - border-bottom-right-radius: 0 /*{global-radii-buttons}*/; + -moz-border-radius-bottomleft: 1em /*{global-radii-buttons}*/; + -webkit-border-bottom-left-radius: 1em /*{global-radii-buttons}*/; + border-bottom-left-radius: 1em /*{global-radii-buttons}*/; + -moz-border-radius-bottomright: 1em /*{global-radii-buttons}*/; + -webkit-border-bottom-right-radius: 1em /*{global-radii-buttons}*/; + border-bottom-right-radius: 1em /*{global-radii-buttons}*/; } .ui-btn-corner-right { - -moz-border-radius-topright: 0 /*{global-radii-buttons}*/; - -webkit-border-top-right-radius: 0 /*{global-radii-buttons}*/; - border-top-right-radius: 0 /*{global-radii-buttons}*/; - -moz-border-radius-bottomright: 0 /*{global-radii-buttons}*/; - -webkit-border-bottom-right-radius: 0 /*{global-radii-buttons}*/; - border-bottom-right-radius: 0 /*{global-radii-buttons}*/; + -moz-border-radius-topright: 1em /*{global-radii-buttons}*/; + -webkit-border-top-right-radius: 1em /*{global-radii-buttons}*/; + border-top-right-radius: 1em /*{global-radii-buttons}*/; + -moz-border-radius-bottomright: 1em /*{global-radii-buttons}*/; + -webkit-border-bottom-right-radius: 1em /*{global-radii-buttons}*/; + border-bottom-right-radius: 1em /*{global-radii-buttons}*/; } .ui-btn-corner-left { - -moz-border-radius-topleft: 0 /*{global-radii-buttons}*/; - -webkit-border-top-left-radius: 0 /*{global-radii-buttons}*/; - border-top-left-radius: 0 /*{global-radii-buttons}*/; - -moz-border-radius-bottomleft: 0 /*{global-radii-buttons}*/; - -webkit-border-bottom-left-radius: 0 /*{global-radii-buttons}*/; - border-bottom-left-radius: 0 /*{global-radii-buttons}*/; + -moz-border-radius-topleft: 1em /*{global-radii-buttons}*/; + -webkit-border-top-left-radius: 1em /*{global-radii-buttons}*/; + border-top-left-radius: 1em /*{global-radii-buttons}*/; + -moz-border-radius-bottomleft: 1em /*{global-radii-buttons}*/; + -webkit-border-bottom-left-radius: 1em /*{global-radii-buttons}*/; + border-bottom-left-radius: 1em /*{global-radii-buttons}*/; } .ui-btn-corner-all { - -moz-border-radius: 0 /*{global-radii-buttons}*/; - -webkit-border-radius: 0 /*{global-radii-buttons}*/; - border-radius: 0 /*{global-radii-buttons}*/; + -moz-border-radius: 1em /*{global-radii-buttons}*/; + -webkit-border-radius: 1em /*{global-radii-buttons}*/; + border-radius: 1em /*{global-radii-buttons}*/; } /* radius clip workaround for cleaning up corner trapping */ @@ -831,8 +1119,8 @@ a.ui-link-inherit { .ui-overlay { background: #666; - filter: Alpha(Opacity=50); opacity: .5; + filter: Alpha(Opacity=50); position: absolute; width: 100%; height: 100%; @@ -860,9 +1148,9 @@ a.ui-link-inherit { box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); } .ui-icon-shadow { - -moz-box-shadow: 0px 1px 0 transparent /*{global-icon-shadow}*/; - -webkit-box-shadow: 0px 1px 0 transparent /*{global-icon-shadow}*/; - box-shadow: 0px 1px 0 transparent /*{global-icon-shadow}*/; + -moz-box-shadow: 0px 1px 0 rgba(255,255,255,.4) /*{global-icon-shadow}*/; + -webkit-box-shadow: 0px 1px 0 rgba(255,255,255,.4) /*{global-icon-shadow}*/; + box-shadow: 0px 1px 0 rgba(255,255,255,.4) /*{global-icon-shadow}*/; } /* Focus state - set here for specificity (note: these classes are added by JavaScript) @@ -876,15 +1164,15 @@ a.ui-link-inherit { } .ui-focus, .ui-btn:focus { - -moz-box-shadow: inset 0px 0px 3px #de4517 /*{global-active-background-color}*/, 0px 0px 9px #de4517 /*{global-active-background-color}*/; - -webkit-box-shadow: inset 0px 0px 3px #de4517 /*{global-active-background-color}*/, 0px 0px 9px #de4517 /*{global-active-background-color}*/; - box-shadow: inset 0px 0px 3px #de4517 /*{global-active-background-color}*/, 0px 0px 9px #de4517 /*{global-active-background-color}*/; + -moz-box-shadow: inset 0px 0px 3px #9b1f23 /*{global-active-background-color}*/, 0px 0px 9px #9b1f23 /*{global-active-background-color}*/; + -webkit-box-shadow: inset 0px 0px 3px #9b1f23 /*{global-active-background-color}*/, 0px 0px 9px #9b1f23 /*{global-active-background-color}*/; + box-shadow: inset 0px 0px 3px #9b1f23 /*{global-active-background-color}*/, 0px 0px 9px #9b1f23 /*{global-active-background-color}*/; } .ui-input-text.ui-focus, .ui-input-search.ui-focus { - -moz-box-shadow: 0px 0px 12px #de4517 /*{global-active-background-color}*/; - -webkit-box-shadow: 0px 0px 12px #de4517 /*{global-active-background-color}*/; - box-shadow: 0px 0px 12px #de4517 /*{global-active-background-color}*/; + -moz-box-shadow: 0px 0px 12px #9b1f23 /*{global-active-background-color}*/; + -webkit-box-shadow: 0px 0px 12px #9b1f23 /*{global-active-background-color}*/; + box-shadow: 0px 0px 12px #9b1f23 /*{global-active-background-color}*/; } /* unset box shadow in browsers that don't do it right @@ -903,4 +1191,3 @@ a.ui-link-inherit { outline-width: 1px; outline-style: auto; } - \ No newline at end of file diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.min.css b/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.min.css index e128c374f0d46fe1277b2bb3e5e97c1680aced98..799f875b66e41e3d5b8033f3abd8b20639877f2e 100644 --- a/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.min.css +++ b/dspace-xmlui/src/main/webapp/themes/mobile/lib/sc-mobile.min.css @@ -1,9 +1,12 @@ /* -* jQuery Mobile Framework 1.1.2 9a15f1aaf99faa7913103f5ea19ef6959b73d763 +* jQuery Mobile Framework 1.1.1 1981b3f5ec22675ae47df8f0bdf9622e7780e90e * http://jquerymobile.com * -* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors -* Released under the MIT license. +* Copyright 2012 jQuery Foundation and other contributors +* Dual licensed under the MIT or GPL Version 2 licenses. * http://jquery.org/license +* +* This compressed file is the one referenced in the mobile.xsl file in the mobile theme folder * -*/.ui-bar-a{border:1px solid #ffffff ;background:#ffffff ;color:#000000 ;font-weight:bold;text-shadow:0 1px 1px #eeeeee ;background-image:-webkit-gradient(linear,left top,left bottom,from( #FFFFFF ),to( #e5e5e5 )); background-image:-webkit-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: -moz-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: -ms-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: -o-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: linear-gradient( #FFFFFF,#e5e5e5 );}.ui-bar-a .ui-link-inherit{color:#000000 ;}.ui-bar-a a.ui-link{color:#7cc4e7 ;font-weight:bold;}.ui-bar-a a.ui-link:visited{ color:#2489CE ;}.ui-bar-a a.ui-link:hover{color:#2489CE ;}.ui-bar-a a.ui-link:active{color:#2489CE ;}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-a,.ui-overlay-a{border:1px solid #d6d6d6 ;color:#333333 ;text-shadow:0 1px 0 #ffffff ;background:#ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #FFFFFF ),to( #f9f9f9 )); background-image:-webkit-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: -moz-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: -ms-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: -o-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: linear-gradient( #FFFFFF,#f9f9f9 );}.ui-overlay-a{background-image:none;border-width:0;}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-a .ui-link-inherit{color:#333333 ;}.ui-body-a .ui-link{color:#bc4b20 ;font-weight:bold;}.ui-body-a .ui-link:visited{ color:#2489CE ;}.ui-body-a .ui-link:hover{color:#2489CE ;}.ui-body-a .ui-link:active{color:#2489CE ;}.ui-btn-up-a{border:1px solid #d6d6d6 ;background:#d6d6d6 ;font-weight:bold;color:#333333 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #dadada ),to( #d1d1d1 )); background-image:-webkit-linear-gradient( #dadada,#d1d1d1 ); background-image: -moz-linear-gradient( #dadada,#d1d1d1 ); background-image: -ms-linear-gradient( #dadada,#d1d1d1 ); background-image: -o-linear-gradient( #dadada,#d1d1d1 ); background-image: linear-gradient( #dadada,#d1d1d1 );}.ui-btn-up-a:visited,.ui-btn-up-a a.ui-link-inherit{color:#333333 ;}.ui-btn-hover-a{border:1px solid #d6d6d6 ;background:#d6d6d6 ;font-weight:bold;color:#000000 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #e9e9e9 ),to( #c2c2c2 )); background-image:-webkit-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: -moz-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: -ms-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: -o-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: linear-gradient( #e9e9e9,#c2c2c2 );}.ui-btn-hover-a:visited,.ui-btn-hover-a:hover,.ui-btn-hover-a a.ui-link-inherit{color:#000000 ;}.ui-btn-down-a{border:1px solid #bbbbbb ;background:#d6d6d6 ;font-weight:bold;color:#333333 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #bebebe ),to( #ededed )); background-image:-webkit-linear-gradient( #bebebe,#ededed ); background-image: -moz-linear-gradient( #bebebe,#ededed ); background-image: -ms-linear-gradient( #bebebe,#ededed ); background-image: -o-linear-gradient( #bebebe,#ededed ); background-image: linear-gradient( #bebebe,#ededed );}.ui-btn-down-a:visited,.ui-btn-down-a:hover,.ui-btn-down-a a.ui-link-inherit{color:#333333 ;}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{ font-family:Helvetica,Arial,sans-serif ;text-decoration:none;}.ui-bar-b{border:1px solid #ffffff ;background:#ffffff ;color:#000000 ;font-weight:bold;text-shadow:0 1px 1px #eeeeee ;background-image:-webkit-gradient(linear,left top,left bottom,from( #FFFFFF ),to( #e5e5e5 )); background-image:-webkit-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: -moz-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: -ms-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: -o-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: linear-gradient( #FFFFFF,#e5e5e5 );}.ui-bar-b .ui-link-inherit{color:#000000 ;}.ui-bar-b a.ui-link{color:#7cc4e7 ;font-weight:bold;}.ui-bar-b a.ui-link:visited{ color:#2489CE ;}.ui-bar-b a.ui-link:hover{color:#2489CE ;}.ui-bar-b a.ui-link:active{color:#2489CE ;}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-b,.ui-overlay-b{border:1px solid #d6d6d6 ;color:#333333 ;text-shadow:0 1px 0 #ffffff ;background:#ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #FFFFFF ),to( #f9f9f9 )); background-image:-webkit-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: -moz-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: -ms-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: -o-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: linear-gradient( #FFFFFF,#f9f9f9 );}.ui-overlay-b{background-image:none;border-width:0;}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-b .ui-link-inherit{color:#333333 ;}.ui-body-b .ui-link{color:#bc4b20 ;font-weight:bold;}.ui-body-b .ui-link:visited{ color:#2489CE ;}.ui-body-b .ui-link:hover{color:#2489CE ;}.ui-body-b .ui-link:active{color:#2489CE ;}.ui-btn-up-b{border:1px solid #d6d6d6 ;background:#d6d6d6 ;font-weight:bold;color:#333333 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #dadada ),to( #d1d1d1 )); background-image:-webkit-linear-gradient( #dadada,#d1d1d1 ); background-image: -moz-linear-gradient( #dadada,#d1d1d1 ); background-image: -ms-linear-gradient( #dadada,#d1d1d1 ); background-image: -o-linear-gradient( #dadada,#d1d1d1 ); background-image: linear-gradient( #dadada,#d1d1d1 );}.ui-btn-up-b:visited,.ui-btn-up-b a.ui-link-inherit{color:#333333 ;}.ui-btn-hover-b{border:1px solid #d6d6d6 ;background:#d6d6d6 ;font-weight:bold;color:#000000 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #e9e9e9 ),to( #c2c2c2 )); background-image:-webkit-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: -moz-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: -ms-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: -o-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: linear-gradient( #e9e9e9,#c2c2c2 );}.ui-btn-hover-b:visited,.ui-btn-hover-b:hover,.ui-btn-hover-b a.ui-link-inherit{color:#000000 ;}.ui-btn-down-b{border:1px solid #bbbbbb ;background:#d6d6d6 ;font-weight:bold;color:#333333 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #bebebe ),to( #ededed )); background-image:-webkit-linear-gradient( #bebebe,#ededed ); background-image: -moz-linear-gradient( #bebebe,#ededed ); background-image: -ms-linear-gradient( #bebebe,#ededed ); background-image: -o-linear-gradient( #bebebe,#ededed ); background-image: linear-gradient( #bebebe,#ededed );}.ui-btn-down-b:visited,.ui-btn-down-b:hover,.ui-btn-down-b a.ui-link-inherit{color:#333333 ;}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{ font-family:Helvetica,Arial,sans-serif ;text-decoration:none;}.ui-bar-c{border:1px solid #ffffff ;background:#ffffff ;color:#000000 ;font-weight:bold;text-shadow:0 1px 1px #eeeeee ;background-image:-webkit-gradient(linear,left top,left bottom,from( #FFFFFF ),to( #e5e5e5 )); background-image:-webkit-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: -moz-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: -ms-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: -o-linear-gradient( #FFFFFF,#e5e5e5 ); background-image: linear-gradient( #FFFFFF,#e5e5e5 );}.ui-bar-c .ui-link-inherit{color:#000000 ;}.ui-bar-c a.ui-link{color:#7cc4e7 ;font-weight:bold;}.ui-bar-c a.ui-link:visited{ color:#2489CE ;}.ui-bar-c a.ui-link:hover{color:#2489CE ;}.ui-bar-c a.ui-link:active{color:#2489CE ;}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-c,.ui-overlay-c{border:1px solid #d6d6d6 ;color:#333333 ;text-shadow:0 1px 0 #ffffff ;background:#ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #FFFFFF ),to( #f9f9f9 )); background-image:-webkit-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: -moz-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: -ms-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: -o-linear-gradient( #FFFFFF,#f9f9f9 ); background-image: linear-gradient( #FFFFFF,#f9f9f9 );}.ui-overlay-c{background-image:none;border-width:0;}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-c .ui-link-inherit{color:#333333 ;}.ui-body-c .ui-link{color:#bc4b20 ;font-weight:bold;}.ui-body-c .ui-link:visited{ color:#2489CE ;}.ui-body-c .ui-link:hover{color:#2489CE ;}.ui-body-c .ui-link:active{color:#2489CE ;}.ui-btn-up-c{border:1px solid #d6d6d6 ;background:#d6d6d6 ;font-weight:bold;color:#333333 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #dadada ),to( #d1d1d1 )); background-image:-webkit-linear-gradient( #dadada,#d1d1d1 ); background-image: -moz-linear-gradient( #dadada,#d1d1d1 ); background-image: -ms-linear-gradient( #dadada,#d1d1d1 ); background-image: -o-linear-gradient( #dadada,#d1d1d1 ); background-image: linear-gradient( #dadada,#d1d1d1 );}.ui-btn-up-c:visited,.ui-btn-up-c a.ui-link-inherit{color:#333333 ;}.ui-btn-hover-c{border:1px solid #d6d6d6 ;background:#d6d6d6 ;font-weight:bold;color:#000000 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #e9e9e9 ),to( #c2c2c2 )); background-image:-webkit-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: -moz-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: -ms-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: -o-linear-gradient( #e9e9e9,#c2c2c2 ); background-image: linear-gradient( #e9e9e9,#c2c2c2 );}.ui-btn-hover-c:visited,.ui-btn-hover-c:hover,.ui-btn-hover-c a.ui-link-inherit{color:#000000 ;}.ui-btn-down-c{border:1px solid #bbbbbb ;background:#d6d6d6 ;font-weight:bold;color:#333333 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #bebebe ),to( #ededed )); background-image:-webkit-linear-gradient( #bebebe,#ededed ); background-image: -moz-linear-gradient( #bebebe,#ededed ); background-image: -ms-linear-gradient( #bebebe,#ededed ); background-image: -o-linear-gradient( #bebebe,#ededed ); background-image: linear-gradient( #bebebe,#ededed );}.ui-btn-down-c:visited,.ui-btn-down-c:hover,.ui-btn-down-c a.ui-link-inherit{color:#333333 ;}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{ font-family:Helvetica,Arial,sans-serif ;text-decoration:none;}a.ui-link-inherit{text-decoration:none !important;}.ui-btn-active{border:1px solid #bc4b20 ;background:#de4517 ;font-weight:bold;color:#ffffff ;cursor:pointer;text-shadow:0 1px 1px #bc4b20 ;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from( #de4517 ),to( #de4517 )); background-image:-webkit-linear-gradient( #de4517,#de4517 ); background-image: -moz-linear-gradient( #de4517,#de4517 ); background-image: -ms-linear-gradient( #de4517,#de4517 ); background-image: -o-linear-gradient( #de4517,#de4517 ); background-image: linear-gradient( #de4517,#de4517 ); font-family:Helvetica,Arial,sans-serif ;}.ui-btn-active:visited,.ui-btn-active:hover,.ui-btn-active a.ui-link-inherit{color:#ffffff ;}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3);}.ui-corner-tl{-moz-border-radius-topleft:0 ;-webkit-border-top-left-radius:0 ;border-top-left-radius:0 ;}.ui-corner-tr{-moz-border-radius-topright:0 ;-webkit-border-top-right-radius:0 ;border-top-right-radius:0 ;}.ui-corner-bl{-moz-border-radius-bottomleft:0 ;-webkit-border-bottom-left-radius:0 ;border-bottom-left-radius:0 ;}.ui-corner-br{-moz-border-radius-bottomright:0 ;-webkit-border-bottom-right-radius:0 ;border-bottom-right-radius:0 ;}.ui-corner-top{-moz-border-radius-topleft:0 ;-webkit-border-top-left-radius:0 ;border-top-left-radius:0 ;-moz-border-radius-topright:0 ;-webkit-border-top-right-radius:0 ;border-top-right-radius:0 ;}.ui-corner-bottom{-moz-border-radius-bottomleft:0 ;-webkit-border-bottom-left-radius:0 ;border-bottom-left-radius:0 ;-moz-border-radius-bottomright:0 ;-webkit-border-bottom-right-radius:0 ;border-bottom-right-radius:0 ;}.ui-corner-right{-moz-border-radius-topright:0 ;-webkit-border-top-right-radius:0 ;border-top-right-radius:0 ;-moz-border-radius-bottomright:0 ;-webkit-border-bottom-right-radius:0 ;border-bottom-right-radius:0 ;}.ui-corner-left{-moz-border-radius-topleft:0 ;-webkit-border-top-left-radius:0 ;border-top-left-radius:0 ;-moz-border-radius-bottomleft:0 ;-webkit-border-bottom-left-radius:0 ;border-bottom-left-radius:0 ;}.ui-corner-all{-moz-border-radius:0 ;-webkit-border-radius:0 ;border-radius:0 ;}.ui-corner-none{-moz-border-radius: 0;-webkit-border-radius: 0;border-radius: 0;}.ui-br{border-bottom:rgb(130,130,130);border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid;}.ui-disabled{filter:Alpha(Opacity=30);opacity:.3;zoom:1;}.ui-disabled,.ui-disabled a{cursor:default !important;pointer-events:none;}.ui-icon,.ui-icon-searchfield:after{background:#000000 ;background:transparent ;background-image:url(images/icons-18-black.png) ;background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px;}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat;}@media only screen and (-webkit-min-device-pixel-ratio:1.5), only screen and (min--moz-device-pixel-ratio:1.5), only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px;}.ui-icon-alt{background-image:url(images/icons-36-black.png);}}.ui-icon-plus{background-position:-0 50%;}.ui-icon-minus{background-position:-36px 50%;}.ui-icon-delete{background-position:-72px 50%;}.ui-icon-arrow-r{background-position:-108px 50%;}.ui-icon-arrow-l{background-position:-144px 50%;}.ui-icon-arrow-u{background-position:-180px 50%;}.ui-icon-arrow-d{background-position:-216px 50%;}.ui-icon-check{background-position:-252px 50%;}.ui-icon-gear{background-position:-288px 50%;}.ui-icon-refresh{background-position:-324px 50%;}.ui-icon-forward{background-position:-360px 50%;}.ui-icon-back{background-position:-396px 50%;}.ui-icon-grid{background-position:-432px 50%;}.ui-icon-star{background-position:-468px 50%;}.ui-icon-alert{background-position:-504px 50%;}.ui-icon-info{background-position:-540px 50%;}.ui-icon-home{background-position:-576px 50%;}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%;}.ui-icon-checkbox-off{background-position:-684px 50%;}.ui-icon-checkbox-on{background-position:-648px 50%;}.ui-icon-radio-off{background-position:-756px 50%;}.ui-icon-radio-on{background-position:-720px 50%;}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent;}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#de4517 ; }.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:46px 46px;}.ui-btn-corner-tl{-moz-border-radius-topleft:0 ;-webkit-border-top-left-radius:0 ;border-top-left-radius:0 ;}.ui-btn-corner-tr{-moz-border-radius-topright:0 ;-webkit-border-top-right-radius:0 ;border-top-right-radius:0 ;}.ui-btn-corner-bl{-moz-border-radius-bottomleft:0 ;-webkit-border-bottom-left-radius:0 ;border-bottom-left-radius:0 ;}.ui-btn-corner-br{-moz-border-radius-bottomright:0 ;-webkit-border-bottom-right-radius:0 ;border-bottom-right-radius:0 ;}.ui-btn-corner-top{-moz-border-radius-topleft:0 ;-webkit-border-top-left-radius:0 ;border-top-left-radius:0 ;-moz-border-radius-topright:0 ;-webkit-border-top-right-radius:0 ;border-top-right-radius:0 ;}.ui-btn-corner-bottom{-moz-border-radius-bottomleft:0 ;-webkit-border-bottom-left-radius:0 ;border-bottom-left-radius:0 ;-moz-border-radius-bottomright:0 ;-webkit-border-bottom-right-radius:0 ;border-bottom-right-radius:0 ;}.ui-btn-corner-right{-moz-border-radius-topright:0 ;-webkit-border-top-right-radius:0 ;border-top-right-radius:0 ;-moz-border-radius-bottomright:0 ;-webkit-border-bottom-right-radius:0 ;border-bottom-right-radius:0 ;}.ui-btn-corner-left{-moz-border-radius-topleft:0 ;-webkit-border-top-left-radius:0 ;border-top-left-radius:0 ;-moz-border-radius-bottomleft:0 ;-webkit-border-bottom-left-radius:0 ;border-bottom-left-radius:0 ;}.ui-btn-corner-all{-moz-border-radius:0 ;-webkit-border-radius:0 ;border-radius:0 ;}.ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{ -webkit-background-clip:padding-box; -moz-background-clip:padding; background-clip:padding-box;}.ui-overlay{background:#666;filter:Alpha(Opacity=50);opacity:.5;position:absolute;width:100%;height:100%;}.ui-overlay-shadow{-moz-box-shadow:0px 0px 12px rgba(0,0,0,.6);-webkit-box-shadow:0px 0px 12px rgba(0,0,0,.6);box-shadow:0px 0px 12px rgba(0,0,0,.6);}.ui-shadow{-moz-box-shadow:0px 1px 4px rgba(0,0,0,.3) ;-webkit-box-shadow:0px 1px 4px rgba(0,0,0,.3) ;box-shadow:0px 1px 4px rgba(0,0,0,.3) ;}.ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow {-moz-box-shadow:0px 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0px 1px 0 rgba(255,255,255,.3);box-shadow:0px 1px 0 rgba(255,255,255,.3);}.ui-shadow-inset{-moz-box-shadow:inset 0px 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0px 1px 4px rgba(0,0,0,.2);box-shadow:inset 0px 1px 4px rgba(0,0,0,.2);}.ui-icon-shadow{-moz-box-shadow:0px 1px 0 transparent ;-webkit-box-shadow:0px 1px 0 transparent ;box-shadow:0px 1px 0 transparent ;}.ui-btn:focus,.ui-link-inherit:focus{outline:0;}.ui-btn.ui-focus{z-index:1;}.ui-focus,.ui-btn:focus{-moz-box-shadow:inset 0px 0px 3px #de4517,0px 0px 9px #de4517 ;-webkit-box-shadow:inset 0px 0px 3px #de4517,0px 0px 9px #de4517 ;box-shadow:inset 0px 0px 3px #de4517,0px 0px 9px #de4517 ;}.ui-input-text.ui-focus,.ui-input-search.ui-focus{-moz-box-shadow:0px 0px 12px #de4517 ;-webkit-box-shadow:0px 0px 12px #de4517 ;box-shadow:0px 0px 12px #de4517 ;}.ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none !important;-webkit-box-shadow:none !important;box-shadow:none !important;}.ui-mobile-nosupport-boxshadow .ui-focus,.ui-mobile-nosupport-boxshadow .ui-btn:focus,.ui-mobile-nosupport-boxshadow .ui-link-inherit:focus{outline-width:1px;outline-style:auto;} \ No newline at end of file +* +*/.ui-bar-a{border:1px solid #424242 ;background:#9b1f23 ;color:#ffffff ;font-weight:bold;text-shadow:0 1px 1px #444444 ;background-image:-webkit-gradient(linear,left top,left bottom,from( #9b1f23 ),to( #660000 )); background-image:-webkit-linear-gradient( #9b1f23,#660000 ); background-image: -moz-linear-gradient( #9b1f23,#660000 ); background-image: -ms-linear-gradient( #9b1f23,#660000 ); background-image: -o-linear-gradient( #9b1f23,#660000 ); background-image: linear-gradient( #9b1f23,#660000 );}.ui-bar-a .ui-link-inherit{color:#ffffff ;}.ui-bar-a a.ui-link{color:#7cc4e7 ;font-weight:bold;}.ui-bar-a a.ui-link:visited{ color:#2489CE ;}.ui-bar-a a.ui-link:hover{color:#2489CE ;}.ui-bar-a a.ui-link:active{color:#2489CE ;}.ui-bar-a,.ui-bar-a input,.ui-bar-a select,.ui-bar-a textarea,.ui-bar-a button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-a,.ui-overlay-a{border:1px solid #aaaaaa ;color:#333333 ;text-shadow:0 0px 0 #ffffff ;background:#ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #ffffff ),to( #ffffff )); background-image:-webkit-linear-gradient( #ffffff,#ffffff ); background-image: -moz-linear-gradient( #ffffff,#ffffff ); background-image: -ms-linear-gradient( #ffffff,#ffffff ); background-image: -o-linear-gradient( #ffffff,#ffffff ); background-image: linear-gradient( #ffffff,#ffffff );}.ui-overlay-a{background-image:none;border-width:0;}.ui-body-a,.ui-body-a input,.ui-body-a select,.ui-body-a textarea,.ui-body-a button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-a .ui-link-inherit{color:#333333 ;}.ui-body-a .ui-link{color:#c1272d ;font-weight:bold;}.ui-body-a .ui-link:visited{ color:#c1272d ;}.ui-body-a .ui-link:hover{color:#dd2c33 ;}.ui-body-a .ui-link:active{color:#c1272d ;}.ui-btn-up-a{border:1px solid #cccccc ;background:#e6e6e6 ;font-weight:bold;color:#2F3E46 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #e6e6e6 ),to( #e6e6e6 )); background-image:-webkit-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: -moz-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: -ms-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: -o-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: linear-gradient( #e6e6e6,#e6e6e6 );}.ui-btn-up-a:visited,.ui-btn-up-a a.ui-link-inherit{color:#2F3E46 ;}.ui-btn-hover-a{border:1px solid #bbbbbb ;background:#dfdfdf ;font-weight:bold;color:#2F3E46 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #f6f6f6 ),to( #e0e0e0 )); background-image:-webkit-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: -moz-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: -ms-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: -o-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: linear-gradient( #f6f6f6,#e0e0e0 );}.ui-btn-hover-a:visited,.ui-btn-hover-a:hover,.ui-btn-hover-a a.ui-link-inherit{color:#2F3E46 ;}.ui-btn-down-a{border:1px solid #bbbbbb ;background:#d6d6d6 ;font-weight:bold;color:#2F3E46 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #d0d0d0 ),to( #dfdfdf )); background-image:-webkit-linear-gradient( #d0d0d0,#dfdfdf ); background-image: -moz-linear-gradient( #d0d0d0,#dfdfdf ); background-image: -ms-linear-gradient( #d0d0d0,#dfdfdf ); background-image: -o-linear-gradient( #d0d0d0,#dfdfdf ); background-image: linear-gradient( #d0d0d0,#dfdfdf );}.ui-btn-down-a:visited,.ui-btn-down-a:hover,.ui-btn-down-a a.ui-link-inherit{color:#2F3E46 ;}.ui-btn-up-a,.ui-btn-hover-a,.ui-btn-down-a{ font-family:Helvetica,Arial,sans-serif ;text-decoration:none;}.ui-bar-b{border:1px solid #424242 ;background:#9b1f23 ;color:#ffffff ;font-weight:bold;text-shadow:0 1px 1px #444444 ;background-image:-webkit-gradient(linear,left top,left bottom,from( #9b1f23 ),to( #660000 )); background-image:-webkit-linear-gradient( #9b1f23,#660000 ); background-image: -moz-linear-gradient( #9b1f23,#660000 ); background-image: -ms-linear-gradient( #9b1f23,#660000 ); background-image: -o-linear-gradient( #9b1f23,#660000 ); background-image: linear-gradient( #9b1f23,#660000 );}.ui-bar-b .ui-link-inherit{color:#ffffff ;}.ui-bar-b a.ui-link{color:#7cc4e7 ;font-weight:bold;}.ui-bar-b a.ui-link:visited{ color:#2489CE ;}.ui-bar-b a.ui-link:hover{color:#2489CE ;}.ui-bar-b a.ui-link:active{color:#2489CE ;}.ui-bar-b,.ui-bar-b input,.ui-bar-b select,.ui-bar-b textarea,.ui-bar-b button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-b,.ui-overlay-b{border:1px solid #aaaaaa ;color:#333333 ;text-shadow:0 0px 0 #ffffff ;background:#ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #ffffff ),to( #ffffff )); background-image:-webkit-linear-gradient( #ffffff,#ffffff ); background-image: -moz-linear-gradient( #ffffff,#ffffff ); background-image: -ms-linear-gradient( #ffffff,#ffffff ); background-image: -o-linear-gradient( #ffffff,#ffffff ); background-image: linear-gradient( #ffffff,#ffffff );}.ui-overlay-b{background-image:none;border-width:0;}.ui-body-b,.ui-body-b input,.ui-body-b select,.ui-body-b textarea,.ui-body-b button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-b .ui-link-inherit{color:#333333 ;}.ui-body-b .ui-link{color:#c1272d ;font-weight:bold;}.ui-body-b .ui-link:visited{ color:#c1272d ;}.ui-body-b .ui-link:hover{color:#dd2c33 ;}.ui-body-b .ui-link:active{color:#c1272d ;}.ui-btn-up-b{border:1px solid #cccccc ;background:#e6e6e6 ;font-weight:bold;color:#2F3E46 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #e6e6e6 ),to( #e6e6e6 )); background-image:-webkit-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: -moz-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: -ms-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: -o-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: linear-gradient( #e6e6e6,#e6e6e6 );}.ui-btn-up-b:visited,.ui-btn-up-b a.ui-link-inherit{color:#2F3E46 ;}.ui-btn-hover-b{border:1px solid #bbbbbb ;background:#dfdfdf ;font-weight:bold;color:#2F3E46 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #f6f6f6 ),to( #e0e0e0 )); background-image:-webkit-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: -moz-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: -ms-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: -o-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: linear-gradient( #f6f6f6,#e0e0e0 );}.ui-btn-hover-b:visited,.ui-btn-hover-b:hover,.ui-btn-hover-b a.ui-link-inherit{color:#2F3E46 ;}.ui-btn-down-b{border:1px solid #bbbbbb ;background:#d6d6d6 ;font-weight:bold;color:#2F3E46 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #d0d0d0 ),to( #dfdfdf )); background-image:-webkit-linear-gradient( #d0d0d0,#dfdfdf ); background-image: -moz-linear-gradient( #d0d0d0,#dfdfdf ); background-image: -ms-linear-gradient( #d0d0d0,#dfdfdf ); background-image: -o-linear-gradient( #d0d0d0,#dfdfdf ); background-image: linear-gradient( #d0d0d0,#dfdfdf );}.ui-btn-down-b:visited,.ui-btn-down-b:hover,.ui-btn-down-b a.ui-link-inherit{color:#2F3E46 ;}.ui-btn-up-b,.ui-btn-hover-b,.ui-btn-down-b{ font-family:Helvetica,Arial,sans-serif ;text-decoration:none;}.ui-bar-c{border:1px solid #424242 ;background:#9b1f23 ;color:#ffffff ;font-weight:bold;text-shadow:0 1px 1px #444444 ;background-image:-webkit-gradient(linear,left top,left bottom,from( #9b1f23 ),to( #660000 )); background-image:-webkit-linear-gradient( #9b1f23,#660000 ); background-image: -moz-linear-gradient( #9b1f23,#660000 ); background-image: -ms-linear-gradient( #9b1f23,#660000 ); background-image: -o-linear-gradient( #9b1f23,#660000 ); background-image: linear-gradient( #9b1f23,#660000 );}.ui-bar-c .ui-link-inherit{color:#ffffff ;}.ui-bar-c a.ui-link{color:#7cc4e7 ;font-weight:bold;}.ui-bar-c a.ui-link:visited{ color:#2489CE ;}.ui-bar-c a.ui-link:hover{color:#2489CE ;}.ui-bar-c a.ui-link:active{color:#2489CE ;}.ui-bar-c,.ui-bar-c input,.ui-bar-c select,.ui-bar-c textarea,.ui-bar-c button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-c,.ui-overlay-c{border:1px solid #aaaaaa ;color:#333333 ;text-shadow:0 0px 0 #ffffff ;background:#ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #ffffff ),to( #ffffff )); background-image:-webkit-linear-gradient( #ffffff,#ffffff ); background-image: -moz-linear-gradient( #ffffff,#ffffff ); background-image: -ms-linear-gradient( #ffffff,#ffffff ); background-image: -o-linear-gradient( #ffffff,#ffffff ); background-image: linear-gradient( #ffffff,#ffffff );}.ui-overlay-c{background-image:none;border-width:0;}.ui-body-c,.ui-body-c input,.ui-body-c select,.ui-body-c textarea,.ui-body-c button{ font-family:Helvetica,Arial,sans-serif ;}.ui-body-c .ui-link-inherit{color:#333333 ;}.ui-body-c .ui-link{color:#c1272d ;font-weight:bold;}.ui-body-c .ui-link:visited{ color:#c1272d ;}.ui-body-c .ui-link:hover{color:#dd2c33 ;}.ui-body-c .ui-link:active{color:#c1272d ;}.ui-btn-up-c{border:1px solid #cccccc ;background:#e6e6e6 ;font-weight:bold;color:#2F3E46 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #e6e6e6 ),to( #e6e6e6 )); background-image:-webkit-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: -moz-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: -ms-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: -o-linear-gradient( #e6e6e6,#e6e6e6 ); background-image: linear-gradient( #e6e6e6,#e6e6e6 );}.ui-btn-up-c:visited,.ui-btn-up-c a.ui-link-inherit{color:#2F3E46 ;}.ui-btn-hover-c{border:1px solid #bbbbbb ;background:#dfdfdf ;font-weight:bold;color:#2F3E46 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #f6f6f6 ),to( #e0e0e0 )); background-image:-webkit-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: -moz-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: -ms-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: -o-linear-gradient( #f6f6f6,#e0e0e0 ); background-image: linear-gradient( #f6f6f6,#e0e0e0 );}.ui-btn-hover-c:visited,.ui-btn-hover-c:hover,.ui-btn-hover-c a.ui-link-inherit{color:#2F3E46 ;}.ui-btn-down-c{border:1px solid #bbbbbb ;background:#d6d6d6 ;font-weight:bold;color:#2F3E46 ;text-shadow:0 1px 0 #ffffff ;background-image:-webkit-gradient(linear,left top,left bottom,from( #d0d0d0 ),to( #dfdfdf )); background-image:-webkit-linear-gradient( #d0d0d0,#dfdfdf ); background-image: -moz-linear-gradient( #d0d0d0,#dfdfdf ); background-image: -ms-linear-gradient( #d0d0d0,#dfdfdf ); background-image: -o-linear-gradient( #d0d0d0,#dfdfdf ); background-image: linear-gradient( #d0d0d0,#dfdfdf );}.ui-btn-down-c:visited,.ui-btn-down-c:hover,.ui-btn-down-c a.ui-link-inherit{color:#2F3E46 ;}.ui-btn-up-c,.ui-btn-hover-c,.ui-btn-down-c{ font-family:Helvetica,Arial,sans-serif ;text-decoration:none;}a.ui-link-inherit{text-decoration:none !important;}.ui-btn-active{border:1px solid #9b1f23 ;background:#9b1f23 ;font-weight:bold;color:#ffffff ;cursor:pointer;text-shadow:0 1px 1px #444444 ;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from( #aa2226 ),to( #8b1b1f )); background-image:-webkit-linear-gradient( #aa2226,#8b1b1f ); background-image: -moz-linear-gradient( #aa2226,#8b1b1f ); background-image: -ms-linear-gradient( #aa2226,#8b1b1f ); background-image: -o-linear-gradient( #aa2226,#8b1b1f ); background-image: linear-gradient( #aa2226,#8b1b1f ); font-family:Helvetica,Arial,sans-serif ;}.ui-btn-active:visited,.ui-btn-active:hover,.ui-btn-active a.ui-link-inherit{color:#ffffff ;}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3);}.ui-corner-tl{-moz-border-radius-topleft:.6em ;-webkit-border-top-left-radius:.6em ;border-top-left-radius:.6em ;}.ui-corner-tr{-moz-border-radius-topright:.6em ;-webkit-border-top-right-radius:.6em ;border-top-right-radius:.6em ;}.ui-corner-bl{-moz-border-radius-bottomleft:.6em ;-webkit-border-bottom-left-radius:.6em ;border-bottom-left-radius:.6em ;}.ui-corner-br{-moz-border-radius-bottomright:.6em ;-webkit-border-bottom-right-radius:.6em ;border-bottom-right-radius:.6em ;}.ui-corner-top{-moz-border-radius-topleft:.6em ;-webkit-border-top-left-radius:.6em ;border-top-left-radius:.6em ;-moz-border-radius-topright:.6em ;-webkit-border-top-right-radius:.6em ;border-top-right-radius:.6em ;}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em ;-webkit-border-bottom-left-radius:.6em ;border-bottom-left-radius:.6em ;-moz-border-radius-bottomright:.6em ;-webkit-border-bottom-right-radius:.6em ;border-bottom-right-radius:.6em ;}.ui-corner-right{-moz-border-radius-topright:.6em ;-webkit-border-top-right-radius:.6em ;border-top-right-radius:.6em ;-moz-border-radius-bottomright:.6em ;-webkit-border-bottom-right-radius:.6em ;border-bottom-right-radius:.6em ;}.ui-corner-left{-moz-border-radius-topleft:.6em ;-webkit-border-top-left-radius:.6em ;border-top-left-radius:.6em ;-moz-border-radius-bottomleft:.6em ;-webkit-border-bottom-left-radius:.6em ;border-bottom-left-radius:.6em ;}.ui-corner-all{-moz-border-radius:.6em ;-webkit-border-radius:.6em ;border-radius:.6em ;}.ui-corner-none{-moz-border-radius: 0;-webkit-border-radius: 0;border-radius: 0;}.ui-br{border-bottom:rgb(130,130,130);border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid;}.ui-disabled{opacity:.3;}.ui-disabled,.ui-disabled a{cursor:default !important;pointer-events:none;}.ui-disabled .ui-btn-text{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=30)";filter:alpha(opacity=30);zoom:1;}.ui-icon,.ui-icon-searchfield:after{background:#FFFFFF ;background:rgba(153,0,0,1) ;background-image:url(images/icons-18-white.png) ;background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px;}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat;}@media only screen and (-webkit-min-device-pixel-ratio:1.5), only screen and (min--moz-device-pixel-ratio:1.5), only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px;}.ui-icon-alt{background-image:url(images/icons-36-black.png);}}.ui-icon-plus{background-position:-0 50%;}.ui-icon-minus{background-position:-36px 50%;}.ui-icon-delete{background-position:-72px 50%;}.ui-icon-arrow-r{background-position:-108px 50%;}.ui-icon-arrow-l{background-position:-144px 50%;}.ui-icon-arrow-u{background-position:-180px 50%;}.ui-icon-arrow-d{background-position:-216px 50%;}.ui-icon-check{background-position:-252px 50%;}.ui-icon-gear{background-position:-288px 50%;}.ui-icon-refresh{background-position:-324px 50%;}.ui-icon-forward{background-position:-360px 50%;}.ui-icon-back{background-position:-396px 50%;}.ui-icon-grid{background-position:-432px 50%;}.ui-icon-star{background-position:-468px 50%;}.ui-icon-alert{background-position:-504px 50%;}.ui-icon-info{background-position:-540px 50%;}.ui-icon-home{background-position:-576px 50%;}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%;}.ui-icon-checkbox-off{background-position:-684px 50%;}.ui-icon-checkbox-on{background-position:-648px 50%;}.ui-icon-radio-off{background-position:-756px 50%;}.ui-icon-radio-on{background-position:-720px 50%;}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent;}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#9b1f23 ; }.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:46px 46px;}a.ui-link-inherit{text-decoration:none !important;}.ui-btn-active{border:1px solid #9b1f23 ;background:#9b1f23 ;font-weight:bold;color:#ffffff ;cursor:pointer;text-shadow:0 1px 1px #444444 ;text-decoration:none;background-image:-webkit-gradient(linear,left top,left bottom,from( #aa2226 ),to( #8b1b1f )); background-image:-webkit-linear-gradient( #aa2226,#8b1b1f ); background-image: -moz-linear-gradient( #aa2226,#8b1b1f ); background-image: -ms-linear-gradient( #aa2226,#8b1b1f ); background-image: -o-linear-gradient( #aa2226,#8b1b1f ); background-image: linear-gradient( #aa2226,#8b1b1f ); font-family:Helvetica,Arial,sans-serif ;}.ui-btn-active:visited,.ui-btn-active:hover,.ui-btn-active a.ui-link-inherit{color:#ffffff ;}.ui-btn-inner{border-top:1px solid #fff;border-color:rgba(255,255,255,.3);}.ui-corner-tl{-moz-border-radius-topleft:.6em ;-webkit-border-top-left-radius:.6em ;border-top-left-radius:.6em ;}.ui-corner-tr{-moz-border-radius-topright:.6em ;-webkit-border-top-right-radius:.6em ;border-top-right-radius:.6em ;}.ui-corner-bl{-moz-border-radius-bottomleft:.6em ;-webkit-border-bottom-left-radius:.6em ;border-bottom-left-radius:.6em ;}.ui-corner-br{-moz-border-radius-bottomright:.6em ;-webkit-border-bottom-right-radius:.6em ;border-bottom-right-radius:.6em ;}.ui-corner-top{-moz-border-radius-topleft:.6em ;-webkit-border-top-left-radius:.6em ;border-top-left-radius:.6em ;-moz-border-radius-topright:.6em ;-webkit-border-top-right-radius:.6em ;border-top-right-radius:.6em ;}.ui-corner-bottom{-moz-border-radius-bottomleft:.6em ;-webkit-border-bottom-left-radius:.6em ;border-bottom-left-radius:.6em ;-moz-border-radius-bottomright:.6em ;-webkit-border-bottom-right-radius:.6em ;border-bottom-right-radius:.6em ;}.ui-corner-right{-moz-border-radius-topright:.6em ;-webkit-border-top-right-radius:.6em ;border-top-right-radius:.6em ;-moz-border-radius-bottomright:.6em ;-webkit-border-bottom-right-radius:.6em ;border-bottom-right-radius:.6em ;}.ui-corner-left{-moz-border-radius-topleft:.6em ;-webkit-border-top-left-radius:.6em ;border-top-left-radius:.6em ;-moz-border-radius-bottomleft:.6em ;-webkit-border-bottom-left-radius:.6em ;border-bottom-left-radius:.6em ;}.ui-corner-all{-moz-border-radius:.6em ;-webkit-border-radius:.6em ;border-radius:.6em ;}.ui-corner-none{-moz-border-radius: 0;-webkit-border-radius: 0;border-radius: 0;}.ui-br{border-bottom:rgb(130,130,130);border-bottom:rgba(130,130,130,.3);border-bottom-width:1px;border-bottom-style:solid;}.ui-disabled{opacity:.3;}.ui-disabled,.ui-disabled a{cursor:default !important;pointer-events:none;}.ui-disabled .ui-btn-text{-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=30)";filter:alpha(opacity=30);zoom:1;}.ui-icon,.ui-icon-searchfield:after{background:#FFFFFF ;background:rgba(153,0,0,1) ;background-image:url(images/icons-18-white.png) ;background-repeat:no-repeat;-moz-border-radius:9px;-webkit-border-radius:9px;border-radius:9px;}.ui-icon-alt{background:#fff;background:rgba(255,255,255,.3);background-image:url(images/icons-18-black.png);background-repeat:no-repeat;}@media only screen and (-webkit-min-device-pixel-ratio:1.5), only screen and (min--moz-device-pixel-ratio:1.5), only screen and (min-resolution:240dpi){.ui-icon-plus,.ui-icon-minus,.ui-icon-delete,.ui-icon-arrow-r,.ui-icon-arrow-l,.ui-icon-arrow-u,.ui-icon-arrow-d,.ui-icon-check,.ui-icon-gear,.ui-icon-refresh,.ui-icon-forward,.ui-icon-back,.ui-icon-grid,.ui-icon-star,.ui-icon-alert,.ui-icon-info,.ui-icon-home,.ui-icon-search,.ui-icon-searchfield:after,.ui-icon-checkbox-off,.ui-icon-checkbox-on,.ui-icon-radio-off,.ui-icon-radio-on{background-image:url(images/icons-36-white.png);-moz-background-size:776px 18px;-o-background-size:776px 18px;-webkit-background-size:776px 18px;background-size:776px 18px;}.ui-icon-alt{background-image:url(images/icons-36-black.png);}}.ui-icon-plus{background-position:-0 50%;}.ui-icon-minus{background-position:-36px 50%;}.ui-icon-delete{background-position:-72px 50%;}.ui-icon-arrow-r{background-position:-108px 50%;}.ui-icon-arrow-l{background-position:-144px 50%;}.ui-icon-arrow-u{background-position:-180px 50%;}.ui-icon-arrow-d{background-position:-216px 50%;}.ui-icon-check{background-position:-252px 50%;}.ui-icon-gear{background-position:-288px 50%;}.ui-icon-refresh{background-position:-324px 50%;}.ui-icon-forward{background-position:-360px 50%;}.ui-icon-back{background-position:-396px 50%;}.ui-icon-grid{background-position:-432px 50%;}.ui-icon-star{background-position:-468px 50%;}.ui-icon-alert{background-position:-504px 50%;}.ui-icon-info{background-position:-540px 50%;}.ui-icon-home{background-position:-576px 50%;}.ui-icon-search,.ui-icon-searchfield:after{background-position:-612px 50%;}.ui-icon-checkbox-off{background-position:-684px 50%;}.ui-icon-checkbox-on{background-position:-648px 50%;}.ui-icon-radio-off{background-position:-756px 50%;}.ui-icon-radio-on{background-position:-720px 50%;}.ui-checkbox .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;}.ui-icon-checkbox-off,.ui-icon-radio-off{background-color:transparent;}.ui-checkbox-on .ui-icon,.ui-radio-on .ui-icon{background-color:#9b1f23 ; }.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:46px 46px;}.ui-btn-corner-tl{-moz-border-radius-topleft:1em ;-webkit-border-top-left-radius:1em ;border-top-left-radius:1em ;}.ui-btn-corner-tr{-moz-border-radius-topright:1em ;-webkit-border-top-right-radius:1em ;border-top-right-radius:1em ;}.ui-btn-corner-bl{-moz-border-radius-bottomleft:1em ;-webkit-border-bottom-left-radius:1em ;border-bottom-left-radius:1em ;}.ui-btn-corner-br{-moz-border-radius-bottomright:1em ;-webkit-border-bottom-right-radius:1em ;border-bottom-right-radius:1em ;}.ui-btn-corner-top{-moz-border-radius-topleft:1em ;-webkit-border-top-left-radius:1em ;border-top-left-radius:1em ;-moz-border-radius-topright:1em ;-webkit-border-top-right-radius:1em ;border-top-right-radius:1em ;}.ui-btn-corner-bottom{-moz-border-radius-bottomleft:1em ;-webkit-border-bottom-left-radius:1em ;border-bottom-left-radius:1em ;-moz-border-radius-bottomright:1em ;-webkit-border-bottom-right-radius:1em ;border-bottom-right-radius:1em ;}.ui-btn-corner-right{-moz-border-radius-topright:1em ;-webkit-border-top-right-radius:1em ;border-top-right-radius:1em ;-moz-border-radius-bottomright:1em ;-webkit-border-bottom-right-radius:1em ;border-bottom-right-radius:1em ;}.ui-btn-corner-left{-moz-border-radius-topleft:1em ;-webkit-border-top-left-radius:1em ;border-top-left-radius:1em ;-moz-border-radius-bottomleft:1em ;-webkit-border-bottom-left-radius:1em ;border-bottom-left-radius:1em ;}.ui-btn-corner-all{-moz-border-radius:1em ;-webkit-border-radius:1em ;border-radius:1em ;}.ui-corner-tl,.ui-corner-tr,.ui-corner-bl,.ui-corner-br,.ui-corner-top,.ui-corner-bottom,.ui-corner-right,.ui-corner-left,.ui-corner-all,.ui-btn-corner-tl,.ui-btn-corner-tr,.ui-btn-corner-bl,.ui-btn-corner-br,.ui-btn-corner-top,.ui-btn-corner-bottom,.ui-btn-corner-right,.ui-btn-corner-left,.ui-btn-corner-all{ -webkit-background-clip:padding-box; -moz-background-clip:padding; background-clip:padding-box;}.ui-overlay{background:#666;opacity:.5;filter:Alpha(Opacity=50);position:absolute;width:100%;height:100%;}.ui-overlay-shadow{-moz-box-shadow:0px 0px 12px rgba(0,0,0,.6);-webkit-box-shadow:0px 0px 12px rgba(0,0,0,.6);box-shadow:0px 0px 12px rgba(0,0,0,.6);}.ui-shadow{-moz-box-shadow:0px 1px 4px rgba(0,0,0,.3) ;-webkit-box-shadow:0px 1px 4px rgba(0,0,0,.3) ;box-shadow:0px 1px 4px rgba(0,0,0,.3) ;}.ui-bar-a .ui-shadow,.ui-bar-b .ui-shadow,.ui-bar-c .ui-shadow {-moz-box-shadow:0px 1px 0 rgba(255,255,255,.3);-webkit-box-shadow:0px 1px 0 rgba(255,255,255,.3);box-shadow:0px 1px 0 rgba(255,255,255,.3);}.ui-shadow-inset{-moz-box-shadow:inset 0px 1px 4px rgba(0,0,0,.2);-webkit-box-shadow:inset 0px 1px 4px rgba(0,0,0,.2);box-shadow:inset 0px 1px 4px rgba(0,0,0,.2);}.ui-icon-shadow{-moz-box-shadow:0px 1px 0 rgba(255,255,255,.4) ;-webkit-box-shadow:0px 1px 0 rgba(255,255,255,.4) ;box-shadow:0px 1px 0 rgba(255,255,255,.4) ;}.ui-btn:focus,.ui-link-inherit:focus{outline:0;}.ui-btn.ui-focus{z-index:1;}.ui-focus,.ui-btn:focus{-moz-box-shadow:inset 0px 0px 3px #9b1f23,0px 0px 9px #9b1f23 ;-webkit-box-shadow:inset 0px 0px 3px #9b1f23,0px 0px 9px #9b1f23 ;box-shadow:inset 0px 0px 3px #9b1f23,0px 0px 9px #9b1f23 ;}.ui-input-text.ui-focus,.ui-input-search.ui-focus{-moz-box-shadow:0px 0px 12px #9b1f23 ;-webkit-box-shadow:0px 0px 12px #9b1f23 ;box-shadow:0px 0px 12px #9b1f23 ;}.ui-mobile-nosupport-boxshadow *{-moz-box-shadow:none !important;-webkit-box-shadow:none !important;box-shadow:none !important;}.ui-mobile-nosupport-boxshadow .ui-focus,.ui-mobile-nosupport-boxshadow .ui-btn:focus,.ui-mobile-nosupport-boxshadow .ui-link-inherit:focus{outline-width:1px;outline-style:auto;} \ No newline at end of file diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/mobile.xsl b/dspace-xmlui/src/main/webapp/themes/mobile/mobile.xsl old mode 100755 new mode 100644 index ffb8c676cb7f2eac388e99158573d2f50299d9ad..6ddacd196b1e3b6b8eb44cc21672bb3027c009f9 --- a/dspace-xmlui/src/main/webapp/themes/mobile/mobile.xsl +++ b/dspace-xmlui/src/main/webapp/themes/mobile/mobile.xsl @@ -72,9 +72,6 @@ <xsl:call-template name="buildHeader"/> --> - <!--The trail is built by applying a template over pageMeta's trail children. --> - <xsl:call-template name="buildTrail"/> - <!-- Goes over the document tag's children elements: body, options, meta. The body template generates the ds-body div that contains all the content. The options template generates @@ -103,13 +100,13 @@ <link rel="stylesheet"> <xsl:attribute name="href"> <xsl:value-of select="$mobile-url"/> - <xsl:text>/xmlui/themes/mobile/lib/sc-mobile.min.css</xsl:text> + <xsl:text>/themes/mobile/lib/sc-mobile.min.css</xsl:text> </xsl:attribute> </link> <link rel="stylesheet"> <xsl:attribute name="href"> - <xsl:text>http://code.jquery.com/mobile/1.1.2/jquery.mobile.structure-1.1.2.min.css</xsl:text> + <xsl:text>http://code.jquery.com/mobile/1.1.1/jquery.mobile.structure-1.1.1.min.css</xsl:text> </xsl:attribute> </link> @@ -118,7 +115,7 @@ <link rel="stylesheet"> <xsl:attribute name="href"> <xsl:value-of select="$mobile-url"/> - <xsl:text>/xmlui/themes/mobile/lib/m-tweaks.css</xsl:text> + <xsl:text>/themes/mobile/lib/m-tweaks.css</xsl:text> </xsl:attribute> </link> @@ -129,19 +126,19 @@ <script> <xsl:attribute name="src"> - <xsl:text>http://code.jquery.com/mobile/1.1.2/jquery.mobile-1.1.2.min.js</xsl:text> + <xsl:text>http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.js</xsl:text> </xsl:attribute> </script> <script> <xsl:attribute name="src"> <xsl:value-of select="$mobile-url"/> - <xsl:text>/xmlui/themes/mobile/lib/cookies.js</xsl:text> + <xsl:text>/themes/mobile/lib/cookies.js</xsl:text> </xsl:attribute> </script> <script> <xsl:attribute name="src"> <xsl:value-of select="$mobile-url"/> - <xsl:text>/xmlui/themes/mobile/lib/m-tweaks.js</xsl:text> + <xsl:text>/themes/mobile/lib/m-tweaks.js</xsl:text> </xsl:attribute> </script> <!-- Add the title in --> @@ -164,11 +161,10 @@ placeholders for header images --> <xsl:template name="buildHeader"> <!-- new header with a data-icon linking to the homepage --> - <!-- <div data-role="header"> - <h2> - FIXME: Colocar breadcumbs aqui - <i18n:text>xmlui.mobile.home_mobile</i18n:text> - </h2> + <div data-role="header"> + <h2> + <i18n:text>xmlui.mobile.home_mobile</i18n:text> + </h2> <a> <xsl:attribute name="href"> <xsl:value-of select="$mobile-url"/> @@ -183,10 +179,9 @@ <xsl:text>reverse</xsl:text> </xsl:attribute> <xsl:text>Home</xsl:text> - </a> --> + </a> <!-- link to full website page --> -<!-- <a> <xsl:attribute name="href"> <xsl:value-of select="$dspace-url"/> @@ -204,33 +199,27 @@ </xsl:attribute> <xsl:text>non-mobile view</xsl:text> </a> - </div>--> <!-- header --> + </div><!-- header --> </xsl:template> + <!-- BEGIN front page customization --> <xsl:template match="dri:body"> <div data-role="content"> <div id="ds-body"> +<xsl:apply-templates /> <xsl:choose> <xsl:when test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='title']='xmlui.general.dspace_home'"> - <div id="search-box"> <h3> <i18n:text>xmlui.mobile.search_all</i18n:text> </h3> - <form id="search" class="ds-interactive-div primary" action="search" method="get"> + <form id="search" class="ds-interactive-div primary" action="{/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='search' and @qualifier='advancedURL']}" method="get"> <fieldset> <input id="search-basic" name="query" type="search" value="" /> <input id="search" name="submit" type="submit" value="Go" /> </fieldset> </form> - </div><!-- #search-box --> - </xsl:when> - </xsl:choose> - -<xsl:apply-templates /> - <xsl:choose> - <xsl:when test="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='title']='xmlui.general.dspace_home'"> <!-- browse ALL code 'borrowed' from ds-options --> <h3> @@ -241,7 +230,7 @@ <a> <xsl:attribute name="href"> <xsl:value-of select="$mobile-url"/> - <xsl:text>/xmlui/browse?type=dateissued</xsl:text> + <xsl:text>/browse?type=dateissued</xsl:text> </xsl:attribute> <xsl:attribute name="data-role"> <xsl:text>button</xsl:text> @@ -258,7 +247,7 @@ <a> <xsl:attribute name="href"> <xsl:value-of select="$mobile-url"/> - <xsl:text>/xmlui/browse?type=author</xsl:text> + <xsl:text>/browse?type=author</xsl:text> </xsl:attribute> <xsl:attribute name="data-role"> <xsl:text>button</xsl:text> @@ -275,7 +264,7 @@ <a> <xsl:attribute name="href"> <xsl:value-of select="$mobile-url"/> - <xsl:text>/xmlui/browse?type=title</xsl:text> + <xsl:text>/browse?type=title</xsl:text> </xsl:attribute> <xsl:attribute name="data-role"> <xsl:text>button</xsl:text> @@ -286,13 +275,13 @@ <xsl:attribute name="data-iconpos"> <xsl:text>right</xsl:text> </xsl:attribute> - <i18n:text>xmlui.mobile.browse_title</i18n:text> + <i18n:text>xmlui.mobile.browse_title</i18n:text> </a> <a> <xsl:attribute name="href"> <xsl:value-of select="$mobile-url"/> - <xsl:text>/xmlui/browse?type=subject</xsl:text> + <xsl:text>/browse?type=subject</xsl:text> </xsl:attribute> <xsl:attribute name="data-role"> <xsl:text>button</xsl:text> @@ -308,13 +297,11 @@ </div><!-- browse-front-page --> <br /> - <!-- link to full website + <!-- link to full website --> <a href="#" data-role="button" data-icon="forward" data-iconpos="left"> <xsl:attribute name="onclick">createCookie('viewfull','true','','$dspace.hostname');window.location='<xsl:value-of select="$dspace-url"/>';</xsl:attribute> <xsl:text>View full website</xsl:text> - </a> --> - - + </a> </xsl:when> </xsl:choose> @@ -326,9 +313,9 @@ <!-- new footer --> <xsl:template name="buildFooter"> - <div data-role="footer"><!-- FOOTER + <div data-role="footer"> <h4>Mobile theme for DSpace</h4> - --></div> + </div> </xsl:template> @@ -423,39 +410,36 @@ <xsl:template match="dim:dim" mode="itemSummaryView-DIM"> <!-- AddThis Button BEGIN --> -<div class="addthis_toolbox addthis_default_style" id="addthis-box"> - <xsl:text>Compartilhar: </xsl:text> - <a> - <xsl:attribute name="class"> - <xsl:text>aaddthis_button_compact</xsl:text> - </xsl:attribute> - <xsl:text> </xsl:text> - </a> - <a> - <xsl:attribute name="class"> - <xsl:text>addthis_button_preferred_3</xsl:text> +<div id="addthis"> + <a> + <xsl:attribute name="href"> + <xsl:text>http://www.addthis.com/bookmark.php?v=250&username=xa-4d35e7801c9278b4</xsl:text> </xsl:attribute> - <xsl:text> </xsl:text> - </a> - <a> <xsl:attribute name="class"> - <xsl:text>addthis_button_preferred_2</xsl:text> + <xsl:text>addthis_button</xsl:text> </xsl:attribute> - <xsl:text> </xsl:text> - </a> - <a> - <xsl:attribute name="class"> - <xsl:text>addthis_button_preferred_1</xsl:text> + <img> + <xsl:attribute name="src"> + <xsl:text>http://s7.addthis.com/static/btn/lg-share-en.gif</xsl:text> + </xsl:attribute> + <xsl:attribute name="width"> + <xsl:text>125</xsl:text> + </xsl:attribute> + <xsl:attribute name="height"> + <xsl:text>16</xsl:text> + </xsl:attribute> + <xsl:attribute name="style"> + <xsl:text>border:0</xsl:text> + </xsl:attribute> + </img> + </a> + <script type="text/javascript"> + <xsl:attribute name="src"> + <xsl:text>http://s7.addthis.com/js/250/addthis_widget.js#username=</xsl:text> </xsl:attribute> - <xsl:text> </xsl:text> - </a> -</div> -<script type="text/javascript"> - <xsl:attribute name="src"> - <xsl:text>http://s7.addthis.com/js/300/addthis_widget.js#pubid=</xsl:text> - </xsl:attribute> - <xsl:text>ra-52ab4aec11085348</xsl:text> -</script> + <xsl:text>username</xsl:text> + </script> + </div> <!-- AddThis Button END --> <div id="metadata-wrapper"> @@ -710,7 +694,8 @@ </xsl:attribute> <img alt="Thumbnail"> <xsl:attribute name="src"> - <xsl:text>/xmlui/themes/mobile/lib/images/mobile-default-thumbnail.png</xsl:text> + <xsl:variable name="request-uri" select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='contextPath'])"/> + <xsl:text>/themes/mobile/lib/images/default-thumbnail.png</xsl:text> </xsl:attribute> </img> </a> @@ -809,80 +794,4 @@ <xsl:template match="dri:options">  </xsl:template> - -<!-- ******************************************************************** --> - <xsl:template name="buildTrail"> - <div id="ds-trail-wrapper"> - <ul id="ds-trail"> - <!-- Display a language selection if more than 1 language is supported --> - <xsl:if - test="count(/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='page'][@qualifier='supportedLocale']) > 1"> - <div id="ds-language-selection"> - <xsl:for-each - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='page'][@qualifier='supportedLocale']"> - <xsl:variable name="locale" select="." /> - <a> - <xsl:attribute name="href"> - <xsl:value-of select="concat($context-path,'/?locale-attribute=')" /> - <xsl:value-of select="$locale" /> - </xsl:attribute> - <xsl:value-of - select="/dri:document/dri:meta/dri:pageMeta/dri:metadata[@element='supportedLocale'][@qualifier=$locale]" /> - </a> - </xsl:for-each> - </div> - </xsl:if> - - <xsl:choose> - <xsl:when test="starts-with($request-uri, 'page/about')"> - <li class="ds-trail-link first-link"> - <i18n:text>xmlui.structure.AboutRepositoryTrail</i18n:text> - </li> - </xsl:when> - <xsl:when test="count(/dri:document/dri:meta/dri:pageMeta/dri:trail) = 0"> - <li class="ds-trail-link first-link">-</li> - </xsl:when> - <xsl:otherwise> - <xsl:apply-templates select="/dri:document/dri:meta/dri:pageMeta/dri:trail"/> - </xsl:otherwise> - </xsl:choose> - </ul> - </div> - </xsl:template> - - <xsl:template match="dri:trail"> - <!--put an arrow between the parts of the trail--> - <xsl:if test="position()>1"> - <li class="ds-trail-arrow"> - <xsl:text>→</xsl:text> - </li> - </xsl:if> - <li> - <xsl:attribute name="class"> - <xsl:text>ds-trail-link </xsl:text> - <xsl:if test="position()=1"> - <xsl:text>first-link </xsl:text> - </xsl:if> - <xsl:if test="position()=last()"> - <xsl:text>last-link</xsl:text> - </xsl:if> - </xsl:attribute> - <!-- Determine whether we are dealing with a link or plain text trail link --> - <xsl:choose> - <xsl:when test="./@target"> - <a> - <xsl:attribute name="href"> - <xsl:value-of select="./@target"/> - </xsl:attribute> - <xsl:apply-templates /> - </a> - </xsl:when> - <xsl:otherwise> - <xsl:apply-templates /> - </xsl:otherwise> - </xsl:choose> - </li> - </xsl:template> -<!-- ******************************************************************** --> - </xsl:stylesheet> diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/readme.txt b/dspace-xmlui/src/main/webapp/themes/mobile/readme.txt old mode 100755 new mode 100644 index 22dda60dcf13b948be47ce4c40d66026ab67eac2..af30d286bda72de97086eb5c440f8740a19850f7 --- a/dspace-xmlui/src/main/webapp/themes/mobile/readme.txt +++ b/dspace-xmlui/src/main/webapp/themes/mobile/readme.txt @@ -1,88 +1,88 @@ - The contents of this file are subject to the license and copyright - detailed in the LICENSE and NOTICE files at the root of the source - tree and available online at - - http://www.dspace.org/license/ - -Mobile theme for DSpace 1.6 -Created by Elias Tzoc <tzoce@miamioh.edu> and - James Russell <james@ohiolink.edu> - September 14, 2012 + The contents of this file are subject to the license and copyright + detailed in the LICENSE and NOTICE files at the root of the source + tree and available online at + + http://www.dspace.org/license/ + +Mobile theme for DSpace 1.6 +Created by Elias Tzoc <tzoce@miamioh.edu> and + James Russell <james@ohiolink.edu> + September 14, 2012 Mobile theme 1.1 Updated by Elias Tzoc <tzoce@miamioh.edu> - September 30, 2013 + September 30, 2013 Fixes: switch to non-mobile pages; CSS and reloading problems; and mobile-optimized page for advanced search - -=================================================================================== -The mobile theme file structure - -+-- mobile -| +-- lib -| | +-- cookies.js -| | +-- detectmobile.js -| | +-- images -| | | +-- ajax-loader.gif -| | | +-- default-thumbnail.png -| | | +-- icons-18-black.png -| | | +-- icons-18-white.png -| | | +-- icons-36-black.png -| | | +-- icons-36-white.png -| | +-- m-tweaks.css -| | +-- sc-mobile.css -| | +-- sc-mobile.min.css -| | +-- mobile.xsl -| | +-- sitemap.xmap -| | +-- themes.xmap -| +-- readme.txt - - -Installation: - -0. Get a new domain name that is an alias of the existing domain name - for your DSpace installation. - e.g. if your current domain is yoursite.edu your new domain name - might be mobile.yoursite.edu - These instructions assume that the new domain name starts with 'mobile.' - If it is something else, you will need to make a change in Step 5. - -1. Copy the mobile theme folder into your XMLUI theme folder - e.g. ../dspace/webapps/xmlui/themes/ - -2. Add a call for the detectmobile.js and cookies.js file in the header - of your current main theme.xsl file. - It should look like: - <script type="text/javascript" src="/themes/mobile/lib/detectmobile.js"> </script> - <script type="text/javascript" src="/themes/mobile/lib/cookies.js"> </script> - * In this file, we also add a "View mobile site" link in the footer - section, which allows users to view the full site on their - mobile devices. The cookies.js file saves this preference - but it's erased when the session is closed. - If you want such a link, the code for this should look like the following - (with the appropriate URL for your mobile site): - <a href="#" onclick="eraseCookie('viewfull');window.location='http://mobile.yoursite.edu';"> - View mobile site</a> - -3. Open the detectmobile.js file and enter your new mobile domain - at the end of the function call e.g. mobile.yoursite.edu - * if you choose a different domain name or theme name other than - "mobile" make sure to update the settings in the sitemap.xmap - -4. In mobile.xsl, find the link "View full website" and replace the - references to yoursite.edu with the domain name for your main site. - * lines 255-257 - -5. Replace or edit the themes.xmap file located in your default theme - folder e.g. ../dspace/webapps/xmlui/themes/ - * The code for setting up the properties for the domain is in - lines 32-37. This will need to be changed if the domain name - for your mobile site starts with something other than 'mobile.' - -6. Restart tomcat and now you should be able to see the mobile theme - in action; to change the look-and-feel, you can go to - http://jquerymobile.com/themeroller/ and either create your own - files or import/upgrade the uncompressed sc-mobile.css file. - -NOTE: Pages with more complex structure such as "Advanced Search" were - excluded in this first mobile theme. - + +=================================================================================== +The mobile theme file structure + ++-- mobile +| +-- lib +| | +-- cookies.js +| | +-- detectmobile.js +| | +-- images +| | | +-- ajax-loader.gif +| | | +-- default-thumbnail.png +| | | +-- icons-18-black.png +| | | +-- icons-18-white.png +| | | +-- icons-36-black.png +| | | +-- icons-36-white.png +| | +-- m-tweaks.css +| | +-- sc-mobile.css +| | +-- sc-mobile.min.css +| | +-- mobile.xsl +| | +-- sitemap.xmap +| | +-- themes.xmap +| +-- readme.txt + + +Installation: + +0. Get a new domain name that is an alias of the existing domain name + for your DSpace installation. + e.g. if your current domain is yoursite.edu your new domain name + might be mobile.yoursite.edu + These instructions assume that the new domain name starts with 'mobile.' + If it is something else, you will need to make a change in Step 5. + +1. Copy the mobile theme folder into your XMLUI theme folder + e.g. ../dspace/webapps/xmlui/themes/ + +2. Add a call for the detectmobile.js and cookies.js file in the header + of your current main theme.xsl file. + It should look like: + <script type="text/javascript" src="/themes/mobile/lib/detectmobile.js"> </script> + <script type="text/javascript" src="/themes/mobile/lib/cookies.js"> </script> + * In this file, we also add a "View mobile site" link in the footer + section, which allows users to view the full site on their + mobile devices. The cookies.js file saves this preference + but it's erased when the session is closed. + If you want such a link, the code for this should look like the following + (with the appropriate URL for your mobile site): + <a href="#" onclick="eraseCookie('viewfull');window.location='http://mobile.yoursite.edu';"> + View mobile site</a> + +3. Open the detectmobile.js file and enter your new mobile domain + at the end of the function call e.g. mobile.yoursite.edu + * if you choose a different domain name or theme name other than + "mobile" make sure to update the settings in the sitemap.xmap + +4. In mobile.xsl, find the link "View full website" and replace the + references to yoursite.edu with the domain name for your main site. + * lines 255-257 + +5. Replace or edit the themes.xmap file located in your default theme + folder e.g. ../dspace/webapps/xmlui/themes/ + * The code for setting up the properties for the domain is in + lines 32-37. This will need to be changed if the domain name + for your mobile site starts with something other than 'mobile.' + +6. Restart tomcat and now you should be able to see the mobile theme + in action; to change the look-and-feel, you can go to + http://jquerymobile.com/themeroller/ and either create your own + files or import/upgrade the uncompressed sc-mobile.css file. + +NOTE: Pages with more complex structure such as "Advanced Search" were + excluded in this first mobile theme. + diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/sitemap.xmap b/dspace-xmlui/src/main/webapp/themes/mobile/sitemap.xmap old mode 100755 new mode 100644 diff --git a/dspace-xmlui/src/main/webapp/themes/mobile/themes.xmap b/dspace-xmlui/src/main/webapp/themes/mobile/themes.xmap old mode 100755 new mode 100644 diff --git a/dspace/bin/dspace-info.pl b/dspace/bin/dspace-info.pl index 0db75d3c094398dd082cc5ea13e25ceb681299b3..e539ef2846fda3e34f12c580dc441d628d9998fc 100755 --- a/dspace/bin/dspace-info.pl +++ b/dspace/bin/dspace-info.pl @@ -32,6 +32,8 @@ my $dspace_dir = realpath(dirname(abs_path($0)).'/..'); my $assetstore_dir = GetConfigParameter( "assetstore.dir" ); my $search_dir = GetConfigParameter( "search.dir" ); my $logs_dir = GetConfigParameter( "log.dir" ); +my $db_name = GetConfigParameter( "db.url" ); +$db_name =~ s/.*\///; # directories in this array are to be checked for ownership by # the dspace user @@ -407,7 +409,7 @@ sub ExecuteSQL my $arg = shift; # do the SQL statement - open SQLOUT, "psql -d dspace -A -c '$arg' | "; + open SQLOUT, "psql -d $db_name -A -c '$arg' | "; # slurp up the results my @results = <SQLOUT>; diff --git a/dspace/bin/dspace_migrate b/dspace/bin/dspace_migrate deleted file mode 100644 index 69504fea151cef0fe056e26c8677a183905df1cc..0000000000000000000000000000000000000000 --- a/dspace/bin/dspace_migrate +++ /dev/null @@ -1,162 +0,0 @@ -#!/bin/bash - -############################################################################ -# -# Version: $Revision$ -# -# Date: $Date$ -# -# 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. -# -# Author : Cody Green -# Digital Initiatives Research -# Texas A&M University -# Email : codygreen@tamu.edu -# Description : Shell script that helps migrate data from a development -# server to a production server. It will remove the handle -# and any entries in the dublin_core.xml file that will be -# duplicated upon importing the data into DSpace. -# -############################################################################ - -# Make sure user is in bash -if [ -z "$BASH" ]; then - printf "ERROR: please run this script with the BASH shell.\n" - exit 192 -fi - -# Check if SED is in the path -which sed > /dev/null -if [ $? -ne 0 ]; then - # Check what OS user has - if [ `uname -s` = "SunOS" ]; then - # Declare variables - declare -rx SED="/usr/bin/sed" - fi - - if [ `uname -s` = "Linux" ]; then - # Declare variables - declare -rx SED="/bin/sed" - fi - - # Sanity check for programs - if [ ! -e $sed ]; then - printf "ERROR: Can not find the program sed.\n - please check that the program is installed or - in your path" - exit 1 - fi -else - export SED=`which sed` -fi - -# Check parameter count, show usage if incorrect number passed -if [ $# -eq 0 ]; then - printf "Usage: dspace_migrate.sh [DIRECTORY]\n" - printf "Example: /dspace/bin/dspace_migrate.sh /home/user/ETDs/ \n\n" - printf "This script will remove the handle and any \nentries in the dublin_core.xml file that will \nbe duplicated upon importing the data into DSpace.\n\n" - exit 0; -fi - -# Check if users needs help -if [ $1 = "--help" -o $1 = "--h" ]; then - printf "Usage: dspace_migrate.sh [DIRECTORY]\n" - printf "Example: /dspace/bin/dspace_migrate.sh /home/user/ETDs/ \n\n" - printf "This script will remove the handle and any \nentries in the dublin_core.xml file that will \nbe duplicated upon importing the data into DSpace.\n\n" - exit 0; -fi - -# Check to see if the directory exists -if [ ! -d $1 ]; then - printf "ERROR: $1 is not a valid directory.\n" - exit 1; -fi - -printf "Fixing Bad Data in ETDs\n" - -# Loop through the directory -for i in ls $1/*/dublin_core.xml; -do - # Ignore ls in the returned values - if [ $i = "ls" ]; then - continue - fi - printf "Checking $i...\n" - # Check if file exists - if [ ! -s $i ]; then - printf "ERROR: $i does not exist of is empty\n" - exit 1 - fi - # copy file - cp $i $i.orig - if [ $? -ne 0 ]; then - printf "ERROR: Could not copy $i to $i.orig \n" - exit 1 - fi - - printf " --removing null and duplicate values for $i\n" - - issued=`grep "element=\"date\" qualifier=\"issued\"" $i|cut -f2 -d \>|cut -f1 -d \<` - available=`grep "element=\"date\" qualifier=\"accessioned\"" $i|cut -f2 -d \>|cut -f1 -d \<` - - if [ $issued = $available ]; then - $SED "/><\/dcvalue>/d" $i | $SED "/element=\"date\" qualifier=\"accessioned\"/d" | $SED "/element=\"date\" qualifier=\"available\"/d" |$SED "/element=\"date\" qualifier=\"issued\"/d" | $SED "/element=\"identifier\" qualifier=\"uri\">http:\/\/hdl/d" | $SED "/element=\"description\" qualifier=\"provenance\"/,/<\/dcvalue>/d" | $SED "/element=\"format\" qualifier=\"extent\"/d" | $SED "/element=\"format\" qualifier=\"mimetype\"/d" | $SED "/bytes, checksum/d" > $i - else - printf " -- date issued $issued \n" - $SED "/><\/dcvalue>/d" $i | $SED "/element=\"date\" qualifier=\"accessioned\"/d" | $SED "/element=\"date\" qualifier=\"available\"/d" | $SED "/element=\"identifier\" qualifier=\"uri\">http:\/\/hdl/d" | $SED "/element=\"description\" qualifier=\"provenance\"/,/<\/dcvalue>/d" | $SED "/element=\"format\" qualifier=\"extent\"/d" | $SED "/element=\"format\" qualifier=\"mimetype\"/d" | $SED "/bytes, checksum/d" > $i - fi - - if [ $? -ne 0 ]; then - printf "ERROR: Could not fix $i\n" - exit 1 - fi - - # Check to see if filesize is 0 - printf " --checking filesize for $i\n" - if [ ! -s $i ]; then - printf "ERROR: filesize for $i is 0\n" - exit 1 - fi - - # remove copy of file - rm -f $i.orig - if [ $? -ne 0 ]; then - printf "ERROR: Could not remove $i.orig\n" - exit 1 - fi - -done -rm -f $1/*/handle -if [ $? -ne 0 ]; then - printf "ERROR: Could not delete handles\n" - exit 1 -fi -printf "Data Has Been Fixed\n" diff --git a/dspace/config/crosswalks/QDC.properties b/dspace/config/crosswalks/QDC.properties index b2b378910370f91952c5f9925478c88f0ea20766..08fa5fd9837d3da2e2923ad116059f938f67c5d8 100644 --- a/dspace/config/crosswalks/QDC.properties +++ b/dspace/config/crosswalks/QDC.properties @@ -5,7 +5,7 @@ # (See http://dublincore.org/schemas/xmls/qdc/2003/04/02/dc.xsd # and http://dublincore.org/schemas/xmls/qdc/2003/04/02/dcterms.xsd ) # -# See org.dspace.content.crosswwalk.QDCCrosswalk for documentation. +# See org.dspace.content.crosswalk.QDCCrosswalk for documentation. # # Author: Larry Stone # Revision: $Revision$ diff --git a/dspace/config/crosswalks/oai/metadataFormats/oai_dc.xsl b/dspace/config/crosswalks/oai/metadataFormats/oai_dc.xsl index c06eac55772f76cde92b11d34c0d0fa37d6274f7..ff127de7ca43360b6296ae912604db331a7c421f 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/oai_dc.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/oai_dc.xsl @@ -23,66 +23,127 @@ xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/oai_dc/ http://www.openarchives.org/OAI/2.0/oai_dc.xsd"> + <!-- dc.title --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='title']/doc:element/doc:field[@name='value']"> <dc:title><xsl:value-of select="." /></dc:title> </xsl:for-each> + <!-- dc.title.* --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='title']/doc:element/doc:element/doc:field[@name='value']"> + <dc:title><xsl:value-of select="." /></dc:title> + </xsl:for-each> + <!-- dc.creator --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='creator']/doc:element/doc:field[@name='value']"> + <dc:creator><xsl:value-of select="." /></dc:creator> + </xsl:for-each> + <!-- dc.contributor.author --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name='author']/doc:element/doc:field[@name='value']"> <dc:creator><xsl:value-of select="." /></dc:creator> </xsl:for-each> + <!-- dc.contributor.* (!author) --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name!='author']/doc:element/doc:field[@name='value']"> <dc:contributor><xsl:value-of select="." /></dc:contributor> </xsl:for-each> + <!-- dc.contributor --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element/doc:field[@name='value']"> + <dc:contributor><xsl:value-of select="." /></dc:contributor> + </xsl:for-each> + <!-- dc.subject --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']/doc:element/doc:field[@name='value']"> <dc:subject><xsl:value-of select="." /></dc:subject> </xsl:for-each> + <!-- dc.subject.* --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']/doc:element/doc:element/doc:field[@name='value']"> + <dc:subject><xsl:value-of select="." /></dc:subject> + </xsl:for-each> + <!-- dc.description --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='description']/doc:element/doc:field[@name='value']"> <dc:description><xsl:value-of select="." /></dc:description> </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='description']/doc:element[@name='abstract']/doc:element/doc:field[@name='value']"> + <!-- dc.description.* (not provenance)--> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='description']/doc:element[@name!='provenance']/doc:element/doc:field[@name='value']"> <dc:description><xsl:value-of select="." /></dc:description> </xsl:for-each> + <!-- dc.date --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='date']/doc:element/doc:field[@name='value']"> + <dc:date><xsl:value-of select="." /></dc:date> + </xsl:for-each> + <!-- dc.date.* --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='date']/doc:element/doc:element/doc:field[@name='value']"> <dc:date><xsl:value-of select="." /></dc:date> </xsl:for-each> + <!-- dc.type --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='type']/doc:element/doc:field[@name='value']"> <dc:type><xsl:value-of select="." /></dc:type> </xsl:for-each> + <!-- dc.type.* --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='type']/doc:element/doc:element/doc:field[@name='value']"> + <dc:type><xsl:value-of select="." /></dc:type> + </xsl:for-each> + <!-- dc.identifier --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='identifier']/doc:element/doc:field[@name='value']"> + <dc:identifier><xsl:value-of select="." /></dc:identifier> + </xsl:for-each> + <!-- dc.identifier.* --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='identifier']/doc:element/doc:element/doc:field[@name='value']"> <dc:identifier><xsl:value-of select="." /></dc:identifier> </xsl:for-each> + <!-- dc.language --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='language']/doc:element/doc:field[@name='value']"> + <dc:language><xsl:value-of select="." /></dc:language> + </xsl:for-each> + <!-- dc.language.* --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='language']/doc:element/doc:element/doc:field[@name='value']"> <dc:language><xsl:value-of select="." /></dc:language> </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='relation']/doc:element/doc:element/doc:field[@name='value']"> + <!-- dc.relation --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='relation']/doc:element/doc:field[@name='value']"> <dc:relation><xsl:value-of select="." /></dc:relation> </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='relation']/doc:element/doc:field[@name='value']"> + <!-- dc.relation.* --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='relation']/doc:element/doc:element/doc:field[@name='value']"> <dc:relation><xsl:value-of select="." /></dc:relation> </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='rights']/doc:element/doc:element/doc:field[@name='value']"> + <!-- dc.rights --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='rights']/doc:element/doc:field[@name='value']"> <dc:rights><xsl:value-of select="." /></dc:rights> </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='rights']/doc:element/doc:field[@name='value']"> + <!-- dc.rights.* --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='rights']/doc:element/doc:element/doc:field[@name='value']"> <dc:rights><xsl:value-of select="." /></dc:rights> </xsl:for-each> + <!-- dc.format --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='format']/doc:element/doc:field[@name='value']"> + <dc:format><xsl:value-of select="." /></dc:format> + </xsl:for-each> + <!-- dc.format.* --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='format']/doc:element/doc:element/doc:field[@name='value']"> + <dc:format><xsl:value-of select="." /></dc:format> + </xsl:for-each> + <!-- ? --> <xsl:for-each select="doc:metadata/doc:element[@name='bitstreams']/doc:element[@name='bitstream']/doc:field[@name='format']"> <dc:format><xsl:value-of select="." /></dc:format> </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='covarage']/doc:element/doc:field[@name='value']"> - <dc:covarage><xsl:value-of select="." /></dc:covarage> + <!-- dc.coverage --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='coverage']/doc:element/doc:field[@name='value']"> + <dc:coverage><xsl:value-of select="." /></dc:coverage> </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='covarage']/doc:element/doc:element/doc:field[@name='value']"> - <dc:covarage><xsl:value-of select="." /></dc:covarage> + <!-- dc.coverage.* --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='coverage']/doc:element/doc:element/doc:field[@name='value']"> + <dc:coverage><xsl:value-of select="." /></dc:coverage> </xsl:for-each> + <!-- dc.publisher --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='publisher']/doc:element/doc:field[@name='value']"> <dc:publisher><xsl:value-of select="." /></dc:publisher> </xsl:for-each> + <!-- dc.publisher.* --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='publisher']/doc:element/doc:element/doc:field[@name='value']"> <dc:publisher><xsl:value-of select="." /></dc:publisher> </xsl:for-each> + <!-- dc.source --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='source']/doc:element/doc:field[@name='value']"> <dc:source><xsl:value-of select="." /></dc:source> </xsl:for-each> + <!-- dc.source.* --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='source']/doc:element/doc:element/doc:field[@name='value']"> <dc:source><xsl:value-of select="." /></dc:source> </xsl:for-each> diff --git a/dspace/config/crosswalks/oai/metadataFormats/qdc.xsl b/dspace/config/crosswalks/oai/metadataFormats/qdc.xsl index 3cbc6c8150cd072ef2216e8b34562b1b08b39ca1..141a2822786582553cbc3ed9aa77c1baee62026e 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/qdc.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/qdc.xsl @@ -41,6 +41,7 @@ </xsl:for-each> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='description']/doc:element[@name='abstract']/doc:element/doc:field[@name='value']"> <dcterms:abstract xmlns:dcterms="http://purl.org/dc/terms/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://purl.org/dc/terms/ http://dublincore.org/schemas/xmls/qdc/2006/01/06/dcterms.xsd http://purl.org/dc/elements/1.1/ http://dublincore.org/schemas/xmls/qdc/2006/01/06/dc.xsd"> + <xsl:value-of select="." /> </dcterms:abstract> </xsl:for-each> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='date']/doc:element[@name='available']/doc:element/doc:field[@name='value']"> diff --git a/dspace/config/crosswalks/oai/metadataFormats/uketd_dc.xsl b/dspace/config/crosswalks/oai/metadataFormats/uketd_dc.xsl index c7a1aa010d4c1ec38867b38b157f4fbce930027e..8824b9eb57b7c51ef22da867a6bc317db0c91b0e 100644 --- a/dspace/config/crosswalks/oai/metadataFormats/uketd_dc.xsl +++ b/dspace/config/crosswalks/oai/metadataFormats/uketd_dc.xsl @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8" ?> -<!-- +<!-- The contents of this file are subject to the license and copyright @@ -7,99 +7,243 @@ tree and available online at http://www.dspace.org/license/ - Developed by DSpace @ Lyncode <dspace@lyncode.com> + Developed by DSpace @ Lyncode <dspace@lyncode.com> --> -<xsl:stylesheet - xmlns:xsl="http://www.w3.org/1999/XSL/Transform" - xmlns:doc="http://www.lyncode.com/xoai" - version="1.0"> - <xsl:output omit-xml-declaration="yes" method="xml" indent="yes" /> - - <xsl:template match="/"> - <uketd_dc:uketddc - xmlns:uketd_dc="http://naca.central.cranfield.ac.uk/ethos-oai/2.0/" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:dcterms="http://purl.org/dc/terms/" - xmlns:uketdterms="http://naca.central.cranfield.ac.uk/ethos-oai/terms/" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://naca.central.cranfield.ac.uk/ethos-oai/2.0/ http://naca.central.cranfield.ac.uk/ethos-oai/2.0/uketd_dc.xsd"> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='date']/doc:element/doc:element/doc:field[@name='value']"> - <dc:date><xsl:value-of select="." /></dc:date> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='date']/doc:element[@name='issued']/doc:element/doc:field[@name='value']"> - <dcterms:issued><xsl:value-of select="." /></dcterms:issued> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='identifier']/doc:element[@name='uri']/doc:element/doc:field[@name='value']"> - <dcterms:isReferencedBy xsi:type="dcterms:URI"><xsl:value-of select="." /></dcterms:isReferencedBy> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='description']/doc:element[@name='abstract']/doc:element/doc:field[@name='value']"> - <dcterms:abstract><xsl:value-of select="." /></dcterms:abstract> - </xsl:for-each> +<xsl:stylesheet + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:doc="http://www.lyncode.com/xoai" + version="1.0"> + <xsl:output omit-xml-declaration="yes" method="xml" indent="yes" /> + + <xsl:template match="/"> + <uketd_dc:uketddc + xmlns:uketd_dc="http://naca.central.cranfield.ac.uk/ethos-oai/2.0/" + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:dcterms="http://purl.org/dc/terms/" + xmlns:uketdterms="http://naca.central.cranfield.ac.uk/ethos-oai/terms/" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://naca.central.cranfield.ac.uk/ethos-oai/2.0/ http://naca.central.cranfield.ac.uk/ethos-oai/2.0/uketd_dc.xsd"> + + <!-- ******* Title: <dc:title> ******* --> + <!-- dc.title --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='title']/doc:element/doc:field[@name='value']"> - <dc:title><xsl:value-of select="." /></dc:title> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name='author']/doc:element/doc:field[@name='value']"> - <dc:creator><xsl:value-of select="." /></dc:creator> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name!='author']/doc:element/doc:field[@name='value']"> - <dc:contributor><xsl:value-of select="." /></dc:contributor> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']/doc:element/doc:field[@name='value']"> - <dc:subject><xsl:value-of select="." /></dc:subject> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='description']/doc:element/doc:field[@name='value']"> - <dc:description><xsl:value-of select="." /></dc:description> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='description']/doc:element[@name='abstract']/doc:element/doc:field[@name='value']"> - <dc:description><xsl:value-of select="." /></dc:description> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='type']/doc:element/doc:field[@name='value']"> - <dc:type><xsl:value-of select="." /></dc:type> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='identifier']/doc:element/doc:element/doc:field[@name='value']"> - <dc:identifier><xsl:value-of select="." /></dc:identifier> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='language']/doc:element/doc:element/doc:field[@name='value']"> - <dc:language><xsl:value-of select="." /></dc:language> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='relation']/doc:element/doc:element/doc:field[@name='value']"> - <dc:relation><xsl:value-of select="." /></dc:relation> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='relation']/doc:element/doc:field[@name='value']"> - <dc:relation><xsl:value-of select="." /></dc:relation> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='rights']/doc:element/doc:element/doc:field[@name='value']"> - <dc:rights><xsl:value-of select="." /></dc:rights> - </xsl:for-each> + <dc:title><xsl:value-of select="." /></dc:title> + </xsl:for-each> + + <!-- ******* Alternative Title: <dcterms:alternative> ******* --> + <!-- dc.title.alternative --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='title']/doc:element[@name='alternative']/doc:element/doc:field[@name='value']"> + <dcterms:alternative><xsl:value-of select="." /></dcterms:alternative> + </xsl:for-each> + + <!-- ******* Author: <dc.creator> ******* --> + <!-- dc.contributor.author --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name='author']/doc:element/doc:field[@name='value']"> + <dc:creator><xsl:value-of select="." /></dc:creator> + </xsl:for-each> + + <!-- ******* Supervisor(s)/Advisor(s): <uketdterms:advisor> ******* --> + <!-- dc.contributor.advisor --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name='advisor']/doc:element/doc:field[@name='value']"> + <uketdterms:advisor><xsl:value-of select="." /></uketdterms:advisor> + </xsl:for-each> + + <!-- ******* Abstract: <dcterms:abstract> ******* --> + <!-- dc.description.abstract --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='description']/doc:element[@name='abstract']/doc:element/doc:field[@name='value']"> + <dcterms:abstract><xsl:value-of select="." /></dcterms:abstract> + </xsl:for-each> + + <!-- ******* Awarding Insitution: <uketdterms:institution> ******* --> + <!-- dc.publisher --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='publisher']/doc:element/doc:field[@name='value']"> + <uketdterms:institution><xsl:value-of select="." /></uketdterms:institution> + </xsl:for-each> + <!-- dc.publisher.institution --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='publisher']/doc:element[@name='institution']/doc:element/doc:field[@name='value']"> + <uketdterms:institution><xsl:value-of select="." /></uketdterms:institution> + </xsl:for-each> + + <!-- ******* Year of award: <dcterms:issued> ******* --> + <!-- dc.date.issued --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='date']/doc:element[@name='issued']/doc:element/doc:field[@name='value']"> + <dcterms:issued><xsl:value-of select="." /></dcterms:issued> + </xsl:for-each> + <!-- dc.date.awarded --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='date']/doc:element[@name='awarded']/doc:element/doc:field[@name='value']"> + <dcterms:issued><xsl:value-of select="." /></dcterms:issued> + </xsl:for-each> + + <!-- ******* Type: <dc:type> ******* --> + <!-- dc.type --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='type']/doc:element/doc:field[@name='value']"> + <dc:type><xsl:value-of select="." /></dc:type> + </xsl:for-each> + + <!-- ******* Qualification Level: <uketdterms:qualificationlevel> ******* --> + <!-- dc.type.qualificationlevel --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='type']/doc:element[@name='qualificationlevel']/doc:element/doc:field[@name='value']"> + <uketdterms:qualificationlevel><xsl:value-of select="." /></uketdterms:qualificationlevel> + </xsl:for-each> + + <!-- ******* Qualification Name: <uketdterms:qualificationname> ******* --> + <!-- dc.type.qualificationname --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='type']/doc:element[@name='qualificationname']/doc:element/doc:field[@name='value']"> + <uketdterms:qualificationname><xsl:value-of select="." /></uketdterms:qualificationname> + </xsl:for-each> + + <!-- ******* Language: <dc:language xsi:type="dcterms:ISO639-2"> ******* --> + <!-- dc.language.iso --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='language']/doc:element[@name='iso']/doc:element/doc:field[@name='value']"> + <dc:language xsi:type="dcterms:ISO639-2"><xsl:value-of select="." /></dc:language> + </xsl:for-each> + + <!-- ******* Sponsors/Funders: <uketdterms:sponsor> ******* --> + <!-- dc.contributor.sponsor --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name='sponsor']/doc:element/doc:field[@name='value']"> + <uketdterms:sponsor><xsl:value-of select="." /></uketdterms:sponsor> + </xsl:for-each> + <!-- dc.contributor.funder --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name='funder']/doc:element/doc:field[@name='value']"> + <uketdterms:sponsor><xsl:value-of select="." /></uketdterms:sponsor> + </xsl:for-each> + <!-- dc.description.sponsorship --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='description']/doc:element[@name='sponsorship']/doc:element/doc:field[@name='value']"> + <uketdterms:sponsor><xsl:value-of select="." /></uketdterms:sponsor> + </xsl:for-each> + + <!-- ******* Grant Number: <uketdterms:grantnumber> ******* --> + <!-- dc.identifier.grantnumber --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='identifier']/doc:element[@name='grantnumber']/doc:element/doc:field[@name='value']"> + <uketdterms:grantnumber><xsl:value-of select="." /></uketdterms:grantnumber> + </xsl:for-each> + + <!-- ******* Institutional Repository URL: <dcterms:isReferencedBy> ******* --> + <!-- dc.identifier.uri --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='identifier']/doc:element[@name='uri']/doc:element/doc:field[@name='value']"> + <dcterms:isReferencedBy><xsl:value-of select="." /></dcterms:isReferencedBy> + <!-- <dc:identifier xsi:type="dcterms:URI"><xsl:value-of select="." /></dc:identifier> --> + </xsl:for-each> + + <!-- ******* URLs for digital object(s) (obtained from file 'bundles') ******* --> + <xsl:for-each select="doc:metadata/doc:element[@name='bundles']/doc:element[@name='bundle']"> + + <!-- ******* URLs for content bitstreams (from ORIGINAL bundle): <dc:identifier xsi:type="dcterms:URI"> ******* --> + <xsl:if test="doc:field[@name='name']/text() = 'ORIGINAL'"> + <xsl:for-each select="doc:element[@name='bitstreams']/doc:element"> + <dc:identifier xsi:type="dcterms:URI"><xsl:value-of select="doc:field[@name='url']/text()" /></dc:identifier> + <uketdterms:checksum xsi:type="uketdterms:MD5"><xsl:value-of select="doc:field[@name='checksum']/text()" /></uketdterms:checksum> + </xsl:for-each> + </xsl:if> + + <!-- ******* URL for License bitstream (from LICENSE bundle): <dcterms:license> ******* --> + <xsl:if test="doc:field[@name='name']/text() = 'LICENSE'"> + <xsl:for-each select="doc:element[@name='bitstreams']/doc:element"> + <dcterms:license><xsl:value-of select="doc:field[@name='url']/text()" /></dcterms:license> + <uketdterms:checksum xsi:type="uketdterms:MD5"><xsl:value-of select="doc:field[@name='checksum']/text()" /></uketdterms:checksum> + </xsl:for-each> + </xsl:if> + + <!-- ******* URL for extracted text bitstream (from TEXT bundle): <dcterms:hasFormat> ******* --> + <xsl:if test="doc:field[@name='name']/text() = 'TEXT'"> + <xsl:for-each select="doc:element[@name='bitstreams']/doc:element"> + <dcterms:hasFormat><xsl:value-of select="doc:field[@name='url']/text()" /></dcterms:hasFormat> + <uketdterms:checksum xsi:type="uketdterms:MD5"><xsl:value-of select="doc:field[@name='checksum']/text()" /></uketdterms:checksum> + </xsl:for-each> + </xsl:if> + + </xsl:for-each> + + <!-- ******* Embargo Date: <uketdterms:embargodate> ******* --> + <!-- dc.rights.embargodate --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='rights']/doc:element[@name='embargodate']/doc:element/doc:field[@name='value']"> + <uketdterms:embargodate><xsl:value-of select="." /></uketdterms:embargodate> + </xsl:for-each> + <!-- dc.embargo.endate --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='embargo']/doc:element[@name='enddate']/doc:element/doc:field[@name='value']"> + <uketdterms:embargodate><xsl:value-of select="." /></uketdterms:embargodate> + </xsl:for-each> + <!-- dc.embargo.terms --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='embargo']/doc:element[@name='terms']/doc:element/doc:field[@name='value']"> + <uketdterms:embargodate><xsl:value-of select="." /></uketdterms:embargodate> + </xsl:for-each> + + <!-- ******* Embargo Type: <uketdterms:embargotype> ******* --> + + <!-- ******* Rights: <dc:rights> ******* --> + <!-- dc.rights --> <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='rights']/doc:element/doc:field[@name='value']"> - <dc:rights><xsl:value-of select="." /></dc:rights> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='bitstreams']/doc:element[@name='bitstream']/doc:field[@name='format']"> - <dc:format><xsl:value-of select="." /></dc:format> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='covarage']/doc:element/doc:field[@name='value']"> - <dc:covarage><xsl:value-of select="." /></dc:covarage> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='covarage']/doc:element/doc:element/doc:field[@name='value']"> - <dc:covarage><xsl:value-of select="." /></dc:covarage> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='publisher']/doc:element/doc:field[@name='value']"> - <dc:publisher><xsl:value-of select="." /></dc:publisher> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='publisher']/doc:element/doc:element/doc:field[@name='value']"> - <dc:publisher><xsl:value-of select="." /></dc:publisher> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='source']/doc:element/doc:field[@name='value']"> - <dc:source><xsl:value-of select="." /></dc:source> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='source']/doc:element/doc:element/doc:field[@name='value']"> - <dc:source><xsl:value-of select="." /></dc:source> - </xsl:for-each> - <xsl:for-each select="doc:metadata/doc:element[@name='bundles']/doc:element[@name='bundle']/doc:element[@name='bitstreams']/doc:element[@name='bitstream']"> - <dc:identifier xsi:type="dcterms:URI"><xsl:value-of select="doc:field[@name='url']/text()" /></dc:identifier> - <uketdterms:checksum xsi:type="uketdterms:MD5"><xsl:value-of select="doc:field[@name='checksum']/text()" /></uketdterms:checksum> - </xsl:for-each> - </uketd_dc:uketddc> - </xsl:template> + <dc:rights><xsl:value-of select="." /></dc:rights> + </xsl:for-each> + <!-- dc.rights.embargoreason --> + <!-- + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='rights']/doc:element[@name='embargoreason']/doc:element/doc:field[@name='value']"> + <dc:rights><xsl:value-of select="." /></dc:rights> + </xsl:for-each> + --> + + <!-- ******* Subject Keywords: <dc:subject> ******* --> + <!-- dc.subject --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']/doc:element/doc:field[@name='value']"> + <dc:subject><xsl:value-of select="." /></dc:subject> + </xsl:for-each> + <!-- dc.subject.other --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']/doc:element[@name='other']/doc:element/doc:field[@name='value']"> + <dc:subject><xsl:value-of select="." /></dc:subject> + </xsl:for-each> + + <!-- ******* DDC Keywords: <dc:subject xsi:type="dcterms:DDC"> ******* --> + <!-- dc.subject.ddc --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']/doc:element[@name='ddc']/doc:element/doc:field[@name='value']"> + <dc:subject xsi:type="dcterms:DDC"><xsl:value-of select="." /></dc:subject> + </xsl:for-each> + + <!-- ******* LCC Keywords: <dc:subject xsi:type="dcterms:LCC"> ******* --> + <!-- dc.subject.lcc --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']/doc:element[@name='lcc']/doc:element/doc:field[@name='value']"> + <dc:subject xsi:type="dcterms:LCC"><xsl:value-of select="." /></dc:subject> + </xsl:for-each> + + <!-- ******* LCSH Keywords: <dc:subject xsi:type="dcterms:LCSH"> ******* --> + <!-- dc.subject.lcsh --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']/doc:element[@name='lcsh']/doc:element/doc:field[@name='value']"> + <dc:subject xsi:type="dcterms:LCSH"><xsl:value-of select="." /></dc:subject> + </xsl:for-each> + + <!-- ******* MESH Keywords: <dc:subject xsi:type="dcterms:MESH"> ******* --> + <!-- dc.subject.mesh --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='subject']/doc:element[@name='mesh']/doc:element/doc:field[@name='value']"> + <dc:subject xsi:type="dcterms:MESH"><xsl:value-of select="." /></dc:subject> + </xsl:for-each> + + <!-- ******* Author Affiliation: <uketdterms:department> ******* --> + <!-- dc.contributor.affiliation --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='contributor']/doc:element[@name='affiliation']/doc:element/doc:field[@name='value']"> + <uketdterms:department><xsl:value-of select="." /></uketdterms:department> + </xsl:for-each> + <!-- dc.publisher.department --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='publisher']/doc:element[@name='department']/doc:element/doc:field[@name='value']"> + <uketdterms:department><xsl:value-of select="." /></uketdterms:department> + </xsl:for-each> + + <!-- ******* Work Identifier(s): <dc:identifier> ******* --> + <!-- dc.identifier.doi --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='identifier']/doc:element[@name='doi']/doc:element/doc:field[@name='value']"> + <dc:identifier><xsl:value-of select="." /></dc:identifier> + </xsl:for-each> + <!-- dc.identifier.isbn --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='identifier']/doc:element[@name='isbn']/doc:element/doc:field[@name='value']"> + <dc:identifier><xsl:value-of select="." /></dc:identifier> + </xsl:for-each> + <!-- dc.identifier.istc --> + <xsl:for-each select="doc:metadata/doc:element[@name='dc']/doc:element[@name='identifier']/doc:element[@name='istc']/doc:element/doc:field[@name='value']"> + <dc:identifier><xsl:value-of select="." /></dc:identifier> + </xsl:for-each> + + <!-- ******* Author Identifier(s): <uketdterms:authoridentifier> ******* --> + + + </uketd_dc:uketddc> + </xsl:template> </xsl:stylesheet> diff --git a/dspace/config/crosswalks/oai/xoai.xml b/dspace/config/crosswalks/oai/xoai.xml index 9f0d67adc2790bd82db9a2f195e71228c0f0ea00..694723b25ce350118c41eec40a0580c697750cb4 100644 --- a/dspace/config/crosswalks/oai/xoai.xml +++ b/dspace/config/crosswalks/oai/xoai.xml @@ -159,6 +159,7 @@ <XSLT>metadataFormats/uketd_dc.xsl</XSLT> <Namespace>http://naca.central.cranfield.ac.uk/ethos-oai/2.0/</Namespace> <SchemaLocation>http://naca.central.cranfield.ac.uk/ethos-oai/2.0/uketd_dc.xsd</SchemaLocation> + <Filter refid="thesisFilter" /> </Format> </Formats> @@ -239,7 +240,19 @@ <Value>starts_with</Value> </Parameter> <Parameter key="value"> - <Value>info:eurepo/grantAgreement/EC/FP</Value> + <Value>info:eu-repo/grantAgreement/EC/FP</Value> + </Parameter> + </Filter> + <Filter id="thesisFilter"> + <Class>org.dspace.xoai.filter.DSpaceAtLeastOneMetadataFilter</Class> + <Parameter key="field"> + <Value>dc.type</Value> + </Parameter> + <Parameter key="operator"> + <Value>contains</Value> + </Parameter> + <Parameter key="value"> + <Value>Thesis</Value> </Parameter> </Filter> </Filters> diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index f6e43a7c79cd2b058258c3d1aad8483469281bca..de8c3bfa9f175633292d7ef1a89f14534962407b 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -36,15 +36,19 @@ dspace.baseUrl = ${dspace.baseUrl} # Change to xmlui if you wish to use the xmlui as the default, or remove # "/jspui" and set webapp of your choice as the "ROOT" webapp in # the servlet engine. -dspace.url = ${dspace.baseUrl} +dspace.url = ${dspace.baseUrl}/xmlui # Optional: DSpace URL for mobile access # This #dspace.mobileUrl = http://mobile.example.com +dspace.mobileUrl = ${dspace.baseMobileUrl}/xmlui # Name of the site dspace.name = ${dspace.name} +# Base URL of the server hosting the iframe +dspace.iframeBaseURL = ${dspace.iframeBaseURL} + # Default language for metadata values default.language = ${default.language} @@ -107,6 +111,11 @@ mail.server.port = ${mail.server.port} # From address for mail mail.from.address = ${mail.from.address} +# Name of a pre-configured Session object to be fetched from a directory. +# This overrides the Session settings above. If none can be found, then DSpace +# will use the above settings to create a Session. +#mail.session.name = Session + # Currently limited to one recipient! feedback.recipient = ${mail.feedback.recipient} @@ -228,6 +237,25 @@ log.dir = ${dspace.dir}/log # an X-Forward header. If it finds it, it will use this for the user IP address #useProxies = true +##### DOI registration agency credentials ###### +# To mint DOIs you have to use a DOI registration agency like DataCite. Several +# DataCite members offers services as DOI registration agency, so f.e. EZID or +# TIB Hannover. To mint DOIs with DSpace you have to get an agreement with an +# DOI registration agency. You have to edit +# [dspace]/config/spring/api/identifier-service.xml and to configure the following +# properties. + +# Credentials used to authenticate against the registration agency: +identifier.doi.user = username +identifier.doi.password = password +# DOI prefix used to mint DOIs. All DOIs minted by DSpace will use this prefix. +# The Prefix will be assinged by the registration agency. +identifier.doi.prefix = 10.5072 +# If you want to, you can further separate your namespace. Should all the suffix +# of all DOIs minted by DSpace start with a special string to separate it from +# other services also minting DOIs under your prefix? +identifier.doi.namespaceseparator = dspace/ + ##### Search settings ##### # Where to put search index files @@ -317,6 +345,15 @@ handle.prefix = ${handle.prefix} # Directory for installing Handle server files handle.dir = ${dspace.dir}/handle-server +# List any additional prefixes that need to be managed by this handle server +# (as for examle handle prefix coming from old dspace repository merged in +# that repository) +# handle.additional.prefixes = prefix1[, prefix2] + +# By default we hide the list handles method in the JSON endpoint as it could +# produce heavy load for large repository +# handle.hide.listhandles = false + ##### Authorization system configuration - Delegate ADMIN ##### # COMMUNITY ADMIN configuration @@ -396,17 +433,23 @@ http.proxy.port = ${http.proxy.port} # Media/Format Filters help to full-text index content or # perform automated format conversions +xpdf.path.pdftotext = /usr/bin/pdftotext +xpdf.path.pdftoppm = /usr/bin/pdftoppm +xpdf.path.pdfinfo = /usr/bin/pdfinfo + #Names of the enabled MediaFilter or FormatFilter plugins filter.plugins = PDF Text Extractor, HTML Text Extractor, \ PowerPoint Text Extractor, \ - Word Text Extractor, JPEG Thumbnail + Word Text Extractor, JPEG Thumbnail, \ + PDF Thumbnail # [To enable Branded Preview]: remove last line above, and uncomment 2 lines below # Word Text Extractor, JPEG Thumbnail, \ # Branded Preview JPEG #Assign 'human-understandable' names to each filter plugin.named.org.dspace.app.mediafilter.FormatFilter = \ - org.dspace.app.mediafilter.PDFFilter = PDF Text Extractor, \ + org.dspace.app.mediafilter.XPDF2Text = PDF Text Extractor, \ + org.dspace.app.mediafilter.XPDF2Thumbnail = PDF Thumbnail, \ org.dspace.app.mediafilter.HTMLFilter = HTML Text Extractor, \ org.dspace.app.mediafilter.WordFilter = Word Text Extractor, \ org.dspace.app.mediafilter.PowerPointFilter = PowerPoint Text Extractor, \ @@ -420,6 +463,8 @@ filter.org.dspace.app.mediafilter.WordFilter.inputFormats = Microsoft Word filter.org.dspace.app.mediafilter.PowerPointFilter.inputFormats = Microsoft Powerpoint, Microsoft Powerpoint XML filter.org.dspace.app.mediafilter.JPEGFilter.inputFormats = BMP, GIF, JPEG, image/png filter.org.dspace.app.mediafilter.BrandedPreviewJPEGFilter.inputFormats = BMP, GIF, JPEG, image/png +filter.org.dspace.app.mediafilter.XPDF2Thumbnail.inputFormats = Adobe PDF +filter.org.dspace.app.mediafilter.XPDF2Text.inputFormats = Adobe PDF #Custom settings for PDFFilter # If true, all PDF extractions are written to temp files as they are indexed...this @@ -472,6 +517,15 @@ crosswalk.dissemination.marc.schemaLocation = \ http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd crosswalk.dissemination.marc.preferList = true +## +## Configure XSLT-driven submission crosswalk for DataCite +## +crosswalk.dissemination.DataCite.stylesheet = crosswalks/DIM2DataCite.xsl +crosswalk.dissemination.DataCite.schemaLocation = \ + http://datacite.org/schema/kernel-2.2 \ + http://schema.datacite.org/meta/kernel-2.2/metadata.xsd +crosswalk.dissemination.DataCite.preferList = false + # Crosswalk Plugin Configuration: # The purpose of Crosswalks is to translate an external metadata format to/from # the DSpace Internal Metadata format (DIM) or the DSpace Database. @@ -636,11 +690,17 @@ aip.disseminate.dmd = MODS, DIM event.dispatcher.default.class = org.dspace.event.BasicDispatcher # -# uncomment below and comment out original property to enable discovery indexing -# event.dispatcher.default.consumers = versioning, search, browse, discovery, eperson, harvester -# +# uncomment below and comment out original property to enable the legacy lucene indexing # event.dispatcher.default.consumers = versioning, search, browse, eperson, harvester -event.dispatcher.default.consumers = versioning, search, browse, discovery, eperson, harvester +# +# add the browse consumer if you want to switch back to the DBMS Browse DAOs implementation +# as the SOLR implementation rely on the discovery consumer +# +# event.dispatcher.default.consumers = versioning, browse, discovery, eperson, harvester +# +# uncomment event.consumer.doi.class and event.consumer.doi.filters below and add doi here +# if you want to send metadata updates to your doi registration agency. +event.dispatcher.default.consumers = versioning, discovery, eperson, harvester # The noindex dispatcher will not create search or browse indexes (useful for batch item imports) event.dispatcher.noindex.class = org.dspace.event.BasicDispatcher @@ -666,6 +726,10 @@ event.consumer.eperson.filters = EPerson+Create event.consumer.harvester.class = org.dspace.harvest.HarvestConsumer event.consumer.harvester.filters = Item+Delete +# consumer to update metadata of DOIs +#event.consumer.doi.class = org.dspace.identifier.doi.DOIConsumer +#event.consumer.doi.filters = Item+Modify_Metadata + # test consumer for debugging and monitoring #event.consumer.test.class = org.dspace.event.TestConsumer #event.consumer.test.filters = All+All @@ -718,12 +782,26 @@ org.dspace.app.itemexport.life.span.hours = 48 # cummulative sizes are more than this entry the export is not kicked off org.dspace.app.itemexport.max.size = 200 +### Batch Item import settings ### +# The directory where the results of imports will be placed (mapfile, upload file) +org.dspace.app.batchitemimport.work.dir = ${dspace.dir}/imports # For backwards compatibility, the subscription emails by default include any modified items # uncomment the following entry for only new items to be emailed # eperson.subscription.onlynew = true +# Identifier providers. +# Following are configuration values for the EZID DOI provider, with appropriate +# values for testing. Replace the values with your assigned "shoulder" and +# credentials. +#identifier.doi.ezid.shoulder = 10.5072/FK2/ +#identifier.doi.ezid.user = apitest +#identifier.doi.ezid.password = apitest +# A default publisher, for Items not previously published. +#identifier.doi.ezid.publisher = a publisher + + #---------------------------------------------------------------# #--------------JSPUI & XMLUI CONFIGURATIONS---------------------# #---------------------------------------------------------------# @@ -731,6 +809,12 @@ org.dspace.app.itemexport.max.size = 200 # except where explicitly stated otherwise. # #---------------------------------------------------------------# +# Determine if super administrators (those whom are in the Administrators group) +# can login as another user from the "edit eperson" page. This is useful for +# debugging problems in a running dspace instance, especially in the workflow +# process. The default value is false, i.e. no one may assume the login of another user. +#webui.user.assumelogin = true + # whether to display the contents of the licence bundle (often just the deposit # licence in standard DSpace installation webui.licence_bundle.show = false @@ -740,8 +824,6 @@ webui.licence_bundle.show = false # logged-in user is an Administrator: # 1. XMLUI metadata XML view, and Item splash pages (long and short views). # 2. JSPUI Item splash pages -# 3. OAI-PMH server, "oai_dc" format. -# (NOTE: Other formats are _not_ affected.) # To designate a field as hidden, add a property here in the form: # metadata.hide.SCHEMA.ELEMENT.QUALIFIER = true # @@ -760,6 +842,14 @@ webui.submit.blocktheses = false # Defaults to true; If set to 'false', submitter has option to skip upload #webui.submit.upload.required = true +# Whether or not to use the 'advanced' form of the access step. +# Defaults to false, ie the simple form is used. +#webui.submission.restrictstep.enableAdvancedForm = false + +# Special Group for UI: all the groups nested inside this group +# will be loaded in the multiple select list of the RestrictStep +#webui.submission.restrictstep.groups = SubmissionAdmin + #### Creative Commons settings ###### # The url to the web service API @@ -798,6 +888,11 @@ cc.license.classfilter = recombo, mark # (e.g. nz = New Zealand, uk = England and Wales, jp = Japan) cc.license.jurisdiction = us +# Locale for CC dialogs +# A locale in the form language or language-country. +# If no default locale is defined the CC default locale will be used +cc.license.locale = en + ##### Settings for Thumbnail creation ##### @@ -827,6 +922,14 @@ webui.item.thumbnail.show = true thumbnail.maxwidth = 80 thumbnail.maxheight = 80 +# Blur before scaling. A little blur before scaling does wonders for keeping +# moire in check. +thumbnail.blurring = true + +# High quality scaling option. Setting to true can dramatically increase +# image quality, but it takes longer to create thumbnails. +thumbnail.hqscaling = true + #### Settings for Item Preview #### @@ -834,47 +937,80 @@ webui.preview.enabled = false # max dimensions of the preview image webui.preview.maxwidth = 600 webui.preview.maxheight = 600 + +# Blur before scaling. A little blur before scaling does wonders for keeping +# moire in check. +webui.preview.blurring = true + +# High quality scaling option. Setting to true can dramatically increase +# image quality, but it will take much longer to create previews. +webui.preview.hqscaling = true + # the brand text webui.preview.brand = My Institution Name + # an abbreviated form of the above text, this will be used # when the preview image cannot fit the normal text webui.preview.brand.abbrev = MyOrg + # the height of the brand webui.preview.brand.height = 20 + # font settings for the brand text webui.preview.brand.font = SansSerif webui.preview.brand.fontpoint = 12 #webui.preview.dc = rights -##### Settings for content count/strength information #### +##### Settings for item count (strength) information #### # whether to display collection and community strengths -# (This configuration is not used by XMLUI. To show strengths in the -# XMLUI, you just need to create a theme which displays them) +# (Since DSpace 4.0, this config option is used by XMLUI, too. +# XMLUI only makes strengths available to themes if this is set to true! +# To show strengths in the XMLUI, you also need to create a theme which displays them) webui.strengths.show = false -# if showing the strengths, should they be counted in real time or -# fetched from cache? NOTE: To improve scaling/performance, -# the XMLUI only makes strengths available to themes if they are CACHED! +# if showing strengths, should they be counted in real time or +# fetched from cache? # # Counts fetched in real time will perform an actual count of the # database contents every time a page with this feature is requested, -# which will not scale. If the below setting is to use the cache, you -# must run the following command periodically to update the count: +# which will not scale. The default behaviour is to use a cache (see +# ItemCounter configuration) +# +# The default is to use a cache +# +# webui.strengths.cache = true + + +###### ItemCounter Configuration ###### +# +# Define the DAO class to use. This must correspond to your choice of +# storage for the browse system (RDBMS: PostgreSQL or Oracle, Solr). +# By default, since DSpace 4.0, the Solr implementation is used. +# +# Only if you use a DBMS implementation and want to use the cache +# (recommended!), you must run the following command periodically +# to update the count: # -# [dspace]/bin/itemcounter +# [dspace]/bin/itemcounter (NOT required if you use the Solr implementation) # -# The default is to count in real time # -webui.strengths.cache = false +# PostgreSQL: +# ItemCountDAO.class = org.dspace.browse.ItemCountDAOPostgres +# +# Oracle: +# ItemCountDAO.class = org.dspace.browse.ItemCountDAOOracle +# +# Solr: +# ItemCountDAO.class = org.dspace.browse.ItemCountDAOSolr ###### Browse Configuration ###### # # Define the DAO class to use this must meet your storage choice for -# the browse system (RDBMS: PostgreSQL or Oracle, SOLR). -# By default the standard RDBMS implementation for your db is used +# the browse system (RDBMS: PostgreSQL or Oracle, Solr). +# By default, since DSpace 4.0, the Solr implementation is used # # PostgreSQL: # browseDAO.class = org.dspace.browse.BrowseDAOPostgres @@ -884,7 +1020,7 @@ webui.strengths.cache = false # browseDAO.class = org.dspace.browse.BrowseDAOOracle # browseCreateDAO.class = org.dspace.browse.BrowseCreateDAOOracle # -# SOLR: +# Solr: # browseDAO.class = org.dspace.browse.SolrBrowseDAO # browseCreateDAO.class = org.dspace.browse.SolrBrowseCreateDAO @@ -1097,47 +1233,96 @@ webui.browse.link.1 = author:dc.contributor.* recent.submissions.sort-option = dateaccessioned # how many recent submissions should be displayed at any one time -# recent.submissions.count = 5 +# Set to 0 since discovery uses a separate configuration for this recent.submissions.count = 0 +# name of the browse index to display collection's items. +# You can set a "item" type of browse index only. +# default = title +#webui.collectionhome.browse-name = title + +# how mamy items should be displayed per page in collection home page +# default = 20 +#webui.collectionhome.perpage = 20 + +# whether does use "dateaccessioned" as a sort option +# If true and the sort option "dateaccessioned" exists, use "dateaccessioned" as a sort option. +# Otherwise use the sort option pertaining the specified browse index. +# default = true +#webui.collectionhome.use.dateaccessioned = true + # tell the community and collection pages that we are using the Recent # Submissions code -plugin.sequence.org.dspace.plugin.CommunityHomeProcessor = \ - org.dspace.app.webui.components.RecentCommunitySubmissions +#plugin.sequence.org.dspace.plugin.SiteHomeProcessor = \ +# org.dspace.app.webui.components.TopCommunitiesSiteProcessor,\ +# org.dspace.app.webui.components.RecentSiteSubmissions -plugin.sequence.org.dspace.plugin.CollectionHomeProcessor = \ - org.dspace.app.webui.components.RecentCollectionSubmissions +#plugin.sequence.org.dspace.plugin.CommunityHomeProcessor = \ +# org.dspace.app.webui.components.RecentCommunitySubmissions + +#plugin.sequence.org.dspace.plugin.CollectionHomeProcessor = \ +# org.dspace.app.webui.components.RecentCollectionSubmissions,\ +# org.dspace.app.webui.components.CollectionItemList #### JSPUI Discovery (extra Discovery setting that applies only to JSPUI) #### -# uncomment the following configuration if you want use Discovery with JSPUI +# uncomment the following configuration if you want to restore the legacy Lucene +# search provider with JSPUI (be sure to re-enable also the search consumer) # plugin.single.org.dspace.app.webui.search.SearchRequestProcessor = \ -# org.dspace.app.webui.discovery.DiscoverySearchRequestProcessor +# org.dspace.app.webui.search.LuceneSearchRequestProcessor # -# default is to use the Legacy Lucene search engine +# default since DSpace 4.0 is to use the Discovery search provider plugin.single.org.dspace.app.webui.search.SearchRequestProcessor = \ - org.dspace.app.webui.search.LuceneSearchRequestProcessor + org.dspace.app.webui.discovery.DiscoverySearchRequestProcessor + +#### XMLUI Discovery (extra Discovery setting that applies only to XMLUI) #### +# uncomment the following configuration if you want to restore the legacy Lucene +# search provider with XMLUI (be sure to re-enable also the search consumer) +# plugin.single.org.dspace.app.xmlui.aspect.administrative.mapper.SearchRequestProcessor = \ +# org.dspace.app.xmlui.aspect.administrative.mapper.LuceneSearchRequestProcessor +# +# default since DSpace 4.0 is to use the Discovery search provider +plugin.single.org.dspace.app.xmlui.aspect.administrative.mapper.SearchRequestProcessor = \ + org.dspace.app.xmlui.aspect.administrative.mapper.DiscoverySearchRequestProcessor #### Sidebar Facets #### # to show facets on the site home page, community, collection -# uncomments the following lines -#plugin.sequence.org.dspace.plugin.CommunityHomeProcessor = \ -# org.dspace.app.webui.components.RecentCommunitySubmissions,\ -# org.dspace.app.webui.discovery.SideBarFacetProcessor -# -#plugin.sequence.org.dspace.plugin.CollectionHomeProcessor = \ +# comment out the following lines if you disable Discovery or don't want +# to show facets on side bars +plugin.sequence.org.dspace.plugin.CommunityHomeProcessor = \ + org.dspace.app.webui.components.RecentCommunitySubmissions,\ + org.dspace.app.webui.discovery.SideBarFacetProcessor + +plugin.sequence.org.dspace.plugin.CollectionHomeProcessor = \ + org.dspace.app.webui.components.CollectionItemList,\ + org.dspace.app.webui.discovery.SideBarFacetProcessor # org.dspace.app.webui.components.RecentCollectionSubmissions,\ -# org.dspace.app.webui.discovery.SideBarFacetProcessor -# -#plugin.sequence.org.dspace.plugin.SiteHomeProcessor = \ -# org.dspace.app.webui.discovery.SideBarFacetProcessor + +plugin.sequence.org.dspace.plugin.SiteHomeProcessor = \ + org.dspace.app.webui.components.TopCommunitiesSiteProcessor,\ + org.dspace.app.webui.components.RecentSiteSubmissions,\ + org.dspace.app.webui.discovery.SideBarFacetProcessor #### JSON JSPUI Request Handler #### # define any JSON handler here # # comment out this line if you disable Discovery plugin.named.org.dspace.app.webui.json.JSONRequest = \ - org.dspace.app.webui.discovery.DiscoveryJSONRequest = discovery + org.dspace.app.webui.discovery.DiscoveryJSONRequest = discovery,\ + org.dspace.app.webui.json.SubmissionLookupJSONRequest = submissionLookup,\ + org.dspace.app.webui.json.UploadProgressJSON = uploadProgress,\ + org.dspace.app.webui.handle.HandleJSONResolver = hdlresolver +### i18n - Locales / Language #### +# Default Locale +# A Locale in the form country or country_language or country_language_variant +# if no default locale is defined the server default locale will be used. +default.locale = en + +# All the Locales, that are supported by this instance of DSpace +# A comma-separated list of Locales. All types of Locales country, country_language, country_language_variant +# Note that the appropriate file are present, especially that all the Messages_x.properties are there +# may be used, e. g: webui.supported.locales = en, de +webui.supported.locales = pt_BR, en #### Submission License substitution variables #### # it is possible include contextual information in the submission license using substitution variables @@ -1189,9 +1374,11 @@ webui.feed.item.date = dc.date.issued # e.g. "metadata.dc.title" # "metadata.dc.contributor.author" # "metadata.dc.date.issued" -webui.feed.item.description = dc.title, dc.contributor.author, \ - dc.contributor.editor, dc.description.abstract, \ - dc.description +#webui.feed.item.description = dc.title, dc.contributor.author, \ +# dc.contributor.editor, dc.description.abstract, \ +# dc.description +webui.feed.item.description = dc.contributor.author, dc.description + # name of field to use for authors (Atom only) - repeatable webui.feed.item.author = dc.contributor.author @@ -1308,6 +1495,17 @@ sitemap.engineurls = http://www.google.com/webmasters/sitemaps/ping?sitemap= # # No known Sitemap 'ping' URL for MSN/Live search +##### SHERPA/Romeo Integration Settings #### +# the SHERPA/RoMEO endpoint +sherpa.romeo.url = http://www.sherpa.ac.uk/romeo/api29.php + +# to disable the sherpa/romeo integration actually available only in JSPUI +# uncomment the follow line +# webui.submission.sherparomeo-policy-enabled = false + +# please register for a free api access key to get many benefits +# http://www.sherpa.ac.uk/news/romeoapikeys.htm +# sherpa.romeo.apikey = YOUR-API-KEY ##### Authority Control Settings ##### @@ -1339,9 +1537,6 @@ sitemap.engineurls = http://www.google.com/webmasters/sitemaps/ping?sitemap= ## configure LC Names plugin #lcname.url = http://alcme.oclc.org/srw/search/lcnaf -## configure SHERPA/RoMEO authority plugin -#sherpa.romeo.url = http://www.sherpa.ac.uk/romeo/api24.php - ## ## This sets the default lowest confidence level at which a metadata value is included ## in an authority-controlled browse (and search) index. It is a symbolic @@ -1412,13 +1607,25 @@ webui.bitstream.order.field = bitstream_order google-metadata.config = ${dspace.dir}/config/crosswalks/google-metadata.properties google-metadata.enable = true - - #---------------------------------------------------------------# #--------------JSPUI SPECIFIC CONFIGURATIONS--------------------# #---------------------------------------------------------------# # These configs are only used by the JSP User Interface # #---------------------------------------------------------------# +##### JSPUI Layout ##### +# set this value if you want to use a diffent main template. +# The value must match the name of a subfolder of dspace-jspui/src/main/webapp/layout +# jspui.template.name = + +##### Show community or collection logo in list ##### +# jspui.home-page.logos = true +# jspui.community-home.logos = true +# jspui.community-list.logos = true + +##### Item Home Processor ##### + +plugin.sequence.org.dspace.plugin.ItemHomeProcessor = \ + org.dspace.app.webui.components.VersioningItemHome ##### Upload File settings ##### @@ -1577,18 +1784,6 @@ plugin.single.org.dspace.app.webui.util.StyleSelection = \ # webui.itemlist.tablewidth = 100% -### i18n - Locales / Language #### -# Default Locale -# A Locale in the form country or country_language or country_language_variant -# if no default locale is defined the server default locale will be used. -default.locale = pt_BR - -# All the Locales that are supported by this instance of DSpace -# A comma-separated list of Locales. All types of Locales country, country_language, country_language_variant -# Note that the appropriate file are present, especially that all the Messages_x.properties are there -# may be used, e. g: webui.supported.locales = en, de -webui.supported.locales = pt_BR, en - #### Additional configuration for Item Mapper #### # the index name (from webui.browse.index above) to use for @@ -1663,7 +1858,6 @@ webui.suggest.enable = false # Take this key (just the UA-XXXXXX-X part) and place it here in this parameter. # jspui.google.analytics.key=UA-XXXXXX-X - #---------------------------------------------------------------# #--------------XMLUI SPECIFIC CONFIGURATIONS--------------------# #---------------------------------------------------------------# @@ -1671,14 +1865,6 @@ webui.suggest.enable = false #---------------------------------------------------------------# -# A list of supported locales for Manakin. Manakin will look at a user's browser -# configuration for the first language that appears in this list to make available -# to in the interface. This parameter is a comma-separated list of Locales. All -# types of Locales country, country_language, country_language_variant -# Note that that if the approprate files are not present (i.e. Messages_XX_XX.xml) -# then Manakin will fall back through to a more general language. -xmlui.supported.locales = pt_BR, en - # Force all authenticated connections to use SSL, only non-authenticated # connections are allowed over plain http. If set to true, then you need to # ensure that the 'dspace.hostname' parameter is set to the correctly. @@ -1691,13 +1877,6 @@ xmlui.supported.locales = pt_BR, en #xmlui.user.registration=true #xmlui.user.editmetadata=true - -# Determine if super administrators (those whom are in the Administrators group) -# can login as another user from the "edit eperson" page. This is useful for -# debugging problems in a running dspace instance, especially in the workflow -# process. The default value is false, i.e. no one may assume the login of another user. -#xmlui.user.assumelogin = true - # Check if the user has a consistent ip address from the start of the login process # to the end of the login process. Disabling this check is not recommended unless # absolutely necessary as the ip check can be helpful for preventing session @@ -1721,7 +1900,6 @@ xmlui.supported.locales = pt_BR, en # and debugging it should be turned off for any production repository. The default # value unless otherwise specified is "false" #xmlui.theme.allowoverrides = false -xmlui.theme.allowoverrides = true # Enabling this property will concatenate CSS, JS and JSON files where possible. # CSS files can be concatenated if multiple CSS files with the same media attribute @@ -1794,8 +1972,16 @@ xmlui.theme.allowoverrides = true # records the original IP address. #xmlui.controlpanel.activity.ipheader = X-Forward-For +#---------------------------------------------------------------# +#----------------REQUEST ITEM CONFIGURATION---------------------# +#---------------------------------------------------------------# + +# Configuration of request-item. Possible values: +# all - Anonymous users can request an item +# logged - Login is mandatory to request an item +# empty/commented out - request-copy not allowed +request.item.type = all +# Helpdesk E-mail +mail.helpdesk = ${mail.admin} -# Special Group for UI: all the groups nested inside this group -# will be loaded in the multiple select list of the RestrictStep -xmlui.submission.restrictstep.groups=SubmissionAdmin -xmlui.submission.restrictstep.enableAdvancedForm=true +#------------END REQUEST ITEM CONFIGURATION---------------------# diff --git a/dspace/config/emails/bkp.change_password b/dspace/config/emails/bkp.change_password deleted file mode 100644 index 3b64ae7d4b3c3193d030cc0904e77fd866895c27..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.change_password +++ /dev/null @@ -1,18 +0,0 @@ -# Email sent to DSpace users when they forget their password. -# -# Parameters: {0} is expanded to a special URL -# -# See org.dspace.core.Email for information on the format of this file. -# -Subject: Alteração de senha - -Recebemos sua solicitação de recuperação de senha. -Para alterá-la, clique em: - - {0} - -Se você não solicitou a recuperação da senha, ignore esta mensagem. - -Atenciosamente, -Equipe Participatório - diff --git a/dspace/config/emails/bkp.export_error b/dspace/config/emails/bkp.export_error deleted file mode 100644 index 571df69553bde9b50bb325353acce26b0615cf47..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.export_error +++ /dev/null @@ -1,19 +0,0 @@ -# Email sent to DSpace users when they successfully export an item or collection. -# -# Parameters: {0} the export error -# {1} the URL to the feedback page -# -# -# See org.dspace.core.Email for information on the format of this file. -# -Subject: DSpace - The item export you requested was not completed. -The item export you requested was not completed, due to the following reason: - {0} - -For more information you may contact your system administrator: - {1} - - - -The DSpace Team - diff --git a/dspace/config/emails/bkp.export_success b/dspace/config/emails/bkp.export_success deleted file mode 100644 index 2396e5ce5e14f4374222000a037014872175baa3..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.export_success +++ /dev/null @@ -1,18 +0,0 @@ -# Email sent to DSpace users when they successfully export an item or collection. -# -# Parameters: {0} is expanded to a special URL -# {1} configurable time (hours) an export file will be kept -# -# See org.dspace.core.Email for information on the format of this file. -# -Subject: DSpace - Item export requested is ready for download -The item export you requested from the repository is now ready for download. - -You may download the compressed file using the following link: -{0} - -This file will remain available for at least {1} hours. - - -The DSpace Team - diff --git a/dspace/config/emails/bkp.feedback b/dspace/config/emails/bkp.feedback deleted file mode 100644 index e7f972e4b5b12a35b3930a038901f34cd5c868d6..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.feedback +++ /dev/null @@ -1,26 +0,0 @@ -# E-mail sent with the information filled out in a feedback form. -# -# Parameters: {0} current date -# {1} email address that the user provided -# {2} logged in as -# {3} page that the user was on when they selected feedback -# {4} User-Agent HTTP Header -# {5} Session Id -# {6} The user's comments -# -# See org.dspace.core.Email for information on the format of this file. -# -Subject: Feedback Form Information - -Comments: - -{6} - - -Date: {0} -Email: {1} -Logged In As: {2} -Referring Page: {3} -User Agent: {4} -Session: {5} - diff --git a/dspace/config/emails/bkp.flowtask_notify b/dspace/config/emails/bkp.flowtask_notify deleted file mode 100644 index 4b494180e77c8474ad944f4ab8a41e7a9008a21a..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.flowtask_notify +++ /dev/null @@ -1,23 +0,0 @@ -# Workflow curation task notification email message -# -# {0} Title of submission -# {1} Name of collection -# {2} Submitter's name -# {3} Name of task operating -# {4} Task result -# {5} Workflow action taken -# -Subject: DSpace: Curation Task Report - -Title: {0} -Collection: {1} -Submitted by: {2} - -Curation task {3} has been performed -with the following result: - -{4} - -Action taken on the submission: {5} - -DSpace diff --git a/dspace/config/emails/bkp.harvesting_error b/dspace/config/emails/bkp.harvesting_error deleted file mode 100644 index e863be842448055a8f821ad7056cf20e1a07aeaf..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.harvesting_error +++ /dev/null @@ -1,20 +0,0 @@ -# E-mail sent to designated address when a harvest process fails -# -# Parameters: {0} Collection id -# {1} Date & time -# {2} Status flag -# {3} Exception message -# {4} Exception stack trace -# -# See org.dspace.core.Email for information on the format of this file. -# -Subject: DSpace: Harvesting Error -Collection {0} failed on harvest: - -Date: {1} -Status Flag: {2} - -{3} - -Exception: -{4} diff --git a/dspace/config/emails/bkp.internal_error b/dspace/config/emails/bkp.internal_error deleted file mode 100644 index 9f1c8db7a4f90047c15ffd3abbf65151b02cc617..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.internal_error +++ /dev/null @@ -1,24 +0,0 @@ -# E-mail sent to designated address when an internal server error occurs -# -# Parameters: {0} DSpace server URL -# {1} Date & time -# {2} Session ID -# {3} URL + HTTP parameters, if any -# {4} Exception stack trace -# {5} User details -# {6} IP address -# -# See org.dspace.core.Email for information on the format of this file. -# -Subject: DSpace: Internal Server Error -An internal server error occurred on {0}: - -Date: {1} -Session ID: {2} -User: {5} -IP address: {6} - -{3} - -Exception: -{4} diff --git a/dspace/config/emails/bkp.register b/dspace/config/emails/bkp.register deleted file mode 100644 index 7439da86dd4dccce4ace9588a6d8d3f5a4df77e4..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.register +++ /dev/null @@ -1,16 +0,0 @@ -# E-mail sent to DSpace users when they register for an account -# -# Parameters: {0} is expanded to a special registration URL -# -# See org.dspace.core.Email for information on the format of this file. -# -Subject: DSpace Account Registration -To complete registration for a DSpace account, please click the link -below: - - {0} - -If you need assistance with your account, please email -dspace-help@myu.edu or call us at xxx-555-xxxx. - -The DSpace Team diff --git a/dspace/config/emails/bkp.registration_notify b/dspace/config/emails/bkp.registration_notify deleted file mode 100644 index 9802ae887d48a3cdd2b4a26bc187f78c789c37cf..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.registration_notify +++ /dev/null @@ -1,17 +0,0 @@ -# Registration notification email -# -# Parameters: {0} The name of the DSpace instance -# {1} The URL of the DSpace instance -# {2} Name: -# {3} Email: -# {4} Registration Date: -# -# See org.dspace.core.Email for information on the format of this file. -# -Subject: DSpace: Registration Notification - -A new user has registered on {0} at {1}: - -Name: {2} -Email: {3} -Date: {4} diff --git a/dspace/config/emails/bkp.submit_archive b/dspace/config/emails/bkp.submit_archive deleted file mode 100644 index 39e3c105a2d4fa3bc7a57d5c254bcca029aff2a0..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.submit_archive +++ /dev/null @@ -1,21 +0,0 @@ -# Item Archived email message -# -# {0} Title of submission -# {1} Name of collection -# {2} handle -# -Subject: DSpace: Submission Approved and Archived - -You submitted: {0} - -To collection: {1} - -Your submission has been accepted and archived in DSpace, -and it has been assigned the following identifier: -{2} - -Please use this identifier when citing your submission. - -Many thanks! - -DSpace diff --git a/dspace/config/emails/bkp.submit_reject b/dspace/config/emails/bkp.submit_reject deleted file mode 100644 index 7408546462531c2e009a917fb8dfc45fa873eac8..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.submit_reject +++ /dev/null @@ -1,23 +0,0 @@ -# Rejection email message -# -# {0} Title of submission -# {1} Name of collection -# {2} Name of the rejector -# {3} Reason for the rejection -# {4} Link to 'My DSpace' page -# -Subject: DSpace: Submission Rejected - -You submitted: {0} - -To collection: {1} - -Your submission has been rejected by {2} -with the following explanation: - -{3} - -Your submission has not been deleted. You can access it from your -"My DSpace" page: {4} - -DSpace diff --git a/dspace/config/emails/bkp.submit_task b/dspace/config/emails/bkp.submit_task deleted file mode 100644 index b2354c8252321458e4298559d07ccbd2cc39066f..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.submit_task +++ /dev/null @@ -1,24 +0,0 @@ -# Workflow task email message -# -# {0} Title of submission -# {1} Name of collection -# {2} submitter's name -# {3} Description of task -# {4} link to 'my DSpace' page -# -Subject: DSpace: You have a new task - -A new item has been submitted: - -Title: {0} -Collection: {1} -Submitted by: {2} - -{3} - -To claim this task, please visit your "My DSpace" -page: {4} - -Many thanks! - -DSpace diff --git a/dspace/config/emails/bkp.subscription b/dspace/config/emails/bkp.subscription deleted file mode 100644 index 6310a36c3654bb95b8dd67d8d6f3314d87065c5e..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.subscription +++ /dev/null @@ -1,12 +0,0 @@ -# E-mail sent to DSpace users when new items appear in collections they are -# subscribed to -# -# Parameters: {0} is the details of the new collections and items -# See org.dspace.core.Email for information on the format of this file. -# -Subject: DSpace Subscription -New items are available in the collections you have subscribed to: - -{0} - -DSpace diff --git a/dspace/config/emails/bkp.suggest b/dspace/config/emails/bkp.suggest deleted file mode 100644 index 4c4db3efac07b6b4089628b848e5e7f84b7ffa5a..0000000000000000000000000000000000000000 --- a/dspace/config/emails/bkp.suggest +++ /dev/null @@ -1,26 +0,0 @@ -# E-mail sent with the information filled out in a suggest form. -# -# Parameters: {0} recipient name -# {1} sender name -# {2} repository name -# {3} item title -# {4} item handle URI -# {5} item local URL - may be used in lieu of {4} if not using handle server -# {6} collection name -# {7} sender message -# See org.dspace.core.Email for information on the format of this file. -# -Subject: An item of interest from DSpace - -Hello {0}: - -{1} requested we send you this email regarding an item available in {2}. - -Title: {3} -Location: {5} -In Collection: {6} -Personal Message: {7} - -The DSpace digital repository system captures, stores, indexes, preserves, and distributes digital material. -For more information, visit www.dspace.org - diff --git a/dspace/config/input-forms.xml b/dspace/config/input-forms.xml index c81fb1748efe1699b750c73e793b036c8d8e99f8..e5a572f06a713ff709ab1534c6bfa0e08d39f833 100644 --- a/dspace/config/input-forms.xml +++ b/dspace/config/input-forms.xml @@ -14,7 +14,7 @@ <!-- the mapping for handle "default". --> <form-map> - <name-map collection-handle="default" form-name="traditional" /> + <name-map collection-handle="default" form-name="dspacesnj" /> </form-map> @@ -35,8 +35,8 @@ <!-- serves as a 'this field is required' flag. --> <form-definitions> - - <form name="traditional"> + + <form name="dspacesnj"> <page number="1"> <field> <dc-schema>dc</dc-schema> @@ -152,8 +152,6 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <required></required> </field> -<!-- ####################################################################################### --> - <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> @@ -164,6 +162,7 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> @@ -174,6 +173,7 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> @@ -184,6 +184,7 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> @@ -194,7 +195,7 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <hint></hint> <required></required> </field> -<!-- ####################################################################################### --> + </page> <page number="2"> @@ -238,185 +239,366 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <dc-element>description</dc-element> <dc-qualifier></dc-qualifier> <repeatable>false</repeatable> - <label>Description</label> + <label>Descrição</label> <input-type>textarea</input-type> <hint>Digite qualquer outra descrição ou comentários abaixo. </hint> <required></required> </field> - -<!-- ####################################################################################### --> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>grade</dc-qualifier> <repeatable>false</repeatable> <label>Nota</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>supervisor</dc-qualifier> <repeatable>true</repeatable> <label>Orientador</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>cosupervisor</dc-qualifier> <repeatable>true</repeatable> <label>Coorientador</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>jurymembers</dc-qualifier> <repeatable>true</repeatable> <label>Membros da Banca</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>defenselocation</dc-qualifier> <repeatable>false</repeatable> - <label>Local da Banca</label> - <input-type>onebox</input-type> + <label>Local da Defesa</label> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>defensedate</dc-qualifier> <repeatable>false</repeatable> <label>Data da defesa</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>defenceinstitution</dc-qualifier> <repeatable>false</repeatable> <label>Instituição da Defesa</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>defensedepartment</dc-qualifier> <repeatable>false</repeatable> <label>Departamento da Defesa</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>programme</dc-qualifier> <repeatable>false</repeatable> <label>Programa</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> -<!-- #######################################################################################3 --> + <field> <dc-schema>dc</dc-schema> <dc-element>creator</dc-element> <dc-qualifier>director</dc-qualifier> <repeatable>false</repeatable> <label>Diretor</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>creator</dc-element> <dc-qualifier>screenplay</dc-qualifier> <repeatable>false</repeatable> <label>Roteirista</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>creator</dc-element> <dc-qualifier>production</dc-qualifier> <repeatable>false</repeatable> <label>Produção</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>coverage</dc-element> <dc-qualifier>temporal</dc-qualifier> <repeatable>false</repeatable> <label>Tempo de Duração</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>type</dc-element> <dc-qualifier>color</dc-qualifier> <repeatable>false</repeatable> <label>Sistema de Cor</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>category</dc-qualifier> <repeatable>false</repeatable> <label>Categoria</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>description</dc-element> <dc-qualifier>copyformat</dc-qualifier> <repeatable>false</repeatable> <label>Formato da Cópia</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> + <field> <dc-schema>dc</dc-schema> <dc-element>format</dc-element> <dc-qualifier>material</dc-qualifier> <repeatable>false</repeatable> <label>Tratamento</label> - <input-type>onebox</input-type> + <input-type>textarea</input-type> <hint></hint> <required></required> </field> -<!-- #######################################################################################3 --> + + </page> + + </form> + + <form name="traditional"> + <page number="1"> + <field> + <dc-schema>dc</dc-schema> + <dc-element>contributor</dc-element> + <dc-qualifier>author</dc-qualifier> + <repeatable>true</repeatable> + <label>Authors</label> + <input-type>name</input-type> + <hint>Enter the names of the authors of this item below.</hint> + <required></required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>title</dc-element> + <dc-qualifier></dc-qualifier> + <repeatable>false</repeatable> + <label>Title</label> + <input-type>onebox</input-type> + <hint>Enter the main title of the item.</hint> + <required>You must enter a main title for this item.</required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>title</dc-element> + <dc-qualifier>alternative</dc-qualifier> + <repeatable>true</repeatable> + <label>Other Titles</label> + <input-type>onebox</input-type> + <hint>If the item has any alternative titles, please enter them below.</hint> + <required></required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>date</dc-element> + <dc-qualifier>issued</dc-qualifier> + <repeatable>false</repeatable> + <label>Date of Issue</label> + <input-type>date</input-type> + <hint>Please give the date of previous publication or public distribution + below. You can leave out the day and/or month if they aren't + applicable.</hint> + <required>You must enter at least the year.</required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>publisher</dc-element> + <dc-qualifier></dc-qualifier> + <repeatable>false</repeatable> + <label>Publisher</label> + <input-type>onebox</input-type> + <hint>Enter the name of the publisher of the previously issued instance of this item.</hint> + <required></required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>identifier</dc-element> + <dc-qualifier>citation</dc-qualifier> + <repeatable>false</repeatable> + <label>Citation</label> + <input-type>onebox</input-type> + <hint>Enter the standard citation for the previously issued instance of this item.</hint> + <required></required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>relation</dc-element> + <dc-qualifier>ispartofseries</dc-qualifier> + <repeatable>true</repeatable> + <label>Series/Report No.</label> + <input-type>series</input-type> + <hint>Enter the series and number assigned to this item by your community.</hint> + <required></required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>identifier</dc-element> + <dc-qualifier></dc-qualifier> + <!-- An input-type of qualdrop_value MUST be marked as repeatable --> + <repeatable>true</repeatable> + <label>Identifiers</label> + <input-type value-pairs-name="common_identifiers">qualdrop_value</input-type> + <hint>If the item has any identification numbers or codes associated with +it, please enter the types and the actual numbers or codes below.</hint> + <required></required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>type</dc-element> + <dc-qualifier></dc-qualifier> + <repeatable>true</repeatable> + <label>Type</label> + <input-type value-pairs-name="common_types">dropdown</input-type> + <hint>Select the type(s) of content of the item. To select more than one value in the list, you may have to hold down the "CTRL" or "Shift" key.</hint> + <required></required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>language</dc-element> + <dc-qualifier>iso</dc-qualifier> + <repeatable>false</repeatable> + <label>Language</label> + <input-type value-pairs-name="common_iso_languages">dropdown</input-type> + <hint>Select the language of the main content of the item. If the language does not appear in the list below, please select 'Other'. If the content does not really have a language (for example, if it is a dataset or an image) please select 'N/A'.</hint> + <required></required> + </field> + </page> + + <page number="2"> + <field> + <dc-schema>dc</dc-schema> + <dc-element>subject</dc-element> + <dc-qualifier></dc-qualifier> + <!-- An input-type of twobox MUST be marked as repeatable --> + <repeatable>true</repeatable> + <label>Subject Keywords</label> + <input-type>twobox</input-type> + <hint>Enter appropriate subject keywords or phrases below. </hint> + <required></required> + <vocabulary>srsc</vocabulary> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>description</dc-element> + <dc-qualifier>abstract</dc-qualifier> + <repeatable>false</repeatable> + <label>Abstract</label> + <input-type>textarea</input-type> + <hint>Enter the abstract of the item below. </hint> + <required></required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>description</dc-element> + <dc-qualifier>sponsorship</dc-qualifier> + <repeatable>false</repeatable> + <label>Sponsors</label> + <input-type>textarea</input-type> + <hint>Enter the names of any sponsors and/or funding codes in the box below. </hint> + <required></required> + </field> + + <field> + <dc-schema>dc</dc-schema> + <dc-element>description</dc-element> + <dc-qualifier></dc-qualifier> + <repeatable>false</repeatable> + <label>Description</label> + <input-type>textarea</input-type> + <hint>Enter any other description or comments in this box. </hint> + <required></required> + </field> </page> </form> @@ -427,9 +609,9 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <dc-element>contributor</dc-element> <dc-qualifier>author</dc-qualifier> <repeatable>true</repeatable> - <label>Um: Autores</label> + <label>One: Authors</label> <input-type>name</input-type> - <hint>Digite os nomes dos autores deste item abaixo.</hint> + <hint>Enter the names of the authors of this item below.</hint> <required></required> </field> </page> @@ -457,7 +639,7 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <stored-value>issn</stored-value> </pair> <pair> - <displayed-value>Other</displayed-value> + <displayed-value>Outro</displayed-value> <stored-value>other</stored-value> </pair> <pair> @@ -465,7 +647,7 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <stored-value>ismn</stored-value> </pair> <pair> - <displayed-value>Gov't Doc #</displayed-value> + <displayed-value>Documento Governamental</displayed-value> <stored-value>govdoc</stored-value> </pair> <pair> @@ -480,19 +662,23 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <value-pairs value-pairs-name="common_types" dc-term="type"> <pair> - <displayed-value>Animation</displayed-value> + <displayed-value>Dissertação</displayed-value> + <stored-value>Dissertation</stored-value> + </pair> + <pair> + <displayed-value>Animação</displayed-value> <stored-value>Animation</stored-value> </pair> <pair> - <displayed-value>Article</displayed-value> + <displayed-value>Artigo</displayed-value> <stored-value>Article</stored-value> </pair> <pair> - <displayed-value>Book</displayed-value> + <displayed-value>Livro</displayed-value> <stored-value>Book</stored-value> </pair> <pair> - <displayed-value>Book chapter</displayed-value> + <displayed-value>Capítulo de Livro</displayed-value> <stored-value>Book chapter</stored-value> </pair> <pair> @@ -504,43 +690,43 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <stored-value>Learning Object</stored-value> </pair> <pair> - <displayed-value>Image</displayed-value> + <displayed-value>Imagem</displayed-value> <stored-value>Image</stored-value> </pair> <pair> - <displayed-value>Image, 3-D</displayed-value> + <displayed-value>Imagem, 3-D</displayed-value> <stored-value>Image, 3-D</stored-value> </pair> <pair> - <displayed-value>Map</displayed-value> + <displayed-value>Mapa</displayed-value> <stored-value>Map</stored-value> </pair> <pair> - <displayed-value>Musical Score</displayed-value> + <displayed-value>Partitura</displayed-value> <stored-value>Musical Score</stored-value> </pair> <pair> - <displayed-value>Plan or blueprint</displayed-value> + <displayed-value>Plano ou Diagrama</displayed-value> <stored-value>Plan or blueprint</stored-value> </pair> <pair> - <displayed-value>Preprint</displayed-value> + <displayed-value>Pré-Impressão</displayed-value> <stored-value>Preprint</stored-value> </pair> <pair> - <displayed-value>Presentation</displayed-value> + <displayed-value>Apresentação</displayed-value> <stored-value>Presentation</stored-value> </pair> <pair> - <displayed-value>Recording, acoustical</displayed-value> + <displayed-value>Gravação, acústica</displayed-value> <stored-value>Recording, acoustical</stored-value> </pair> <pair> - <displayed-value>Recording, musical</displayed-value> + <displayed-value>Gravação, musical</displayed-value> <stored-value>Recording, musical</stored-value> </pair> <pair> - <displayed-value>Recording, oral</displayed-value> + <displayed-value>Gravação, oral</displayed-value> <stored-value>Recording, oral</stored-value> </pair> <pair> @@ -548,15 +734,15 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <stored-value>Software</stored-value> </pair> <pair> - <displayed-value>Technical Report</displayed-value> + <displayed-value>Relatório Técnico</displayed-value> <stored-value>Technical Report</stored-value> </pair> <pair> - <displayed-value>Thesis</displayed-value> + <displayed-value>Tese</displayed-value> <stored-value>Thesis</stored-value> </pair> <pair> - <displayed-value>Video</displayed-value> + <displayed-value>Vídeo</displayed-value> <stored-value>Video</stored-value> </pair> <pair> @@ -564,15 +750,21 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <stored-value>Working Paper</stored-value> </pair> <pair> - <displayed-value>Other</displayed-value> + <displayed-value>Outro</displayed-value> <stored-value>Other</stored-value> </pair> </value-pairs> - <!-- reordenado: - "pt_BR, "en_US", "pt", "en", "es", "de", "fr", "it", "ja", "zh", "other", "" + <!-- default language order: (from dspace 1.2.1) + "pt_BR", "en_US", "en", "es", "de", "fr", "it", "ja", "zh", "other", "" --> <value-pairs value-pairs-name="common_iso_languages" dc-term="language_iso"> + <!-- + <pair> + <displayed-value>N/A</displayed-value> + <stored-value></stored-value> + </pair> + --> <pair> <displayed-value>Português (Brasil)</displayed-value> <stored-value>pt_BR</stored-value> @@ -580,11 +772,7 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <pair> <displayed-value>English (United States)</displayed-value> <stored-value>en_US</stored-value> - </pair> - <pair> - <displayed-value>Português</displayed-value> - <stored-value>pt</stored-value> - </pair> + </pair> <pair> <displayed-value>English</displayed-value> <stored-value>en</stored-value> @@ -617,10 +805,6 @@ por favor insira os tipos e os números ou códigos reais abaixo.</hint> <displayed-value>(Other)</displayed-value> <stored-value>other</stored-value> </pair> - <pair> - <displayed-value>N/A</displayed-value> - <stored-value></stored-value> - </pair> </value-pairs> </form-value-pairs> diff --git a/dspace/config/item-submission.xml b/dspace/config/item-submission.xml index c75c345490659ebd60c8fd7f1ffd156427cee3ab..99e3e100a60521767b7285915dd1f20e9294ba2e 100644 --- a/dspace/config/item-submission.xml +++ b/dspace/config/item-submission.xml @@ -87,6 +87,15 @@ <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.SelectCollectionStep</xmlui-binding> <workflow-editable>false</workflow-editable> </step> + + <!-- Uncomment this to make available the bibliographic import from external source - note ONLY for JSPUI --> + <!-- <step id="collection"> + <heading></heading> can specify heading, if you want it to appear in Progress Bar + <processing-class>org.dspace.submit.step.StartSubmissionLookupStep</processing-class> + <jspui-binding>org.dspace.app.webui.submit.step.JSPStartSubmissionLookupStep</jspui-binding> + <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.SelectCollectionStep</xmlui-binding> + <workflow-editable>false</workflow-editable> + </step> --> <!-- The "complete" step is a "special step" which is *REQUIRED* to be--> <!-- in this section! In DSpace, when a submission is completed, --> @@ -172,24 +181,22 @@ <!--Uncommment to display the SAMPLE step as your first step--> <!--<step id="sample"/>--> + + <!-- Step 1. Since DSpace 4.0, the initial questions has been disabled. Metadata are shown exactly as + required in input-forms and items are assumed to have always multiple-files attached. + If re-enable the initial questions step you should comment out this step--> + <step> + <processing-class>org.dspace.submit.step.SkipInitialQuestionsStep</processing-class> + </step> - <!--Step 1 will be to gather initial information--> + <!--Disabled by default Since DSpace 4.0: Step 1 will be to gather initial information <step> <heading>submit.progressbar.initial-questions</heading> <processing-class>org.dspace.submit.step.InitialQuestionsStep</processing-class> <jspui-binding>org.dspace.app.webui.submit.step.JSPInitialQuestionsStep</jspui-binding> <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.InitialQuestionsStep</xmlui-binding> <workflow-editable>true</workflow-editable> - </step> - - <!--If you disable the initial questions step you should insert the --> - <!--SkipInitialQuestionsStep below, to enable proper processing of --> - <!--input-forms configuration --> - <!-- - <step> - <processing-class>org.dspace.submit.step.SkipInitialQuestionsStep</processing-class> - </step> - --> + </step> --> <!--Step 2 will be to Describe the item.--> <step> @@ -204,12 +211,13 @@ <step> <heading>submit.progressbar.access</heading> <processing-class>org.dspace.submit.step.AccessStep</processing-class> + <jspui-binding>org.dspace.app.webui.submit.step.JSPAccessStep</jspui-binding> <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.AccessStep</xmlui-binding> <workflow-editable>true</workflow-editable> </step> --> - <!--Step 4 will be to Upload the item--> + <!--Step 4 will be to Upload the item --> <step> <heading>submit.progressbar.upload</heading> <processing-class>org.dspace.submit.step.UploadStep</processing-class> @@ -217,16 +225,18 @@ <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.UploadStep</xmlui-binding> <workflow-editable>true</workflow-editable> </step> + - <!-- Step 4 Upload Item with Embargo Features (not supported in JSPUI) - to enable this step, please make sure to comment-out the previous step "UploadStep" + <!-- Step 4 Upload Item with Embargo Features + to enable this step, please make sure to comment-out the previous step "UploadStep" <step> <heading>submit.progressbar.upload</heading> <processing-class>org.dspace.submit.step.UploadWithEmbargoStep</processing-class> + <jspui-binding>org.dspace.app.webui.submit.step.JSPUploadWithEmbargoStep</jspui-binding> <xmlui-binding>org.dspace.app.xmlui.aspect.submission.submit.UploadWithEmbargoStep</xmlui-binding> <workflow-editable>true</workflow-editable> </step> - --> + --> <!--Step 5 will be to Verify/Review everything --> <step> diff --git a/dspace/config/launcher.xml b/dspace/config/launcher.xml index 52d9a3c90069cc84ec165426b8f1cdd8e45271ca..6ad206398ddbe6de39826342641a7edeeb1f2c7d 100644 --- a/dspace/config/launcher.xml +++ b/dspace/config/launcher.xml @@ -120,16 +120,24 @@ </command> <command> - <name>index</name> - <description>General index command (requires extra parameters)</description> + <name>index-db-browse</name> + <description>General browse index command (requires extra parameters)</description> <step> <class>org.dspace.browse.IndexBrowse</class> </step> </command> + + <command> + <name>index-discovery</name> + <description>Update Discovery Solr Search Index</description> + <step> + <class>org.dspace.discovery.IndexClient</class> + </step> + </command> <command> - <name>index-init</name> - <description>Initialise the search and browse indexes</description> + <name>index-lucene-init</name> + <description>Initialise the Lucene search and browse indexes</description> <step passuserargs="false"> <class>org.dspace.browse.IndexBrowse</class> <argument>-f</argument> @@ -145,8 +153,8 @@ </command> <command> - <name>index-update</name> - <description>Update the search and browse indexes</description> + <name>index-lucene-update</name> + <description>Update the Lucene search and browse indexes</description> <step passuserargs="false"> <class>org.dspace.browse.IndexBrowse</class> <argument>-i</argument> @@ -199,6 +207,14 @@ </step> </command> + <command> + <name>doi-organiser</name> + <description>Run the DOI organiser</description> + <step> + <class>org.dspace.identifier.doi.DOIOrganiser</class> + </step> + </command> + <command> <name>packager</name> <description>Execute a packager</description> @@ -215,6 +231,14 @@ </step> </command> + <command> + <name>read</name> + <description>Execute a stream of 'dspace' commands from a file or pipe</description> + <step> + <class>org.dspace.app.launcher.CommandRunner</class> + </step> + </command> + <command> <name>stat-general</name> <description>Compile the general statistics</description> @@ -331,7 +355,7 @@ </step> </command> - <command> + <command> <name>setup-database</name> <description>Create the database tables</description> <step> @@ -364,10 +388,10 @@ </command> <command> - <name>update-discovery-index</name> - <description>Update Discovery Solr Search Index</description> + <name>user</name> + <description>Manipulate a normal user account</description> <step> - <class>org.dspace.discovery.IndexClient</class> + <class>org.dspace.eperson.EPerson</class> </step> </command> @@ -387,4 +411,12 @@ </step> </command> + <command> + <name>version</name> + <description>Display the version of DSpace and other troubleshooting information</description> + <step> + <class>org.dspace.app.util.Version</class> + </step> + </command> + </commands> diff --git a/dspace/config/log4j.properties b/dspace/config/log4j.properties index 01544418c2c7854f02a009ebea1b9fe6ef32ee23..9297ee4d7c807641a77ee0b1b0443c57e666582b 100644 --- a/dspace/config/log4j.properties +++ b/dspace/config/log4j.properties @@ -12,12 +12,22 @@ # write files that rotate every day or every month. # # Text surrounded by ${} symbols is replaced with the corresponding -# property from dspace.cfg. For example: +# property from dspace.cfg by Ant when DSpace is deployed. For example: # -# ${dspace.url} +# dspace.url # # would be replaced with the dspace.url property in dspace.cfg. - +# +# Additional properties expanded by Maven during the DSpace assembly +# process: +# +# loglevel.dspace (currently set to: ${loglevel.dspace}) +# Log level for all DSpace-specific code (org.dspace.*) +# Possible values (from most to least info): DEBUG, INFO, WARN, ERROR, FATAL +# +# loglevel.other (currently set to: ${loglevel.other}) +# Log level for other third-party tools/APIs used by DSpace +# Possible values (from most to least info): DEBUG, INFO, WARN, ERROR, FATAL ########################################################################### # A1 is the name of the appender for most DSpace activity. @@ -25,10 +35,10 @@ # The root category is the default setting for all non-DSpace code. # Change this from INFO to DEBUG to see extra logging created by non-DSpace # code. -log4j.rootCategory=INFO, A1 +log4j.rootCategory=${loglevel.other}, A1 # This line sets the logging level for DSpace code. Set this to DEBUG to see # extra detailed logging for DSpace code. -log4j.logger.org.dspace=INFO, A1 +log4j.logger.org.dspace=${loglevel.dspace}, A1 # Do not change this line log4j.additivity.org.dspace=false # The name of the file appender @@ -84,12 +94,25 @@ log4j.appender.A3.File=${log.dir}/cocoon.log # Set this to yyyy-MM-DD for daily log files, or yyyy-MM for monthly files log4j.appender.A3.DatePattern=yyyy-MM-dd # The number of log files to keep, or 0 to keep them all -log4j.appender.A3.MaxLogs=0 +log4j.appender.A3.MaxLogs=14 # A2 uses PatternLayout. log4j.appender.A3.layout=org.apache.log4j.PatternLayout log4j.appender.A3.layout.ConversionPattern=%d %-5p %c %x - %m%n +########################################################################### +# A4 is the name of the appender for Solr +########################################################################### +log4j.logger.org.apache.solr=ERROR, A4 +log4j.additivity.org.apache.solr=false +log4j.appender.A4=org.dspace.app.util.DailyFileAppender +log4j.appender.A4.File=${log.dir}/solr.log +log4j.appender.A4.DatePattern=yyyy-MM-dd +log4j.appender.A4.MaxLogs=14 +log4j.appender.A4.layout=org.apache.log4j.PatternLayout +log4j.appender.A4.layout.ConversionPattern=%d %-5p %c %x - %m%n + + ########################################################################### # Other settings ########################################################################### @@ -103,4 +126,4 @@ log4j.logger.org.dspace.kernel=ERROR log4j.logger.org.dspace.services=ERROR log4j.logger.org.dspace.servicemanager=ERROR log4j.logger.org.dspace.providers=ERROR -log4j.logger.org.dspace.utils=ERROR \ No newline at end of file +log4j.logger.org.dspace.utils=ERROR diff --git a/dspace/config/modules/authentication-ldap.cfg b/dspace/config/modules/authentication-ldap.cfg index b31cb067c488c904196b0c0273200bddbd82f566..749a11625caea45b23d20a62067ad5850ea0cf53 100644 --- a/dspace/config/modules/authentication-ldap.cfg +++ b/dspace/config/modules/authentication-ldap.cfg @@ -47,8 +47,9 @@ enable = false autoregister = true -# This is the url to the institution's ldap server. The /o=myu.edu -# may or may not be required depending on the LDAP server setup. +# This is the url to the institution's ldap server. The "o=myu.edu" +# part may or may not be required depending on the LDAP server setup, +# but make sure to include the slash after domain name. # A server may also require the ldaps:// protocol. #provider_url = ldap://ldap.myu.edu/o=myu.edu @@ -145,3 +146,24 @@ autoregister = true # netid_email_domain as '@example.com' would set the email of the user # to be 'user@example.com #netid_email_domain = @example.com + +# Take the left part of the groupmap value (before the ":") and look it up +# in user's full DN. If it's found, assign user to the DSpace group +# specified by the right part of the groupmap value (after the ":"). +# One user may belong to multiple groups. +#login.groupmap.1 = ou=ldap-dept1:dspace-group1 +#login.groupmap.2 = ou=ldap-dept2:dspave-groupA +#login.groupmap.3 = ou=ldap-dept3:dspave-groupA + +# If this property is uncommented, it changes the meaning of the left part of +# the groupmap value (before the ":") as follows. +# The value of login.groupmap.attribute specifies the name of an LDAP attribute. +# If user has this attribute, look up the value of this attribute in the left +# part of the groupmap value (before the ":"). If it's found, assign user to +# the DSpace group specified by the right part of the groupmap value (after +# the ":"). +#login.groupmap.attribute = group +#login.groupmap.1 = ldap-dept1:dspace-group1 +#login.groupmap.2 = ldap-dept2:dspave-groupA +#login.groupmap.3 = ldap-dept3:dspave-groupA + diff --git a/dspace/config/modules/oai.cfg b/dspace/config/modules/oai.cfg index d9b2fd1475bbc841edeb5b03ae423470b92e460f..f5cf967a5abfdd49756e364ce58257aeebd1207b 100644 --- a/dspace/config/modules/oai.cfg +++ b/dspace/config/modules/oai.cfg @@ -35,9 +35,9 @@ cache.dir = ${dspace.dir}/var/oai ### Harvester settings -# Crosswalk settings; the {name} value must correspond to a declated ingestion crosswalk +# Crosswalk settings; the {name} value must correspond to a declared ingestion crosswalk # harvester.oai.metadataformats.{name} = {namespace},{optional display name} -# The display name is only used in the xmlui for the jspui there are entries in the +# The display name is only used in the xmlui; for the jspui there are entries in the # Messages.properties in the form jsp.tools.edit-collection.form.label21.select.{name} harvester.oai.metadataformats.dc = http://www.openarchives.org/OAI/2.0/oai_dc/, Simple Dublin Core harvester.oai.metadataformats.qdc = http://purl.org/dc/terms/, Qualified Dublin Core @@ -53,17 +53,17 @@ harvester.oai.metadataformats.dim = http://www.dspace.org/xmlns/dspace/dim, DSpa # default: false harvester.autoStart=false -# Amount of time subtracted from the from argument of the PMH request to account +# Amount of time subtracted from the "from" argument of the OAI-PMH request to account # for the time taken to negotiate a connection. Measured in seconds. Default value is 120. #harvester.timePadding = 120 # How frequently the harvest scheduler checks the remote provider for updates, -# messured in minutes. The default vaule is 12 hours (or 720 minutes) +# measured in minutes. The default vaule is 12 hours (or 720 minutes) #harvester.harvestFrequency = 720 # The heartbeat is the frequency at which the harvest scheduler queries the local # database to determine if any collections are due for a harvest cycle (based on -# the harvestFrequency) value. The scheduler is optimized to then sleep until the +# the harvestFrequency) value. The scheduler is optimized to sleep after the check until the # next collection is actually ready to be harvested. The minHeartbeat and # maxHeartbeat are the lower and upper bounds on this timeframe. Measured in seconds. # Default minHeartbeat is 30. Default maxHeartbeat is 3600. diff --git a/dspace/config/modules/sword-server.cfg b/dspace/config/modules/sword-server.cfg index 95722b45395edd7c3b70017a1b977387d731bac3..2ac350062ac3557369908564289d760f533873ed 100644 --- a/dspace/config/modules/sword-server.cfg +++ b/dspace/config/modules/sword-server.cfg @@ -151,7 +151,7 @@ keep-original-package = true # In the event of package ingest failure, provide an option to store # the package on the file system. The default is false. # keep-package-on-fail=false -# failed-package.dir=${dspace.baseUrl}/upload +# failed-package.dir=${dspace.dir}/upload # Should the server identify the sword version in deposit response? # diff --git a/dspace/config/modules/swordv2-server.cfg b/dspace/config/modules/swordv2-server.cfg index bbc7bd5b6bfea25cb1315ec97c0136f1cead2e9c..6f9de311fcdacd7912e67f812bea4d5e50fc8933 100644 --- a/dspace/config/modules/swordv2-server.cfg +++ b/dspace/config/modules/swordv2-server.cfg @@ -56,7 +56,7 @@ accept-packaging.item.SimpleZip = http://purl.org/net/sword/package/SimpleZip accept-packaging.item.Binary = http://purl.org/net/sword/package/Binary # A comma separated list of MIME types that SWORD will accept -accepts = application/zip, image/jpeg +accepts = */* # Collection Specific settings: these will be used on the collections # with the given handles @@ -91,7 +91,12 @@ max-upload-size = 0 # and will accelerate the rate at which the repository consumes disk # space. BUT, it will also mean that the deposited packages are # recoverable in their original form. It is strongly recommended, -# therefore, to leave this option turned on +# therefore, to leave this option turned on. +# +# NOTE: this affects all incoming deposits, whether they are package +# deposits or not. That is, if individual files are uploaded to the +# Media Resource, a copy of that file will be stored in the SWORD +# bundle AND into the ORIGINAL bundle. # keep-original-package = true @@ -101,18 +106,69 @@ keep-original-package = true # # bundle.name = SWORD +# The bundle name that SWORD should use to store deleted bitstreams +# if versions.keep is set to true. This will be used in the case +# that individual files are updated or removed via SWORD. If +# the entire Media Resource (files in the ORIGINAL bundle) is removed +# this will be backed up in its entirity in a bundle of its own +# +# bundle.deleted = DELETED + # In the event of package ingest failure, provide an option to store # the package on the file system. The default is false. #keep-package-on-fail=false -#failed-package.dir=http://localhost:8080/upload +#failed-package.dir=${dspace.dir}/upload # Should we support mediated deposit via sword? Enabled, this will # allow users to deposit content packages on behalf of other users. # +# WARNING: enabling mediated deposit is not intrinsically secure, +# it places a trust relationship between the authenticating user +# and the On-Behalf-Of user account within DSpace. For example, +# ANY authenticated user may make changes to an existing item +# which belongs to the On-Behalf-Of user, which represents a significant +# security risk. It is therefore recommended to either disable +# mediated deposit, or to expressly set a list of accounts which +# are allowed to mediate on behalf of other users (see on-behalf-of.update.mediators) +# # See the SWORD specification for a detailed explanation of deposit # On-Behalf-Of another user # on-behalf-of.enable = true +# +# Which user accounts are allowed to do updates on items which already +# exist in DSpace, on-behalf-of other users? +# +# If this is left blank, or omitted, then all accounts can mediate +# updates to items, which could be a security risk, as there is no +# implicit checking that the authenticated user is a "legitimate" +# mediator +# +# FIXME: this would be best maintained in the database with a nice UI +# ... so if you feel the urge to build one please don't hesitate! +# +#on-behalf-of.update.mediators = user1@myu.edu, user2@myu.edu + +# Should the deposit receipt include a verbose description of the deposit? +# +verbose-description.receipt.enable = false + +# should the error document include a verbose description of the error +# +verbose-description.error.enable = true + +# The error document can contain an alternate url, which the client +# can use to follow up any issues. +# +# This is the Contact-Us page on the XMLUI (localise the url space +# first) +# +error.alternate.url = http://localhost:8080/xmlui/contact + +# The URL may have an associated content type; if you know what it +# is, you can enter it here +# +error.alternate.content-type = text/html # The URL which identifies the sword software which provides # the sword interface. This is the URL which DSpace will use @@ -138,7 +194,7 @@ auth-type = Basic # The location where uploaded files and packages are # stored while being processed -upload.tempdir = ${dspace.dir}/upload +upload.tempdir = ${upload.temp.dir} # The metadata field in which to store the updated date for # items deposited via SWORD. @@ -157,7 +213,8 @@ author.field = dc.contributor.author title.field = dc.title # Supported packaging formats for the dissemination of packages -disseminate-packaging.METSDSpaceSIP = http://purl.org/net/sword/package/METSDSpaceSIP +# FIXME: this format is not supported ... +#disseminate-packaging.METSDSpaceSIP = http://purl.org/net/sword/package/METSDSpaceSIP disseminate-packaging.SimpleZip = http://purl.org/net/sword/package/SimpleZip # Configure the plugins to process incoming packages. The form of this @@ -179,10 +236,11 @@ disseminate-packaging.SimpleZip = http://purl.org/net/sword/package/SimpleZip # plugin.named.org.dspace.sword2.SwordContentIngester = \ org.dspace.sword2.SimpleZipContentIngester = http://purl.org/net/sword/package/SimpleZip, \ - org.dspace.sword2.SwordMETSIngester = http://purl.org/net/sword/package/METSDSpaceSIP, \ - org.dspace.sword2.BinaryContentIngester = http://purl.org/net/sword/package/Binary, \ - org.dspace.swordpackagers.SwordDocXIngester = application/vnd.openxmlformats-officedocument.wordprocessingml.document, \ - org.dspace.swordpackagers.SwordXifIngester = image/jpeg + org.dspace.sword2.SwordMETSContentIngester = http://purl.org/net/sword/package/METSDSpaceSIP, \ + org.dspace.sword2.BinaryContentIngester = http://purl.org/net/sword/package/Binary +#, \ +# org.dspace.swordpackagers.SwordDocXIngester = application/vnd.openxmlformats-officedocument.wordprocessingml.document, \ +# org.dspace.swordpackagers.SwordXifIngester = image/jpeg plugin.single.org.dspace.sword2.SwordEntryIngester = \ org.dspace.sword2.SimpleDCEntryIngester @@ -203,9 +261,46 @@ plugin.named.org.dspace.sword2.SwordStatementDisseminator = \ org.dspace.sword2.AtomStatementDisseminator = application/atom+xml_type_feed, \ org.dspace.sword2.OreStatementDisseminator = application/rdf+xml +# Which bundles should the Statement include in its list of aggregated resources +# +# The Statement will automatically mark any bitstreams which are in the bundle +# identified by the ${bundle.name} property, provided that bundle is also +# listed here (i.e. if you want Original Deposits to be listed in the Statement +# then you should add the SWORD bundle to this list) +# +statement.bundles = ORIGINAL, SWORD, LICENSE + +# Workflow manager implementation - tells us what we are allowed to do +# via the SWORDv2 interface +# +# There are two default workflow managers: +# - org.dspace.sword2.WorkflowManagerDefault: Only items in submission +# are allowed to be UPDATED or DELETED using SWORD. +# - org.dspace.sword2.WorkflowManagerUnrestricted: Items in workflow, +# in archive, or withdrawn can also be UPDATED or DELETED using +# SWORD plugin.single.org.dspace.sword2.WorkflowManager = \ org.dspace.sword2.WorkflowManagerDefault +# Should the WorkflowManagerDefault allow updates to the item's metadata +# to take place on items which are in states other than the workspace +# (e.g. in the workflow, archive, or withdrawn) ? +# +workflowmanagerdefault.always-update-metadata = true + +# Should the server allow PUT to individual files? +# +# If this is enabled, then DSpace may be used with the DepositMO SWORD +# extensions, BUT the caveat is that DSpace does not formally support +# Bitstream replace, so this is equivalent to a DELETE and then a POST, +# which violates the RESTfulness of the server. The resulting file +# DOES NOT have the same identifier as the file it was replacing. As such +# it is STRONGLY RECOMMENDED to leave this option turned off unless working +# explicitly with DepositMO enabled client environments +# +workflowmanagerdefault.file-replace.enable = false + + # tell the SWORD METS implementation which package ingester to use # to install deposited content. This should refer to one of the # classes configured for: @@ -227,7 +322,7 @@ plugin.single.org.dspace.sword2.WorkflowManager = \ # restored to activity. restore-mode.enable = false -# metadata field mapping for SimpleDCEntryIngester +# metadata field mapping for SimpleDCEntryIngester, SimpleDCEntryDisseminator and FeedContentDisseminator, # simpledc.abstract = dc.description.abstract simpledc.accessRights = dc.rights @@ -245,7 +340,7 @@ simpledc.created = dc.date.created simpledc.creator = dc.contributor.author simpledc.date = dc.date simpledc.dateAccepted = dc.date.accepted -simpledc.dateCopyrighted = dc.date.??? +# simpledc.dateCopyrighted = dc.date.??? simpledc.dateSubmitted = dc.date.submitted simpledc.description = dc.description #simpledc.educationLevel = dc.??? @@ -285,6 +380,50 @@ simpledc.title = dc.title simpledc.type = dc.type #simpledc.valid = dc.???? +atom.author = dc.contributor.author +atom.published = dc.date.created +atom.rights = dc.rights +atom.summary = dc.description.abstract +atom.title = dc.title +atom.updated = dc.date.created + +# Used by SimpleDCEntryIngester: +# +# Which metadata fields can be replaced during a PUT to the Item of an +# Atom Entry document? Fields listed here are the ones which will be +# removed when a new PUT comes through (irrespective of whether there +# is a new incoming value to replace them) +# +metadata.replaceable = dc.description.abstract, \ + dc.rights, \ + dc.title.alternative, \ + dc.identifier.citation, \ + dc.contributor, \ + dc.coverage, \ + dc.contributor.author, \ + dc.date, \ + dc.description, \ + dc.format.extent, \ + dc.format, dc.identifier, \ + dc.relation.ispartof, \ + dc.relation.isreferencedby, \ + dc.relation.isreplacedby, \ + dc.relation.isrequiredby, \ + dc.language, \ + dc.format.medium, \ + dc.date.modified, \ + dc.publisher, \ + dc.relation.references, \ + dc.relation, \ + dc.relation.replaces, \ + dc.relation.requires, \ + dc.source, \ + dc.coverage.spatial, \ + dc.subject, \ + dc.coverage.temporal, \ + dc.title, \ + dc.type + # order of precedence for importing multipart content. if entry-first then # metadata in the package will override metadata in the entry, otherwise @@ -306,11 +445,22 @@ workflow.notify = true # versions.keep = true -state.workspace.uri = http://localhost:8080/xmlui/state/inprogress +state.workspace.uri = http://dspace.org/state/inprogress state.workspace.description = The item is in the user workspace -state.workflow.uri = http://localhost:8080/xmlui/state/inreview +state.workflow.uri = http://dspace.org/state/inreview state.workflow.description = The item is undergoing review prior to acceptance to the archive -state.archive.uri = http://localhost:8080/xmlui/state/archived +state.archive.uri = http://dspace.org/state/archived state.archive.description = The item has been archived -state.withdrawn.uri = http://localhost:8080/xmlui/state/withdrawn -state.withdrawn.description = The item has been withdrawn from the item and is no longer available +state.withdrawn.uri = http://dspace.org/state/withdrawn +state.withdrawn.description = The item has been withdrawn from the archive and is no longer available + +# URL template for items in the workspace (items in the archive will use +# the handle) +# +# JSPUI +# workspace.url-template = http://localhost:8080/jspui/view-workspaceitem?submit_view=Yes&workspace_id=#wsid# + +# XMLUI +workspace.url-template = http://localhost:8080/xmlui/submit?workspaceID=#wsid# + + diff --git a/dspace/config/modules/usage-statistics.cfg b/dspace/config/modules/usage-statistics.cfg index 4ac4220e00f63704cafcfc8732b7a08988242d6c..c6d7c746f6217cc7c6849ed1181a3a2803e297f9 100644 --- a/dspace/config/modules/usage-statistics.cfg +++ b/dspace/config/modules/usage-statistics.cfg @@ -14,7 +14,7 @@ resolver.timeout = 200 # If disabled, anyone with READ permissions on the DSpaceObject will be able # to view the statistics. #View/download statistics -authorization.admin.usage=true +authorization.admin.usage=false #Search/search result statistics authorization.admin.search=true #Workflow result statistics diff --git a/dspace/config/modules/versioning.cfg b/dspace/config/modules/versioning.cfg index 2c51ac2d9ea8351de29817be321890d9bc726c96..f7105452d2aec8d43e2a42195f10e8f500b4598a 100644 --- a/dspace/config/modules/versioning.cfg +++ b/dspace/config/modules/versioning.cfg @@ -3,7 +3,8 @@ #---------------------------------------------------# # These configs are used by the versioning system # #---------------------------------------------------# - +#Parameter 'enabled' is used only by JSPUI +enabled=false # Control if the history overview of an item should only be shown to administrators # If enabled only the administrators for the item will be able to view the versioning history # If disabled anyone with READ permissions on the item will be able to view the versioning history diff --git a/dspace/config/news-xmlui.xml b/dspace/config/news-xmlui.xml index 5921d3d4146ca0f246d35b5bcc30c578f9bf73df..cfd73d6636154ff5a0ea66f799b9bc3325b69001 100644 --- a/dspace/config/news-xmlui.xml +++ b/dspace/config/news-xmlui.xml @@ -2,6 +2,7 @@ <document xmlns="http://di.tamu.edu/DRI/1.0/" xmlns:i18n="http://apache.org/cocoon/i18n/2.1" version="1.1"> <body> +<!-- <div id="file.news.div.news" n="news" rend="primary"> <head> <i18n:text>participatorio.repo.title</i18n:text> @@ -26,6 +27,7 @@ <i18n:text>participatorio.repo.textObjetivo</i18n:text> </p> </div> +--> </body> <options /> <meta> diff --git a/dspace/config/spring/api/bte.xml b/dspace/config/spring/api/bte.xml index dc714f83f510e8cd2eaf2e11d89ca6bf190cc089..68a5d7c77a1f9d71771115e407a967949d538912 100644 --- a/dspace/config/spring/api/bte.xml +++ b/dspace/config/spring/api/bte.xml @@ -5,173 +5,576 @@ <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> + http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> - <bean id="org.dspace.app.itemimport.DataLoaderService" class="org.dspace.app.itemimport.DataLoaderService"> + <!-- **************************************************************************************************** --> + <!-- BTE Batch import Service --> + <!-- **************************************************************************************************** --> + + <bean id="org.dspace.app.itemimport.BTEBatchImportService" class="org.dspace.app.itemimport.BTEBatchImportService"> <property name="dataLoaders"> <map> - <entry> - <key><value>bibtex</value></key> - <ref bean="gr.ekt.transformationengine.dataloaders.dspace.BibTexDataLoader"/> - </entry> - <entry> - <key><value>csv</value></key> - <ref bean="gr.ekt.transformationengine.dataloaders.dspace.CSVDataLoader"/> - </entry> - <entry> - <key><value>tsv</value></key> - <ref bean="gr.ekt.transformationengine.dataloaders.dspace.TSVDataLoader"/> - </entry> - <entry> - <key><value>endnote</value></key> - <ref bean="gr.ekt.transformationengine.dataloaders.dspace.EndnoteDataLoader"/> - </entry> - <entry> - <key><value>ris</value></key> - <ref bean="gr.ekt.transformationengine.dataloaders.dspace.RISDataLoader"/> - </entry> + <!-- Specify here any data loaders that you want to have access to in the command line batch import. + Key is the name that you need to specify in the "-i" option in the command line script when "-b" + option is used (which means BTE Batch import) --> + <entry key="pubmedXML" value-ref="pubmedFileDataLoader" /> + <entry key="crossrefXML" value-ref="crossRefFileDataLoader" /> + <entry key="arxivXML" value-ref="arXivFileDataLoader" /> + <entry key="ciniiXML" value-ref="ciniiFileDataLoader" /> + <entry key="bibtex" value-ref="bibTeXDataLoader" /> + <entry key="ris" value-ref="risDataLoader" /> + <entry key="endnote" value-ref="endnoteDataLoader" /> + <entry key="csv" value-ref="csvDataLoader" /> + <entry key="tsv" value-ref="tsvDataLoader" /> + <entry key="oai" value-ref="oaipmhDataLoader" /> </map> </property> + + <!-- The map that will be used to map internal BTE keys to DSpace metadata fields --> + <property name="outputMap" ref="outputMap" /> + + <property name="transformationEngine" ref="batchImportTransformationEngine" /> + </bean> + + <!-- **************************************************************************************************** --> + <!-- BTE Batch import Transformation Engine --> + <!-- **************************************************************************************************** --> + + <bean id="batchImportTransformationEngine" class="gr.ekt.bte.core.TransformationEngine"> + <property name="workflow" ref="batchImportLinearWorkflow" /> </bean> - <bean id="gr.ekt.transformationengine.core.TransformationEngine" class="gr.ekt.transformationengine.core.TransformationEngine"> - <property name="workflow" ref="conjunctionTransformationWorkflow"/> - <property name="outputGenerator" ref="outputGenerator" /> + <!-- Specify here any filters or modifiers to run before the output --> + <bean id="batchImportLinearWorkflow" class="gr.ekt.bte.core.LinearWorkflow"> + <property name="process"> + <list> + <!-- Add here filters and modifiers --> + </list> + </property> </bean> - <bean id="gr.ekt.transformationengine.dataloaders.dspace.BibTexDataLoader" - class="gr.ekt.transformationengine.dataloaders.dspace.BibTexDataLoader"/> + <!-- **************************************************************************************************** --> + <!-- Submission Lookup Service --> + <!-- **************************************************************************************************** --> + + <bean class="org.dspace.submit.lookup.SubmissionLookupService" + name="org.dspace.submit.lookup.SubmissionLookupService"> + <property name="phase1TransformationEngine" ref="phase1TransformationEngine" /> + <property name="phase2TransformationEngine" ref="phase2TransformationEngine" /> + <!-- Uncomment the following property if you want specific fields to appear in the detail presentation + of a publication. Default values are the ones shown below --> + <!-- + <property name="detailFields"> + <list> + <value>title</value> + <value>authors</value> + <value>editors</value> + <value>translators</value> + <value>chairs</value> + <value>issued</value> + <value>abstract</value> + <value>doi</value> + <value>journal</value> + <value>volume</value> + <value>issue</value> + <value>publisher</value> + <value>jissn</value> + <value>jeissn</value> + <value>pisbn</value> + <value>eisbn</value> + <value>arxivCategory</value> + <value>keywords</value> + <value>mesh</value> + <value>language</value> + <value>subtype</value> + <value>translators</value> + </list> + </property> + --> + </bean> - <bean id="gr.ekt.transformationengine.dataloaders.dspace.CSVDataLoader" - class="gr.ekt.transformationengine.dataloaders.dspace.CSVDataLoader"/> + <!-- **************************************************************************************************** --> + <!-- Submission Lookup Transformation Engine (phase 1) --> + <!-- **************************************************************************************************** --> - <bean id="gr.ekt.transformationengine.dataloaders.dspace.EndnoteDataLoader" - class="gr.ekt.transformationengine.dataloaders.dspace.EndnoteDataLoader"/> + <bean name="phase1TransformationEngine" class="gr.ekt.bte.core.TransformationEngine"> + <property name="dataLoader" ref="multipleDataLoader"/> + <property name="workflow" ref="phase1LinearWorkflow"/> + <property name="outputGenerator" ref="org.dspace.submit.lookup.SubmissionLookupOutputGenerator"/> + </bean> - <bean id="gr.ekt.transformationengine.dataloaders.dspace.RISDataLoader" - class="gr.ekt.transformationengine.dataloaders.dspace.RISDataLoader"/> + <bean name="multipleDataLoader" class="org.dspace.submit.lookup.MultipleSubmissionLookupDataLoader"> + <property name="dataloadersMap"> + <map> + <!-- Specify here any data loaders you want to include in the submission lookup process. + Dataloades must either extend the "NetworkSubmissionLookupDataLoader" abstract class + or conform to "FileDataLoader" interface of BTE --> + <entry key="pubmed" value-ref="pubmedOnlineDataLoader"/> + <entry key="crossref" value-ref="crossRefOnlineDataLoader"/> + <entry key="arxiv" value-ref="arXivOnlineDataLoader"/> + <entry key="cinii" value-ref="ciniiOnlineDataLoader"/> + <entry key="pubmedXML" value-ref="pubmedFileDataLoader"/> + <entry key="crossRefXML" value-ref="crossRefFileDataLoader"/> + <entry key="arXivXML" value-ref="arXivFileDataLoader"/> + <entry key="ciniiXML" value-ref="ciniiFileDataLoader"/> + <entry key="bibtex" value-ref="bibTeXDataLoader"/> + <entry key="ris" value-ref="risDataLoader"/> + <entry key="endnote" value-ref="endnoteDataLoader"/> + <entry key="csv" value-ref="csvDataLoader"/> + <entry key="tsv" value-ref="tsvDataLoader"/> + </map> + </property> + </bean> - <bean id="gr.ekt.transformationengine.dataloaders.dspace.TSVDataLoader" - class="gr.ekt.transformationengine.dataloaders.dspace.TSVDataLoader"/> + <bean name="org.dspace.submit.lookup.SubmissionLookupOutputGenerator" class="org.dspace.submit.lookup.SubmissionLookupOutputGenerator"/> + + <!-- Specify here any filters or modifiers to run before the output --> + <bean name="phase1LinearWorkflow" class="gr.ekt.bte.core.LinearWorkflow"> + <property name="process"> + <list> + <ref bean="mapConverter_arxivSubject"/> + <ref bean="mapConverter_pubstatusPubmed"/> + <ref bean="removeLastDot"/> + </list> + </property> + </bean> + + <!-- Converts an input value to an output one --> + <bean name="mapConverter_arxivSubject" class="org.dspace.submit.lookup.MapConverterModifier" init-method="init"> + <constructor-arg value="mapConverter_arxivSubject Modifier"/> + <property name="converterNameFile" value="mapConverter-arxivSubject.properties"/> + <property name="configurationService" ref="org.dspace.services.ConfigurationService"/> + <property name="fieldKeys"> + <list> + <!-- Specify the internal BTE keys that this modifiers needs to be applied --> + <value>arxivCategory</value> + </list> + </property> + </bean> + + <!-- Converts an input value to an output one --> + <bean name="mapConverter_pubstatusPubmed" class="org.dspace.submit.lookup.MapConverterModifier" init-method="init"> + <constructor-arg value="mapConverter_pubstatusPubmed Modifier"/> + <property name="converterNameFile" value="mapConverter-pubstatusPubmed.properties"/> + <property name="configurationService" ref="org.dspace.services.ConfigurationService"/> + <property name="defaultValue" value="Subjected to Journal"/> + <property name="fieldKeys"> + <list> + <!-- Specify the internal BTE keys that this modifiers needs to be applied --> + <value>publicationStatus</value> + </list> + </property> + </bean> + + <!-- Remove the last dot in the specified field keys --> + <bean name="removeLastDot" class="org.dspace.submit.lookup.RemoveLastDotModifier"> + <constructor-arg value="removeLastDot Modifier"/> + <property name="fieldKeys"> + <list> + <value>title</value> + </list> + </property> + </bean> + + <!-- **************************************************************************************************** --> + <!-- Submission Lookup Transformation Engine (phase 2) --> + <!-- **************************************************************************************************** --> + + <bean name="phase2TransformationEngine" class="gr.ekt.bte.core.TransformationEngine"> + <property name="dataLoader" ref="submissionItemDataLoader"/> + <property name="workflow" ref="phase2linearWorkflow"/> + <property name="outputGenerator" ref="org.dspace.submit.lookup.DSpaceWorkspaceItemOutputGenerator"/> + </bean> + + <bean name="submissionItemDataLoader" class="org.dspace.submit.lookup.SubmissionItemDataLoader"/> + + <!-- Specify here any filters or modifiers to run before the output --> + <bean name="phase2linearWorkflow" class="gr.ekt.bte.core.LinearWorkflow"> + <property name="process"> + <list> + <ref bean="fieldMergeModifier"/> + <ref bean="valueConcatenationModifier"/> + <ref bean="languageCodeModifier"/> + </list> + </property> + </bean> + + <bean name="fieldMergeModifier" class="org.dspace.submit.lookup.FieldMergeModifier"> + <property name="mergeFieldMap"> + <map> + <entry key="allauthors"> + <list> + <value>authors</value> + </list> + </entry> + <entry key="allkeywords"> + <list> + <value>keywords</value> + <value>mesh</value> + </list> + </entry> + </map> + </property> + </bean> + + <bean name="valueConcatenationModifier" class="org.dspace.submit.lookup.ValueConcatenationModifier"> + <property name="field" value="allkeywords"/> + <property name="separator" value=";" /> + <property name="whitespaceAfter" value="true" /> + </bean> + <bean name="languageCodeModifier" class="org.dspace.submit.lookup.LanguageCodeModifier"/> - <bean id="conjunctionTransformationWorkflow" - class="gr.ekt.transformationengine.core.ConjunctionTransformationWorkflow"> - <property name="steps"> + <bean name="org.dspace.submit.lookup.DSpaceWorkspaceItemOutputGenerator" class="org.dspace.submit.lookup.DSpaceWorkspaceItemOutputGenerator"> + <property name="outputMap" ref="outputMap"/> + + <property name="extraMetadataToKeep"> <list> + <value>dc.import.contributorauthor</value> + <value>dc.import.contributoreditor</value> + <value>dc.import.contributortranslator</value> + <!-- <value>dc.description.scopusurl</value> + <value>dc.description.scopuscitationcount</value> + <value>dc.description.scopuscitationurl</value>--> </list> + </property> + </bean> + + <!-- **************************************************************************************************** --> + <!-- DataLoader beans --> + <!-- **************************************************************************************************** --> + <!-- Each dataloader needs a mapping that defines how the input maps to + records. Internally every record organizes the data as key-list of values + pairs, and in order to be able to recall the values the keys should have + distinct names. Each data format has a way to address individual data, and + this is the key of the map. The value is the label that the record internally + associates with the specific data and is used in the output mapping as well. --> + + <!-- The key of the map is just the BibTeX label (e.g. author, date, pages + etc). The value the label that the record internally associates with the + specific data. --> + <bean id="bibTeXDataLoader" class="gr.ekt.bteio.loaders.BibTeXDataLoader"> + <property name="fieldMap"> + <map> + <entry key="title" value="title" /> + <entry key="author" value="authors" /> + <entry key="journal" value="journal" /> + <entry key="year" value="issued" /> + <entry key="ISSN" value="jissn" /> + </map> </property> </bean> - <bean id="dcMap" class="java.util.HashMap"> - <constructor-arg> + <!-- Each entry in a CSV is a row, and each column represents the same data + in each entry. For example the first column might record the item title, + the second the authors etc. The key of the field map is this number. Note + that the first column is number 0. The CSV data loader has these extra parameters + that configure its behaviour: - skipLines: a number that instructs the reader + to ignore the first lines in the input file. Default value: 0 - separator: + a character that signifies how the values are separated. Default value ',' + -quoteChar: individual valued could include the separator character. For + example if the separator is ',' and there is an abstract, there is a high + probability that it will contain commas. If the value is quoted using the + quoteChar then separator characters inside it will be ignored. Default value + '"'. -valueSeparator: There are cases where a value is the concatenation + of multiple values. For instance a list of authors. In this case the CSVDataLoader + can split the CSV value into its individual values, if they are separated + with valueSeparator. This can be a full java regular expression. Default + value: null (the csv value is not used by default). --> + <bean id="csvDataLoader" class="gr.ekt.bteio.loaders.CSVDataLoader"> + <property name="fieldMap"> <map> - <entry> - <key> - <value>Title</value> - </key> - <ref bean="titleDSpaceMetadata" /> - </entry> - <entry> - <key> - <value>Type</value> - </key> - <ref bean="typeDSpaceMetadata" /> - </entry> - <entry> - <key> - <value>Author</value> - </key> - <ref bean="authorDSpaceMetadata" /> - </entry> - <entry> - <key> - <value>Journal</value> - </key> - <ref bean="sourceDSpaceMetadata" /> - </entry> - <entry> - <key> - <value>Year</value> - </key> - <ref bean="dateDSpaceMetadata" /> - </entry> - <entry> - <key> - <value>ISSN</value> - </key> - <ref bean="issnDSpaceMetadata" /> - </entry> + <entry key="0" value="title" /> + <entry key="1" value="authors" /> + <entry key="2" value="issued" /> + <entry key="3" value="journal" /> + <entry key="4" value="abstract" /> + <entry key="5" value="jissn" /> + <entry key="6" value="subtype" /> </map> - </constructor-arg> + </property> + <property name="skipLines" value="1" /> </bean> - <bean id="ektMap" class="java.util.HashMap"> - <constructor-arg> + <!-- A TSV file is exactly the same as a CSV one, with the difference that + the separator is a tab instead of a comma. See the comments in the previous + section. --> + <bean id="tsvDataLoader" class="gr.ekt.bteio.loaders.CSVDataLoader"> + <property name="fieldMap"> <map> - <entry> - <key> - <value>Title</value> - </key> - <ref bean="titleDSpaceMetadata" /> - </entry> - <entry> - <key> - <value>Type</value> - </key> - <ref bean="typeDSpaceMetadata" /> - </entry> + <entry key="0" value="title" /> + <entry key="1" value="authors" /> + <entry key="2" value="issued" /> + <entry key="3" value="journal" /> + <entry key="4" value="abstract" /> + <entry key="5" value="jissn" /> + <entry key="6" value="subtype" /> </map> - </constructor-arg> + </property> + <!-- This makes the CSV data loader able to load TSV data --> + <property name="separator" value="\u0009" /> + <property name="skipLines" value="1" /> + </bean> + + <!-- The map for the RIS data loader has to have as keys the RIS tags that + need to be loaded. --> + <bean id="risDataLoader" class="gr.ekt.bteio.loaders.RISDataLoader"> + <property name="fieldMap"> + <map> + <entry key="T1" value="title" /> + <entry key="AU" value="authors" /> + <entry key="SO" value="journal" /> + <entry key="PY" value="issued" /> + <entry key="SN" value="jissn" /> + <entry key="PT" value="subtype" /> + <entry key="AB" value="abstract" /> + </map> + </property> + </bean> + + <bean id="endnoteDataLoader" class="gr.ekt.bteio.loaders.EndnoteDataLoader"> + <property name="fieldMap"> + <map> + <entry key="TI" value="title" /> + <entry key="AU" value="authors" /> + <entry key="AB" value="abstract" /> + <entry key="PY" value="issued" /> + <entry key="SO" value="journal" /> + </map> + </property> </bean> - <bean id="outputGenerator" - class="gr.ekt.transformationengine.outputGenerators.DSpaceOutputGenerator"> - <property name="mappings"> + <!-- OAI Data Loader --> + <bean id="oaipmhDataLoader" class="gr.ekt.bteio.loaders.OAIPMHDataLoader"> + <property name="fieldMap"> <map> - <entry> - <key> - <value>dc</value> - </key> - <ref bean="dcMap" /> - </entry> - <entry> - <key> - <value>ekt</value> - </key> - <ref bean="ektMap" /> - </entry> + <entry key="title" value="title" /> + <entry key="creator" value="authors" /> + <entry key="description" value="abstract" /> + <entry key="date" value="issued" /> + <entry key="type" value="subtype" /> </map> </property> + <property name="prefix" value="oai_dc" /> + <property name="serverAddress" + value="http://ebooks.serrelib.gr/serrelib-oai/request" /> + </bean> + + <!-- PubMed --> + <bean id="pubmedOnlineDataLoader" class="org.dspace.submit.lookup.PubmedOnlineDataLoader"> + <property name="searchProvider" value="false" /> + <property name="fieldMap" ref="pubmedInputMap" /> + </bean> + + <bean id="pubmedFileDataLoader" class="org.dspace.submit.lookup.PubmedFileDataLoader"> + <property name="fieldMap" ref="pubmedInputMap" /> + </bean> + + <bean name="pubmedInputMap" class="java.util.HashMap" scope="prototype"> + <constructor-arg> + <map key-type="java.lang.String" value-type="java.lang.String"> + <entry key="pubmedID" value="pubmedID" /> + <entry key="doi" value="doi" /> + <entry key="printISSN" value="jissn" /> + <entry key="electronicISSN" value="jeissn" /> + <entry key="journalTitle" value="journal" /> + <entry key="articleTitle" value="title" /> + <entry key="pubDate" value="issued" /> + <entry key="journalVolume" value="volume" /> + <entry key="journalIssue" value="issue" /> + <entry key="language" value="language" /> + <entry key="publicationType" value="subtype" /> + <entry key="primaryKeyword" value="keywords" /> + <entry key="secondaryKeyword" value="keywords" /> + <entry key="primaryMeshHeading" value="mesh" /> + <entry key="secondaryMeshHeading" value="mesh" /> + <entry key="startPage" value="firstpage" /> + <entry key="endPage" value="lastpage" /> + <entry key="abstractText" value="abstract" /> + <entry key="publicationStatus" value="publicationStatus" /> + <entry key="author" value="authors" /> + <!-- Not used --> + <!-- + <entry key="pubblicationModel" value="" /> + --> + </map> + </constructor-arg> + </bean> + + <!-- Arxiv Data Loaders --> + <bean id="arXivOnlineDataLoader" class="org.dspace.submit.lookup.ArXivOnlineDataLoader"> + <property name="searchProvider" value="false" /> + <property name="fieldMap" ref="arxivInputMap" /> </bean> - <bean id="titleDSpaceMetadata" class="gr.ekt.transformationengine.dspace.DSpaceMetadata"> - <property name="schema" value="dc" /> - <property name="element" value="title" /> + + <bean id="arXivFileDataLoader" class="org.dspace.submit.lookup.ArXivFileDataLoader"> + <property name="fieldMap" ref="arxivInputMap" /> </bean> - <bean id="typeDSpaceMetadata" class="gr.ekt.transformationengine.dspace.DSpaceMetadata"> - <property name="schema" value="dc" /> - <property name="element" value="type" /> + + <bean name="arxivInputMap" class="java.util.HashMap" scope="prototype"> + <constructor-arg> + <map key-type="java.lang.String" value-type="java.lang.String"> + <entry key="journalRef" value="journal" /> + <entry key="doi" value="doi" /> + <entry key="author" value="authors" /> + <entry key="authorWithAffiliation" value="authorsWithAffiliation" /> + <entry key="comment" value="note" /> + <entry key="published" value="issued" /> + <entry key="articleTitle" value="title" /> + <entry key="summary" value="abstract" /> + <entry key="id" value="url" /> + <entry key="pdfUrl" value="fulltextUrl" /> + <entry key="primaryCategory" value="arxivCategory" /> + <entry key="category" value="arxivCategory" /> + </map> + </constructor-arg> </bean> - <bean id="authorDSpaceMetadata" class="gr.ekt.transformationengine.dspace.DSpaceMetadata"> - <property name="schema" value="dc" /> - <property name="element" value="contributor" /> - <property name="qualifier" value="author" /> + + <!-- CrossRef Data Loaders --> + <bean id="crossRefOnlineDataLoader" class="org.dspace.submit.lookup.CrossRefOnlineDataLoader"> + <property name="searchProvider" value="false" /> + <!-- For CrossRef service you need to obtain an API Key from CrossRef. Once you get it, add it + to the following configuration value + --> + <property name="apiKey" value="" /> + <!-- Uncomment the following line if you want to define the max results returned by the + CrossRef free text (by author, title, date) search. Default value is 10 + --> + <!-- <property name="maxResults" value="10" /> --> + <property name="fieldMap" ref="crossrefInputMap" /> + </bean> + + <bean id="crossRefFileDataLoader" class="org.dspace.submit.lookup.CrossRefFileDataLoader"> + <property name="fieldMap" ref="crossrefInputMap" /> + </bean> + + <bean name="crossrefInputMap" class="java.util.HashMap" scope="prototype"> + <constructor-arg> + <map key-type="java.lang.String" value-type="java.lang.String"> + <entry key="journalTitle" value="journal" /> + <entry key="doi" value="doi" /> + <entry key="authors" value="authors" /> + <entry key="printISSN" value="jissn" /> + <entry key="electronicISSN" value="jeissn" /> + <entry key="year" value="issued" /> + <entry key="articleTitle" value="title" /> + <entry key="volume" value="volume" /> + <entry key="issue" value="issue" /> + <entry key="firstPage" value="firstpage" /> + <entry key="lastPage" value="lastpage" /> + <entry key="printISBN" value="pisbn" /> + <entry key="electronicISBN" value="eisbn" /> + <entry key="editionNumber" value="editionnumber" /> + <entry key="seriesTitle" value="seriestitle" /> + <entry key="volumeTitle" value="volumetitle" /> + <entry key="editors" value="editors" /> + <entry key="translators" value="translators" /> + <entry key="chairs" value="chairs" /> + <entry key="doyType" value="subtype" /> + <!-- Not used --> + <!-- + <entry key="publicationType" value="" /> + --> + </map> + </constructor-arg> </bean> - <bean id="abstractDSpaceMetadata" class="gr.ekt.transformationengine.dspace.DSpaceMetadata"> - <property name="schema" value="dc" /> - <property name="element" value="description" /> - <property name="qualifier" value="abstract" /> + + <!-- CiNii --> + <bean id="ciniiOnlineDataLoader" class="org.dspace.submit.lookup.CiNiiOnlineDataLoader"> + <property name="searchProvider" value="false" /> + <!-- For CiNii service you need to obtain an Application ID from NII. + Once you get it, add it to the following configuration value. + For details, see http://ci.nii.ac.jp/info/en/api/developer.html + --> + <property name="appId" value="" /> + <!-- Uncomment the following line if you want to define the max results + returned by the CiNii free text (by author, title, date) search. + Default value is 10 + --> + <!-- <property name="maxResults" value="10" /> --> + <property name="fieldMap" ref="ciniiInputMap" /> </bean> - <bean id="sourceDSpaceMetadata" class="gr.ekt.transformationengine.dspace.DSpaceMetadata"> - <property name="schema" value="dc" /> - <property name="element" value="source" /> + + <bean id="ciniiFileDataLoader" class="org.dspace.submit.lookup.CiNiiFileDataLoader"> + <property name="fieldMap" ref="ciniiInputMap" /> </bean> - <bean id="dateDSpaceMetadata" class="gr.ekt.transformationengine.dspace.DSpaceMetadata"> - <property name="schema" value="dc" /> - <property name="element" value="date" /> + + <bean name="ciniiInputMap" class="java.util.HashMap" scope="prototype"> + <constructor-arg> + <map key-type="java.lang.String" value-type="java.lang.String"> + <entry key="naid" value="naid" /> + <entry key="ncid" value="ncid" /> + <entry key="issn" value="jissn" /> + <entry key="journal" value="journal" /> + <entry key="title" value="title" /> + <entry key="issued" value="issued" /> + <entry key="volume" value="volume" /> + <entry key="issue" value="issue" /> + <entry key="spage" value="firstpage" /> + <entry key="epage" value="lastpage" /> + <entry key="language" value="language" /> + <entry key="description" value="abstract" /> + <entry key="subjects" value="keywords" /> + <entry key="authors" value="authors" /> + <entry key="publisher" value="publisher" /> + </map> + </constructor-arg> </bean> - <bean id="issnDSpaceMetadata" class="gr.ekt.transformationengine.dspace.DSpaceMetadata"> - <property name="schema" value="dc" /> - <property name="element" value="identifier" /> + + <!-- **************************************************************************************************** --> + <!-- Output Mapping --> + <!-- **************************************************************************************************** --> + + <!-- The output generator needs a configuration on how to map internal records + to the DSpace metadata fields. The following map specifies this relationship. + The value needs to be the label that the record internally associates with + the specific data and it is specified in the data loader beans. The key is + in the format of <schema>.<element>[.<qualifier>] and specified the dspace + metadata field that the value will map to. --> + <bean name="outputMap" class="java.util.HashMap" scope="prototype"> + <constructor-arg> + <map key-type="java.lang.String" value-type="java.lang.String"> + <entry value="jissn" key="dc.identifier.issn" /> + <entry value="pisbn" key="dc.identifier.isbn" /> + <entry value="journal" key="dc.source" /> + <entry value="title" key="dc.title" /> + <entry value="issued" key="dc.date.issued" /> + <entry value="language" key="dc.language.iso" /> + <entry value="subtype" key="dc.type" /> + <entry value="authors" key="dc.contributor.author" /> + <entry value="editors" key="dc.contributor.editor" /> + <entry value="translators" key="dc.contributor.other" /> + <entry value="chairs" key="dc.contributor.other" /> + <entry value="abstract" key="dc.description.abstract" /> + <entry value="allkeywords" key="dc.subject" /> + <entry value="arxivCategory" key="dc.subject" /> + <entry value="doi" key="dc.identifier" /> + <entry value="publisher" key="dc.publisher" /> + <!-- Not used - new metadata fields need to be declared for them in DSpace registry --> + <!-- + <entry value="url" key="" /> + <entry value="note" key="" /> + <entry value="fulltextUrl" key="" /> + <entry value="authorsWithAffiliation" key="" /> + <entry value="pubmedID" key="" /> + <entry value="publicationStatus" key="" /> + <entry value="jeissn" key="" /> + <entry value="volume" key="" /> + <entry value="issue" key="" /> + <entry value="firstpage" key="" /> + <entry value="lastpage" key="" /> + <entry value="eisbn" key="" /> + <entry value="editionnumber" key="" /> + <entry value="seriestitle" key="" /> + <entry value="volumetitle" key="" /> + <entry value="titleAlternative" key="" /> + <entry value="authorAlternative" key="" /> + <entry value="ncid" key="" /> + <entry value="naid" key="" /> + --> + + </map> + </constructor-arg> </bean> -</beans> \ No newline at end of file + +</beans> diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index 28e1275f27796f728b23c590aab725cfe4a29800..7dbdf5939f8bf7ac18b2d01437ba0471ff754588 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -23,6 +23,7 @@ <context:annotation-config /> <!-- allows us to use spring annotations in beans --> <bean id="solrServiceResourceIndexPlugin" class="org.dspace.discovery.SolrServiceResourceRestrictionPlugin" scope="prototype"/> + <bean id="SolrServiceSpellIndexingPlugin" class="org.dspace.discovery.SolrServiceSpellIndexingPlugin" scope="prototype"/> <alias name="solrServiceResourceIndexPlugin" alias="org.dspace.discovery.SolrServiceResourceRestrictionPlugin"/> @@ -43,7 +44,7 @@ <entry key="default" value-ref="defaultConfiguration" /> <!--Use site to override the default configuration for the home page & default discovery page--> - <!--<entry key="site" value-ref="defaultConfiguration" />--> + <entry key="site" value-ref="homepageConfiguration" /> <!--<entry key="123456789/7621" value-ref="defaultConfiguration"/>--> </map> </property> @@ -134,15 +135,17 @@ <bean class="org.dspace.discovery.configuration.DiscoveryRecentSubmissionsConfiguration"> <property name="metadataSortField" value="dc.date.accessioned" /> <property name="type" value="date"/> - <property name="max" value="5"/> + <property name="max" value="20"/> + <!-- If enabled the collection home page will not display metadata but show a pageable list of recent submissions --> + <property name="useAsHomePage" value="false"/> </bean> </property> <!--Default result per page --> <property name="defaultRpp" value="10" /> <property name="hitHighlightingConfiguration"> <bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration"> - <property name="metadataFields"> - <list> + <property name="metadataFields"> + <list> <bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration"> <property name="field" value="dc.title"/> <property name="snippets" value="5"/> @@ -161,33 +164,106 @@ <property name="maxSize" value="250"/> <property name="snippets" value="2"/> </bean> - </list> - </property> - </bean> + </list> + </property> + </bean> </property> <property name="moreLikeThisConfiguration"> <bean class="org.dspace.discovery.configuration.DiscoveryMoreLikeThisConfiguration"> <!--When altering this list also alter the "xmlui.Discovery.RelatedItems.help" key as it describes the metadata fields below--> <property name="similarityMetadataFields"> - <list> + <list> <value>dc.title</value> - <value>dc.contributor.author</value> - <value>dc.creator</value> + <value>dc.contributor.author</value> + <value>dc.creator</value> <value>dc.subject</value> - </list> - </property> + </list> + </property> <!--The minimum number of matching terms across the metadata fields above before an item is found as related --> <property name="minTermFrequency" value="5"/> <!--The maximum number of related items displayed--> <property name="max" value="3"/> <!--The minimum word length below which words will be ignored--> <property name="minWordLength" value="5"/> - </bean> + </bean> </property> + <!-- When true a "did you mean" example will be displayed, value can be true or false --> + <property name="spellCheckEnabled" value="true"/> </bean> + <!--The Homepage specific configuration settings for discovery--> + <bean id="homepageConfiguration" class="org.dspace.discovery.configuration.DiscoveryConfiguration" scope="prototype"> + <!--Which sidebar facets are to be displayed (same as defaultConfiguration above)--> + <property name="sidebarFacets"> + <list> + <ref bean="searchFilterAuthor" /> + <ref bean="searchFilterSubject" /> + <ref bean="searchFilterIssued" /> + </list> + </property> + <!--The search filters which can be used on the discovery search page (same as defaultConfiguration above)--> + <property name="searchFilters"> + <list> + <ref bean="searchFilterTitle" /> + <ref bean="searchFilterAuthor" /> + <ref bean="searchFilterSubject" /> + <ref bean="searchFilterIssued" /> + </list> + </property> + <!--The sort filters for the discovery search (same as defaultConfiguration above)--> + <property name="searchSortConfiguration"> + <bean class="org.dspace.discovery.configuration.DiscoverySortConfiguration"> + <!--<property name="defaultSort" ref="sortDateIssued"/>--> + <!--DefaultSortOrder can either be desc or asc (desc is default)--> + <property name="defaultSortOrder" value="desc"/> + <property name="sortFields"> + <list> + <ref bean="sortTitle" /> + <ref bean="sortDateIssued" /> + </list> + </property> + </bean> + </property> + <!-- Limit recent submissions on homepage to only 5 (default is 20) --> + <property name="recentSubmissionConfiguration"> + <bean class="org.dspace.discovery.configuration.DiscoveryRecentSubmissionsConfiguration"> + <property name="metadataSortField" value="dc.date.accessioned" /> + <property name="type" value="date"/> + <property name="max" value="5"/> + <property name="useAsHomePage" value="false"/> + </bean> + </property> + <property name="hitHighlightingConfiguration"> + <bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightingConfiguration"> + <property name="metadataFields"> + <list> + <bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration"> + <property name="field" value="dc.title"/> + <property name="snippets" value="5"/> + </bean> + <bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration"> + <property name="field" value="dc.contributor.author"/> + <property name="snippets" value="5"/> + </bean> + <bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration"> + <property name="field" value="dc.description.abstract"/> + <property name="maxSize" value="250"/> + <property name="snippets" value="2"/> + </bean> + <bean class="org.dspace.discovery.configuration.DiscoveryHitHighlightFieldConfiguration"> + <property name="field" value="fulltext"/> + <property name="maxSize" value="250"/> + <property name="snippets" value="2"/> + </bean> + </list> + </property> + </bean> + </property> + <!-- When true a "did you mean" example will be displayed, value can be true or false --> + <property name="spellCheckEnabled" value="true"/> + </bean> <!--Search filter configuration beans--> <bean id="searchFilterTitle" class="org.dspace.discovery.configuration.DiscoverySearchFilter"> @@ -244,4 +320,4 @@ <property name="type" value="date"/> </bean> -</beans> \ No newline at end of file +</beans> diff --git a/dspace/config/spring/api/identifier-service.xml b/dspace/config/spring/api/identifier-service.xml index 3e8f7b8d771745fdc098cc6c10292e6eca7b5619..734ea63072eeaeb562a43757d45baec9af9a1bc2 100644 --- a/dspace/config/spring/api/identifier-service.xml +++ b/dspace/config/spring/api/identifier-service.xml @@ -21,11 +21,82 @@ autowire="byType" scope="singleton"/> - <!-- provider for using the versioned handle identifier instead of the default one. --> <!--<bean id="org.dspace.identifier.HandleIdentifierProvider" class="org.dspace.identifier.VersionedHandleIdentifierProvider"--> <!--scope="singleton">--> <!--<property name="configurationService" ref="org.dspace.services.ConfigurationService"/>--> <!--</bean>--> + <!-- provider to mint and register DOIs with DSpace. + To mint DOIs you need a registration agency. The DOIIdentifierProvider + maintains the doi database table and handling of DSpaceObject. It uses + a DOIConnector that handle all API calls to your DOI registration + agency. Please configure a DOIConnector as well!--> + + <!-- To mint DOIs with DSpace get an agreement with a DOI registration + agency, take a look into dspace.cfg, and remove this comment + <bean id="org.dspace.identifier.DOIIdentifierProvider" + class="org.dspace.identifier.DOIIdentifierProvider" + scope="singleton"> + <property name="configurationService" + ref="org.dspace.services.ConfigurationService" /> + <property name="DOIConnector" + ref="org.dspace.identifier.doi.DOIConnector" /> + </bean> + --> + + <!-- The DOIConnector will handle the API calls to your DOI registration + agency for the DOIIdentifierProvider. If your registration agency + tells you to use DataCites API directly you can use the + DataCiteConnector. If your registration agency is not part of DataCite + or provides their own API you have to implement a DOIConnector. + EZID f.e. is part of DataCite but provides their own APIs. The following + DataCiteConnector won't work if EZID is your registration agency. + --> + <!-- Remove this comment to use DataCite API directly as DOIConnector. + <bean id="org.dspace.identifier.doi.DOIConnector" + class="org.dspace.identifier.doi.DataCiteConnector" + scope="singleton"> + <property name='DATACITE_SCHEME' value='https'/> + <property name='DATACITE_HOST' value='test.datacite.org'/> + <property name='DATACITE_DOI_PATH' value='/mds/doi/' /> + <property name='DATACITE_METADATA_PATH' value='/mds/metadata/' /> + <property name='disseminationCrosswalkName' value="DataCite" /> + </bean> + --> + + <!-- Provider to mint and register DOIs using EZID as the registrar. + --> + <!-- Uncomment to enable DOI using EZID + <bean id="org.dspace.identifier.EZIDIdentifierProvider" + class="org.dspace.identifier.EZIDIdentifierProvider" + scope='singleton'> + <description>Uses the EZID service to provide DOI identifiers from DataCite</description> + <property name="configurationService" + ref="org.dspace.services.ConfigurationService"/> + <property name='requestFactory'> + <bean class='org.dspace.identifier.ezid.EZIDRequestFactory'> + <property name='EZID_SCHEME' value='https'/> + <property name='EZID_HOST' value='n2t.net'/> + </bean> + </property> + <property name='crosswalk'> + <map> + <entry key='datacite.creator' value='dc.contributor.author'/> + <entry key='datacite.title' value='dc.title'/> + <entry key='datacite.publisher' value='dc.publisher'/> + <entry key='datacite.publicationyear' value='dc.date.issued'/> + </map> + </property> + <property name='crosswalkTransform'> + <description>How to compute the crosswalked value from the original. Default is plain copy.</description> + <map> + <entry key='datacite.publicationyear'> + <bean class='org.dspace.identifier.ezid.DateToYear'/> + </entry> + </map> + </property> + </bean> + --> + </beans> diff --git a/dspace/config/xmlui.xconf b/dspace/config/xmlui.xconf index 4a94aaecd568dd78498ee9a0e90cf575d664401b..9c2ec5295a462e32ac94c24e3ccdf91ae10a3753 100644 --- a/dspace/config/xmlui.xconf +++ b/dspace/config/xmlui.xconf @@ -82,7 +82,7 @@ <!-- Base DSpace XMLUI Aspects for Display, Browse, Search, Admin, Login and Submission --> <aspect name="Displaying Artifacts" path="resource://aspects/ViewArtifacts/" /> <aspect name="Browsing Artifacts" path="resource://aspects/BrowseArtifacts/" /> -<!-- <aspect name="Searching Artifacts" path="resource://aspects/SearchArtifacts/" /> --> <!--usando Discovery --> + <aspect name="Discovery" path="resource://aspects/Discovery/" /> <aspect name="Administration" path="resource://aspects/Administrative/" /> <aspect name="E-Person" path="resource://aspects/EPerson/" /> <aspect name="Submission and Workflow" path="resource://aspects/Submission/" /> @@ -115,14 +115,21 @@ <!-- ============== Search Engines ============== --> - <!-- By default, DSpace uses a basic (Lucene based) search engine (see SearchArtifacts aspect above) --> <!-- - To enable Discovery (faceted/filtered search), uncomment this aspect. - Also make sure to comment out the above 'SearchArtifacts' aspect + To enable the old lucene based search (no facets, filters), uncomment this aspect. + Also make sure to comment out the above 'Discovery' aspect (in the "Basic Features/Aspects" group) as leaving it on together - with Discovery will cause UI overlap issues + with Searching Artifacts aspect will cause UI overlap issues + + @deprecated Since DSpace 4 the system use an abstraction layer named + Discovery to provide access to different search provider. The + legacy system build upon Apache Lucene is likely to be removed in + a future version. If you are interested in use Lucene as backend + for the DSpace search system please consider to build a Lucene + implementation of the Discovery interfaces --> - <aspect name="Discovery" path="resource://aspects/Discovery/" /> + <!--<aspect name="Searching Artifacts" path="resource://aspects/SearchArtifacts/" />--> + <!-- ============== SWORDv1 Client @@ -166,16 +173,17 @@ their respective items. --> <themes> + <!-- <theme name="Participatorio-mobile" regex=".*" path="Participatorio-mobile/" /> --> + <theme name="Participatorio-desktop" regex=".*" path="Participatorio-desktop/" /> + <!-- <theme name="Participatorio" regex=".*" path="Participatorio/" /> --> + <!-- Example configuration --> <!-- <theme name="Test Theme 1" handle="123456789/1" path="theme1/"/> --> <!-- <theme name="Test Theme 2" regex="community-list" path="theme2/"/> --> - <theme name="mobile" regex=".*" path="mobile/"/> - - <!-- Mirage theme, @mire contributed theme, default since DSpace 3.0 --> -<!-- <theme name="Atmire Mirage Theme" regex=".*" path="Mirage/" /> --> + <!-- <theme name="Atmire Mirage Theme" regex=".*" path="Mirage/" /> --> <!-- Reference theme, the default Manakin XMLUI layout up to DSpace 1.8 --> <!-- <theme name="Default Reference Theme" regex=".*" path="Reference/" /> --> diff --git a/dspace/docs/DSpace-Manual.pdf b/dspace/docs/DSpace-Manual.pdf deleted file mode 100644 index 2a59a8f519c02ba743e7eb76d48db878a51cc7b7..0000000000000000000000000000000000000000 Binary files a/dspace/docs/DSpace-Manual.pdf and /dev/null differ diff --git a/dspace/etc/clean-database.sql b/dspace/etc/clean-database.sql index 5c211bc2c10b9d836c3e6e8b7a148424eec7a65d..9d0c4939f51672b75de486fd4db6defb39a1e5c2 100644 --- a/dspace/etc/clean-database.sql +++ b/dspace/etc/clean-database.sql @@ -64,6 +64,7 @@ DROP TABLE TasklistItem; DROP TABLE WorkflowItem; DROP TABLE WorkspaceItem; DROP TABLE Handle; +DROP TABLE Doi; DROP TABLE EPersonGroup2EPerson; DROP TABLE ResourcePolicy; DROP TABLE Collection2Item; @@ -114,6 +115,7 @@ DROP SEQUENCE collection2item_seq; DROP SEQUENCE resourcepolicy_seq; DROP SEQUENCE epersongroup2eperson_seq; DROP SEQUENCE handle_seq; +DROP SEQUENCE doi_seq; DROP SEQUENCE workspaceitem_seq; DROP SEQUENCE workflowitem_seq; DROP SEQUENCE tasklistitem_seq; @@ -132,4 +134,4 @@ DROP SEQUENCE versionhistory_seq; DROP SEQUENCE versionitem_seq; -- Drop the getnextid() function -DROP FUNCTION getnextid(VARCHAR(40)); +DROP FUNCTION getnextid; diff --git a/dspace/etc/h2/database_schema.sql b/dspace/etc/h2/database_schema.sql index 5d54f9cdc8612ce7da581050adca23b6404a643f..a09fde37b275e1664e8589d345f6142cfe51cebc 100644 --- a/dspace/etc/h2/database_schema.sql +++ b/dspace/etc/h2/database_schema.sql @@ -102,6 +102,7 @@ CREATE SEQUENCE collection2item_seq; CREATE SEQUENCE resourcepolicy_seq; CREATE SEQUENCE epersongroup2eperson_seq; CREATE SEQUENCE handle_seq; +CREATE SEQUENCE doi_seq; CREATE SEQUENCE workspaceitem_seq; CREATE SEQUENCE workflowitem_seq; CREATE SEQUENCE tasklistitem_seq; @@ -116,6 +117,7 @@ CREATE SEQUENCE group2group_seq; CREATE SEQUENCE group2groupcache_seq; CREATE SEQUENCE harvested_collection_seq; CREATE SEQUENCE harvested_item_seq; +CREATE SEQUENCE webapp_seq; ------------------------------------------------------- -- BitstreamFormatRegistry table @@ -491,6 +493,23 @@ CREATE INDEX handle_handle_idx ON Handle(handle); -- index by resource id and resource type id CREATE INDEX handle_resource_id_and_type_idx ON handle(resource_id, resource_type_id); +------------------------------------------------------- +-- Doi table +------------------------------------------------------- +CREATE TABLE Doi +( + doi_id INTEGER PRIMARY KEY, + doi VARCHAR(256), + resource_type_id INTEGER, + resource_id INTEGER, + status INTEGER +); + +-- index by handle, commonly looked up +CREATE INDEX doi_doi_idx ON Doi(doi); +-- index by resource id and resource type id +CREATE INDEX doi_resource_id_and_type_idx ON Doi(resource_id, resource_type_id); + ------------------------------------------------------- -- WorkspaceItem table ------------------------------------------------------- @@ -807,8 +826,11 @@ CREATE TABLE versionitem CREATE SEQUENCE versionitem_seq; CREATE SEQUENCE versionhistory_seq; - - - - - +CREATE TABLE Webapp +( + webapp_id INTEGER NOT NULL PRIMARY KEY, + AppName VARCHAR(32), + URL VARCHAR, + Started TIMESTAMP, + isUI INTEGER +); diff --git a/dspace/etc/oracle/ORACLE_README.txt b/dspace/etc/oracle/ORACLE_README.txt index 93be5aaceb972151fc54782e726678e58459858e..a9434fa0df13468b999e582c89da5dc61e69a25f 100644 --- a/dspace/etc/oracle/ORACLE_README.txt +++ b/dspace/etc/oracle/ORACLE_README.txt @@ -18,7 +18,7 @@ browse code - LIMIT and OFFSET is used to limit browse results, and an Oracle-hack is used to limit the result set to a given size Oracle has no boolean data type, so a new schema file was created that -uses INTEGERs and code is inserted everywhere to use 0 for false +uses NUMBER(1) (AKA 'integers') and code is inserted everywhere to use 0 for false and 1 for true if the db.name is Oracle Oracle doesn't have a TEXT data type either, so TEXT columns are defined diff --git a/dspace/etc/oracle/database_schema.sql b/dspace/etc/oracle/database_schema.sql index 0915e98b2a2ca909efac1fb3622ff6f6330f83ee..16239f014cd24ad810969cf2502921230ea2c1c9 100644 --- a/dspace/etc/oracle/database_schema.sql +++ b/dspace/etc/oracle/database_schema.sql @@ -55,6 +55,7 @@ CREATE SEQUENCE collection2item_seq; CREATE SEQUENCE resourcepolicy_seq; CREATE SEQUENCE epersongroup2eperson_seq; CREATE SEQUENCE handle_seq; +CREATE SEQUENCE doi_seq; CREATE SEQUENCE workspaceitem_seq; CREATE SEQUENCE workflowitem_seq; CREATE SEQUENCE tasklistitem_seq; @@ -72,6 +73,8 @@ CREATE SEQUENCE harvested_collection_seq; CREATE SEQUENCE harvested_item_seq; CREATE SEQUENCE versionitem_seq; CREATE SEQUENCE versionhistory_seq; +CREATE SEQUENCE webapp_seq; +CREATE SEQUENCE requestitem_seq; ------------------------------------------------------- -- BitstreamFormatRegistry table @@ -443,6 +446,21 @@ CREATE TABLE Handle -- index by resource id and resource type id CREATE INDEX handle_resource_id_type_idx ON handle(resource_id, resource_type_id); +------------------------------------------------------- +-- Doi table +------------------------------------------------------- +CREATE TABLE Doi +( + doi_id INTEGER PRIMARY KEY, + doi VARCHAR2(256) UNIQUE, + resource_type_id INTEGER, + resource_id INTEGER, + status INTEGER +); + +-- index by resource id and resource type id +CREATE INDEX doi_resource_id_type_idx ON doi(resource_id, resource_type_id); + ------------------------------------------------------- -- WorkspaceItem table ------------------------------------------------------- @@ -751,3 +769,30 @@ CREATE TABLE versionitem version_summary VARCHAR2(255), versionhistory_id INTEGER REFERENCES VersionHistory(versionhistory_id) ); + +CREATE TABLE Webapp +( + webapp_id INTEGER NOT NULL PRIMARY KEY, + AppName VARCHAR2(32), + URL VARCHAR2(1000), + Started TIMESTAMP, + isUI NUMBER(1) +); + +CREATE TABLE requestitem +( + requestitem_id INTEGER NOT NULL, + token varchar(48), + item_id INTEGER, + bitstream_id INTEGER, + allfiles NUMBER(1), + request_email VARCHAR2(64), + request_name VARCHAR2(64), + request_date TIMESTAMP, + accept_request NUMBER(1), + decision_date TIMESTAMP, + expires TIMESTAMP, + CONSTRAINT requestitem_pkey PRIMARY KEY (requestitem_id), + CONSTRAINT requestitem_token_key UNIQUE (token) +); + diff --git a/dspace/etc/oracle/update-sequences.sql b/dspace/etc/oracle/update-sequences.sql index e44b35a9fe08a76f8da872b9eb351b4ea731159a..9288805c24afed68f154c9cbf209286cf6a02238 100644 --- a/dspace/etc/oracle/update-sequences.sql +++ b/dspace/etc/oracle/update-sequences.sql @@ -86,6 +86,7 @@ @updateseq.sql metadataschemaregistry_seq metadataschemaregistry metadata_schema_id "" @updateseq.sql harvested_collection_seq harvested_collection id "" @updateseq.sql harvested_item_seq harvested_item id "" +@updateseq.sql webapp_seq webapp id "" -- Handle Sequence is a special case. Since Handles minted by DSpace use the 'handle_seq', -- we need to ensure the next assigned handle will *always* be unique. So, 'handle_seq' diff --git a/dspace/etc/oracle/xmlworkflow/workflow_migration.sql b/dspace/etc/oracle/xmlworkflow/workflow_migration.sql index 404c9a273199f6c8093132debd8e03a6351b62b7..8d89672f39922e27e9cb93fe1501088c10fe4502 100644 --- a/dspace/etc/oracle/xmlworkflow/workflow_migration.sql +++ b/dspace/etc/oracle/xmlworkflow/workflow_migration.sql @@ -5,28 +5,28 @@ INSERT INTO cwf_collectionrole (collectionrole_id, role_id, group_id, collection SELECT cwf_collectionrole_seq.nextval as collectionrole_id, 'reviewer' AS role_id, -eperson_group_id AS group_id, -to_number(replace(replace(name, 'COLLECTION_', ''), '_WORKFLOW_STEP_1', '')) AS collection_id -FROM epersongroup -WHERE name LIKE 'COLLECTION_%_WORKFLOW_STEP_1'; +collection.workflow_step_1 AS group_id, +collection.collection_id AS collection_id +FROM collection +WHERE collection.workflow_step_1 IS NOT NULL; INSERT INTO cwf_collectionrole (collectionrole_id, role_id, group_id, collection_id) SELECT cwf_collectionrole_seq.nextval as collectionrole_id, 'editor' AS role_id, -eperson_group_id AS group_id, -to_number(replace(replace(name, 'COLLECTION_', ''), '_WORKFLOW_STEP_2', '')) AS collection_id -FROM epersongroup -WHERE name LIKE 'COLLECTION_%_WORKFLOW_STEP_2'; +collection.workflow_step_2 AS group_id, +collection.collection_id AS collection_id +FROM collection +WHERE collection.workflow_step_2 IS NOT NULL; INSERT INTO cwf_collectionrole (collectionrole_id, role_id, group_id, collection_id) SELECT cwf_collectionrole_seq.nextval as collectionrole_id, 'finaleditor' AS role_id, -eperson_group_id AS group_id, -to_number(replace(replace(name, 'COLLECTION_', ''), '_WORKFLOW_STEP_3', '')) AS collection_id -FROM epersongroup -WHERE name LIKE 'COLLECTION_%_WORKFLOW_STEP_3'; +collection.workflow_step_3 AS group_id, +collection.collection_id AS collection_id +FROM collection +WHERE collection.workflow_step_3 IS NOT NULL; -- Migrate workflow items diff --git a/dspace/etc/postgres/database_schema.sql b/dspace/etc/postgres/database_schema.sql index d93ae9566f968b4f8e4e2f29eb9322e530687d38..2402a1a298bb15dfb90c7a47f9a404665f41755b 100644 --- a/dspace/etc/postgres/database_schema.sql +++ b/dspace/etc/postgres/database_schema.sql @@ -93,6 +93,7 @@ CREATE SEQUENCE collection2item_seq; CREATE SEQUENCE resourcepolicy_seq; CREATE SEQUENCE epersongroup2eperson_seq; CREATE SEQUENCE handle_seq; +CREATE SEQUENCE doi_seq; CREATE SEQUENCE workspaceitem_seq; CREATE SEQUENCE workflowitem_seq; CREATE SEQUENCE tasklistitem_seq; @@ -109,6 +110,8 @@ CREATE SEQUENCE harvested_collection_seq; CREATE SEQUENCE harvested_item_seq; CREATE SEQUENCE versionitem_seq; CREATE SEQUENCE versionhistory_seq; +CREATE SEQUENCE webapp_seq; +CREATE SEQUENCE requestitem_seq; ------------------------------------------------------- -- BitstreamFormatRegistry table @@ -484,6 +487,23 @@ CREATE INDEX handle_handle_idx ON Handle(handle); -- index by resource id and resource type id CREATE INDEX handle_resource_id_and_type_idx ON handle(resource_id, resource_type_id); +------------------------------------------------------- +-- Doi table +------------------------------------------------------- +CREATE TABLE Doi +( + doi_id INTEGER PRIMARY KEY, + doi VARCHAR(256) UNIQUE, + resource_type_id INTEGER, + resource_id INTEGER, + status INTEGER +); + +-- index by handle, commonly looked up +CREATE INDEX doi_doi_idx ON Doi(doi); +-- index by resource id and resource type id +CREATE INDEX doi_resource_id_and_type_idx ON Doi(resource_id, resource_type_id); + ------------------------------------------------------- -- WorkspaceItem table ------------------------------------------------------- @@ -798,9 +818,28 @@ CREATE TABLE versionitem versionhistory_id INTEGER REFERENCES VersionHistory(versionhistory_id) ); +CREATE TABLE Webapp +( + webapp_id INTEGER NOT NULL PRIMARY KEY, + AppName VARCHAR(32), + URL VARCHAR, + Started TIMESTAMP, + isUI INTEGER +); - - - - - +CREATE TABLE requestitem +( + requestitem_id int4 NOT NULL, + token varchar(48), + item_id int4, + bitstream_id int4, + allfiles bool, + request_email varchar(64), + request_name varchar(64), + request_date timestamp, + accept_request bool, + decision_date timestamp, + expires timestamp, + CONSTRAINT requestitem_pkey PRIMARY KEY (requestitem_id), + CONSTRAINT requestitem_token_key UNIQUE (token) +); diff --git a/dspace/etc/postgres/update-sequences.sql b/dspace/etc/postgres/update-sequences.sql index 59ac6428c830c631414b0d923369d359b64a2823..f1a96d564fc2a63d1080a20761d28012f0ed0f7c 100644 --- a/dspace/etc/postgres/update-sequences.sql +++ b/dspace/etc/postgres/update-sequences.sql @@ -84,6 +84,8 @@ SELECT setval('metadatavalue_seq', max(metadata_value_id)) FROM metadatavalue; SELECT setval('metadataschemaregistry_seq', max(metadata_schema_id)) FROM metadataschemaregistry; SELECT setval('harvested_collection_seq', max(id)) FROM harvested_collection; SELECT setval('harvested_item_seq', max(id)) FROM harvested_item; +SELECT setval('webapp_seq', max(webapp_id)) FROM webapp; +SELECT setval('requestitem_seq', max(requestitem_id)) FROM requestitem; -- Handle Sequence is a special case. Since Handles minted by DSpace use the 'handle_seq', -- we need to ensure the next assigned handle will *always* be unique. So, 'handle_seq' @@ -99,4 +101,4 @@ SELECT setval('handle_seq', AS BIGINT) ) FROM handle - WHERE handle SIMILAR TO '%/[0123456789]*'; \ No newline at end of file + WHERE handle SIMILAR TO '%/[0123456789]*'; diff --git a/dspace/etc/postgres/xmlworkflow/workflow_migration.sql b/dspace/etc/postgres/xmlworkflow/workflow_migration.sql index 5f11ce2a7fdb8cf0eee4a598ccb14a0f6f5cffd7..b7a908e3e67cb2673b3686d7b08e9ec9cbd9f897 100644 --- a/dspace/etc/postgres/xmlworkflow/workflow_migration.sql +++ b/dspace/etc/postgres/xmlworkflow/workflow_migration.sql @@ -2,26 +2,26 @@ INSERT INTO cwf_collectionrole (role_id, group_id, collection_id) SELECT 'reviewer' AS role_id, -eperson_group_id AS group_id, -replace(replace(name, 'COLLECTION_', ''), '_WORKFLOW_STEP_1', '')::INTEGER AS collection_id -FROM epersongroup -WHERE name LIKE 'COLLECTION_%_WORKFLOW_STEP_1'; +collection.workflow_step_1 AS group_id, +collection.collection_id AS collection_id +FROM collection +WHERE collection.workflow_step_1 IS NOT NULL; INSERT INTO cwf_collectionrole (role_id, group_id, collection_id) SELECT 'editor' AS role_id, -eperson_group_id AS group_id, -replace(replace(name, 'COLLECTION_', ''), '_WORKFLOW_STEP_2', '')::INTEGER AS collection_id -FROM epersongroup -WHERE name LIKE 'COLLECTION_%_WORKFLOW_STEP_2'; +collection.workflow_step_2 AS group_id, +collection.collection_id AS collection_id +FROM collection +WHERE collection.workflow_step_2 IS NOT NULL; INSERT INTO cwf_collectionrole (role_id, group_id, collection_id) SELECT 'finaleditor' AS role_id, -eperson_group_id AS group_id, -replace(replace(name, 'COLLECTION_', ''), '_WORKFLOW_STEP_3', '')::INTEGER AS collection_id -FROM epersongroup -WHERE name LIKE 'COLLECTION_%_WORKFLOW_STEP_3'; +collection.workflow_step_3 AS group_id, +collection.collection_id AS collection_id +FROM collection +WHERE collection.workflow_step_3 IS NOT NULL; -- Migrate workflow items diff --git a/dspace/modules/additions/pom.xml b/dspace/modules/additions/pom.xml index 772fa35bb039ea8928350d44827a570a231014e1..216401701809158ea38f1b37aafd7b7466eed00e 100644 --- a/dspace/modules/additions/pom.xml +++ b/dspace/modules/additions/pom.xml @@ -17,7 +17,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>modules</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> diff --git a/dspace/modules/jspui/pom.xml b/dspace/modules/jspui/pom.xml index ae9b8ea10dc40de6ca93f3d7b3daf50a0a7ebde9..129d13d19ed7416c02bede15e19531f7bce95c05 100644 --- a/dspace/modules/jspui/pom.xml +++ b/dspace/modules/jspui/pom.xml @@ -12,7 +12,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>modules</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> diff --git a/dspace/modules/lni/pom.xml b/dspace/modules/lni/pom.xml index d6dcecf0f810762475399805930795fde1fe3faf..565c19cf019a076ac2089942e56e5ac849cad771 100644 --- a/dspace/modules/lni/pom.xml +++ b/dspace/modules/lni/pom.xml @@ -13,7 +13,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>modules</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> diff --git a/dspace/modules/oai/pom.xml b/dspace/modules/oai/pom.xml index fedab4badf8dcdc7485d61b79f8fd81c9c3ab994..c9c0af54641f446994057ecd996aef3bc745f19e 100644 --- a/dspace/modules/oai/pom.xml +++ b/dspace/modules/oai/pom.xml @@ -12,7 +12,7 @@ <parent> <artifactId>modules</artifactId> <groupId>org.dspace</groupId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> @@ -93,17 +93,21 @@ <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> - <version>1.5.6</version> </dependency> <dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-core</artifactId> - <version>3.3.0</version> + <version>${solr.version}</version> + <exclusions> + <exclusion> + <groupId>jdk.tools</groupId> + <artifactId>jdk.tools</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-jdk14</artifactId> - <version>1.5.6</version> </dependency> </dependencies> diff --git a/dspace/modules/pom.xml b/dspace/modules/pom.xml index d7f1db761ef33dbeba8ab09c329e81fb10b07db3..166d568fe5fdcb2ff37dc829d4604b473a0c5c22 100644 --- a/dspace/modules/pom.xml +++ b/dspace/modules/pom.xml @@ -9,7 +9,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>../../pom.xml</relativePath> </parent> @@ -63,6 +63,15 @@ <module>jspui</module> </modules> </profile> + <profile> + <id>dspace-rest</id> + <activation> + <activeByDefault>true</activeByDefault> + </activation> + <modules> + <module>rest</module> + </modules> + </profile> <profile> <id>dspace-sword</id> <activation> diff --git a/dspace/modules/solr/pom.xml b/dspace/modules/solr/pom.xml index d27579789db0f89f1d2fe227e5b1ec6c698da963..2a811b02fd72af3063bf69e712f1f04f947e6f0d 100644 --- a/dspace/modules/solr/pom.xml +++ b/dspace/modules/solr/pom.xml @@ -2,7 +2,7 @@ <modelVersion>4.0.0</modelVersion> <groupId>org.dspace.modules</groupId> <artifactId>solr</artifactId> - <version>3.2</version> + <version>4.1</version> <packaging>war</packaging> <name>DSpace SOLR :: Local Customizations</name> <description> @@ -13,7 +13,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>modules</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> @@ -39,7 +39,7 @@ need to take precedence over the solr-core, the solr-core will still be loaded in the solr-core.jar --> <excludes> - <exclude>WEB-INF/lib/apache-solr-core-3.5.0.jar</exclude> + <exclude>WEB-INF/lib/apache-solr-core-4.4.0.jar</exclude> <!--Also ensure we use the DSpace solr web.xml file else our localhost filter will not work !--> <exclude>WEB-INF/web.xml</exclude> </excludes> @@ -58,7 +58,7 @@ <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-solr</artifactId> - <version>3.5.0.1</version> + <version>4.1</version> <classifier>skinny</classifier> <type>war</type> </dependency> @@ -66,11 +66,41 @@ <dependency> <groupId>org.dspace</groupId> <artifactId>dspace-solr</artifactId> - <version>3.5.0.1</version> + <version>4.1</version> <classifier>classes</classifier> <type>jar</type> </dependency> + <!-- add dependencies for support of ICU extra analyzer --> + <dependency> + <groupId>org.apache.solr</groupId> + <artifactId>solr-analysis-extras</artifactId> + <version>${lucene.version}</version> + </dependency> + + <dependency> + <groupId>com.ibm.icu</groupId> + <artifactId>icu4j</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.lucene</groupId> + <artifactId>lucene-analyzers-icu</artifactId> + <version>${lucene.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.lucene</groupId> + <artifactId>lucene-analyzers-smartcn</artifactId> + <version>${lucene.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.lucene</groupId> + <artifactId>lucene-analyzers-stempel</artifactId> + <version>${lucene.version}</version> + </dependency> + <!-- support odd cases where JAXP cannot be found in JVM --> <dependency> <groupId>xalan</groupId> diff --git a/dspace/modules/sword/pom.xml b/dspace/modules/sword/pom.xml index e75b7d07ed6a3d47f000f8ca26a2ec894bb2d39f..540ac4ec74e3a689bd2aca5095df3181042e8c2b 100644 --- a/dspace/modules/sword/pom.xml +++ b/dspace/modules/sword/pom.xml @@ -16,7 +16,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>modules</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> diff --git a/dspace/modules/swordv2/pom.xml b/dspace/modules/swordv2/pom.xml index 6f61b953dc87e9918866701e0ad90ee513f06221..ce910325a2199bb9b87e0b34b99cb2f63ef1fc89 100644 --- a/dspace/modules/swordv2/pom.xml +++ b/dspace/modules/swordv2/pom.xml @@ -16,7 +16,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>modules</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> diff --git a/dspace/modules/xmlui/pom.xml b/dspace/modules/xmlui/pom.xml index bb57620cfe5f2a777fe194b49d89b9561ec59ef3..30f6ef6605145105f6ae5a0328daa33524716e69 100644 --- a/dspace/modules/xmlui/pom.xml +++ b/dspace/modules/xmlui/pom.xml @@ -12,7 +12,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>modules</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> diff --git a/dspace/modules/xmlui/src/main/java/org/dspace/app/xmlui/aspect/eperson/EditProfile.java b/dspace/modules/xmlui/src/main/java/org/dspace/app/xmlui/aspect/eperson/EditProfile.java deleted file mode 100644 index bbf00c49fb60b893c0d84d8378946d9a1b9ff77a..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/java/org/dspace/app/xmlui/aspect/eperson/EditProfile.java +++ /dev/null @@ -1,497 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.xmlui.aspect.eperson; - -import java.io.IOException; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.Locale; -import java.util.Map; - -import org.apache.avalon.framework.parameters.Parameters; -import org.apache.cocoon.ProcessingException; -import org.apache.cocoon.environment.ObjectModelHelper; -import org.apache.cocoon.environment.Request; -import org.apache.cocoon.environment.SourceResolver; -import org.apache.log4j.Logger; -import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer; -import org.dspace.app.xmlui.wing.Message; -import org.dspace.app.xmlui.wing.WingException; -import org.dspace.app.xmlui.wing.element.Body; -import org.dspace.app.xmlui.wing.element.Button; -import org.dspace.app.xmlui.wing.element.Division; -import org.dspace.app.xmlui.wing.element.Field; -import org.dspace.app.xmlui.wing.element.List; -import org.dspace.app.xmlui.wing.element.PageMeta; -import org.dspace.app.xmlui.wing.element.Select; -import org.dspace.app.xmlui.wing.element.Text; -import org.dspace.content.Collection; -import org.dspace.core.ConfigurationManager; -import org.dspace.core.I18nUtil; -import org.dspace.core.LogManager; -import org.dspace.eperson.Group; -import org.dspace.eperson.Subscribe; -import org.xml.sax.SAXException; - -/** - * Display a form that allows the user to edit their profile. - * There are two cases in which this can be used: 1) when an - * existing user is attempting to edit their own profile, and - * 2) when a new user is registering for the first time. - * - * There are several parameters this transformer accepts: - * - * email - The email address of the user registering for the first time. - * - * registering - A boolean value to indicate whether the user is registering for the first time. - * - * retryInformation - A boolean value to indicate whether there was an error with the user's profile. - * - * retryPassword - A boolean value to indicate whether there was an error with the user's password. - * - * allowSetPassword - A boolean value to indicate whether the user is allowed to set their own password. - * - * @author Scott Phillips - */ -public class EditProfile extends AbstractDSpaceTransformer -{ - private static Logger log = Logger.getLogger(EditProfile.class); - - /** Language string used: */ - private static final Message T_title_create = - message("xmlui.EPerson.EditProfile.title_create"); - - private static final Message T_title_update = - message("xmlui.EPerson.EditProfile.title_update"); - - private static final Message T_dspace_home = - message("xmlui.general.dspace_home"); - - private static final Message T_trail_new_registration = - message("xmlui.EPerson.trail_new_registration"); - - private static final Message T_trail_update = - message("xmlui.EPerson.EditProfile.trail_update"); - - private static final Message T_head_create = - message("xmlui.EPerson.EditProfile.head_create"); - - private static final Message T_head_update = - message("xmlui.EPerson.EditProfile.head_update"); - - private static final Message T_email_address = - message("xmlui.EPerson.EditProfile.email_address"); - - private static final Message T_first_name = - message("xmlui.EPerson.EditProfile.first_name"); - - private static final Message T_error_required = - message("xmlui.EPerson.EditProfile.error_required"); - - private static final Message T_last_name = - message("xmlui.EPerson.EditProfile.last_name"); - - private static final Message T_telephone = - message("xmlui.EPerson.EditProfile.telephone"); - - private static final Message T_language = - message("xmlui.EPerson.EditProfile.Language"); - - private static final Message T_create_password_instructions = - message("xmlui.EPerson.EditProfile.create_password_instructions"); - - private static final Message T_update_password_instructions = - message("xmlui.EPerson.EditProfile.update_password_instructions"); - - private static final Message T_password = - message("xmlui.EPerson.EditProfile.password"); - - private static final Message T_error_invalid_password = - message("xmlui.EPerson.EditProfile.error_invalid_password"); - - private static final Message T_confirm_password = - message("xmlui.EPerson.EditProfile.confirm_password"); - - private static final Message T_error_unconfirmed_password = - message("xmlui.EPerson.EditProfile.error_unconfirmed_password"); - - private static final Message T_submit_update = - message("xmlui.EPerson.EditProfile.submit_update"); - - private static final Message T_submit_create = - message("xmlui.EPerson.EditProfile.submit_create"); - - private static final Message T_subscriptions = - message("xmlui.EPerson.EditProfile.subscriptions"); - - private static final Message T_subscriptions_help = - message("xmlui.EPerson.EditProfile.subscriptions_help"); - - private static final Message T_email_subscriptions = - message("xmlui.EPerson.EditProfile.email_subscriptions"); - - private static final Message T_select_collection = - message("xmlui.EPerson.EditProfile.select_collection"); - - private static final Message T_head_auth = - message("xmlui.EPerson.EditProfile.head_auth"); - - private static final Message T_head_identify = - message("xmlui.EPerson.EditProfile.head_identify"); - - private static final Message T_head_security = - message("xmlui.EPerson.EditProfile.head_security"); - - private static Locale[] supportedLocales = getSupportedLocales(); - static - { - Arrays.sort(supportedLocales, new Comparator<Locale>() { - public int compare(Locale a, Locale b) - { - return a.getDisplayName().compareTo(b.getDisplayName()); - } - }); - } - - /** The email address of the user registering for the first time.*/ - private String email; - - /** Determine if the user is registering for the first time */ - private boolean registering; - - /** Determine if the user is allowed to set their own password */ - private boolean allowSetPassword; - - /** A list of fields in error */ - private java.util.List<String> errors; - - public void setup(SourceResolver resolver, Map objectModel, String src, - Parameters parameters) throws ProcessingException, SAXException, - IOException - { - super.setup(resolver,objectModel,src,parameters); - - this.email = parameters.getParameter("email","unknown"); - this.registering = parameters.getParameterAsBoolean("registering",false); - this.allowSetPassword = parameters.getParameterAsBoolean("allowSetPassword",false); - - String errors = parameters.getParameter("errors",""); - if (errors.length() > 0) - { - this.errors = Arrays.asList(errors.split(",")); - } - else - { - this.errors = new ArrayList<String>(); - } - - // Ensure that the email variable is set. - if (eperson != null) - { - this.email = eperson.getEmail(); - } - } - - public void addPageMeta(PageMeta pageMeta) throws WingException - { - // Set the page title - if (registering) - { - pageMeta.addMetadata("title").addContent(T_title_create); - } - else - { - pageMeta.addMetadata("title").addContent(T_title_update); - } - - pageMeta.addTrailLink(contextPath + "/",T_dspace_home); - if (registering) - { - pageMeta.addTrail().addContent(T_trail_new_registration); - } - else - { - pageMeta.addTrail().addContent(T_trail_update); - } - } - - - public void addBody(Body body) throws WingException, SQLException - { - // Log that we are viewing a profile - log.info(LogManager.getHeader(context, "view_profile", "")); - - Request request = ObjectModelHelper.getRequest(objectModel); - - String defaultFirstName="",defaultLastName="",defaultPhone=""; - String defaultLanguage=null; - if (request.getParameter("submit") != null) - { - defaultFirstName = request.getParameter("first_name"); - defaultLastName = request.getParameter("last_name"); - defaultPhone = request.getParameter("phone"); - defaultLanguage = request.getParameter("language"); - } - else if (eperson != null) - { - defaultFirstName = eperson.getFirstName(); - defaultLastName = eperson.getLastName(); - defaultPhone = eperson.getMetadata("phone"); - defaultLanguage = eperson.getLanguage(); - } - - String action = contextPath; - if (registering) - { - action += "/register"; - } - else - { - action += "/profile"; - } - - - - - Division profile = body.addInteractiveDivision("information", - action,Division.METHOD_POST,"primary"); - - if (registering) - { - profile.setHead(T_head_create); - } - else - { - profile.setHead(T_head_update); - } - - // Add the progress list if we are registering a new user - if (registering) - { - EPersonUtils.registrationProgressList(profile, 2); - } - - - - - - List form = profile.addList("form",List.TYPE_FORM); - - List identity = form.addList("identity",List.TYPE_FORM); - identity.setHead(T_head_identify); - - // Email - identity.addLabel(T_email_address); - identity.addItem(email); - - // First name - Text firstName = identity.addItem().addText("first_name"); - firstName.setAutofocus("autofocus"); - firstName.setRequired(); - firstName.setLabel(T_first_name); - firstName.setValue(defaultFirstName); - if (errors.contains("first_name")) - { - firstName.addError(T_error_required); - } - if (!registering && !ConfigurationManager.getBooleanProperty("xmlui.user.editmetadata", true)) - { - firstName.setDisabled(); - } - - // Last name - Text lastName = identity.addItem().addText("last_name"); - lastName.setRequired(); - lastName.setLabel(T_last_name); - lastName.setValue(defaultLastName); - if (errors.contains("last_name")) - { - lastName.addError(T_error_required); - } - if (!registering &&!ConfigurationManager.getBooleanProperty("xmlui.user.editmetadata", true)) - { - lastName.setDisabled(); - } - - // Phone - Text phone = identity.addItem().addText("phone"); - phone.setLabel(T_telephone); - phone.setValue(defaultPhone); - if (errors.contains("phone")) - { - phone.addError(T_error_required); - } - if (!registering && !ConfigurationManager.getBooleanProperty("xmlui.user.editmetadata", true)) - { - phone.setDisabled(); - } - - // Language - Select lang = identity.addItem().addSelect("language"); - lang.setLabel(T_language); - if (supportedLocales.length > 0) - { - for (Locale lc : supportedLocales) - { - lang.addOption(lc.toString(), lc.getDisplayName()); - } - } - else - { - lang.addOption(I18nUtil.DEFAULTLOCALE.toString(), I18nUtil.DEFAULTLOCALE.getDisplayName()); - } - lang.setOptionSelected((defaultLanguage == null || defaultLanguage.equals("")) ? - I18nUtil.DEFAULTLOCALE.toString() : defaultLanguage); - if (!registering && !ConfigurationManager.getBooleanProperty("xmlui.user.editmetadata", true)) - { - lang.setDisabled(); - } - - // Subscriptions - if (!registering) - { - List subscribe = form.addList("subscriptions",List.TYPE_FORM); - subscribe.setHead(T_subscriptions); - - subscribe.addItem(T_subscriptions_help); - - Collection[] currentList = Subscribe.getSubscriptions(context, context.getCurrentUser()); - Collection[] possibleList = Collection.findAll(context); - - Select subscriptions = subscribe.addItem().addSelect("subscriptions"); - subscriptions.setLabel(T_email_subscriptions); - subscriptions.setHelp(""); - subscriptions.enableAddOperation(); - subscriptions.enableDeleteOperation(); - - subscriptions.addOption(-1,T_select_collection); - for (Collection possible : possibleList) - { - String name = possible.getMetadata("name"); - if (name.length() > 50) - { - name = name.substring(0, 47) + "..."; - } - subscriptions.addOption(possible.getID(), name); - } - - for (Collection collection: currentList) - { - subscriptions.addInstance().setOptionSelected(collection.getID()); - } - } - - - if (allowSetPassword) - { - List security = form.addList("security",List.TYPE_FORM); - security.setHead(T_head_security); - - if (registering) - { - security.addItem().addContent(T_create_password_instructions); - } - else - { - security.addItem().addContent(T_update_password_instructions); - } - - - Field password = security.addItem().addPassword("password"); - password.setLabel(T_password); - if (registering) - { - password.setRequired(); - } - if (errors.contains("password")) - { - password.addError(T_error_invalid_password); - } - - Field passwordConfirm = security.addItem().addPassword("password_confirm"); - passwordConfirm.setLabel(T_confirm_password); - if (registering) - { - passwordConfirm.setRequired(); - } - if (errors.contains("password_confirm")) - { - passwordConfirm.addError(T_error_unconfirmed_password); - } - } - - Button submit = form.addItem().addButton("submit"); - if (registering) - { - submit.setValue(T_submit_update); - } - else - { - submit.setValue(T_submit_create); - } - - profile.addHidden("eperson-continue").setValue(knot.getId()); - - - - if (!registering) - { - // Add a list of groups that this user is apart of. - Group[] memberships = Group.allMemberGroups(context, context.getCurrentUser()); - - - // Not a member of any groups then don't do anything. - if (!(memberships.length > 0)) - { - return; - } - - List list = profile.addList("memberships"); - list.setHead(T_head_auth); - for (Group group: memberships) - { - list.addItem(group.getName()); - } - } - } - - /** - * Recycle - */ - public void recycle() - { - this.email = null; - this.errors = null; - super.recycle(); - } - - /** - * get the available Locales for the User Interface as defined in dspace.cfg - * property xmlui.supported.locales - * returns an array of Locales or null - * - * @return an array of supported Locales or null - */ - private static Locale[] getSupportedLocales() - { -// ############################################################################################# - String ll = ConfigurationManager.getProperty("webui.supported.locales"); - if (ll != null) - { - return I18nUtil.parseLocales(ll); - } - else - { - Locale result[] = new Locale[1]; - result[0] = I18nUtil.DEFAULTLOCALE; - return result; - } - } -} diff --git a/dspace/modules/xmlui/src/main/java/org/dspace/app/xmlui/aspect/viewArtifacts/Navigation.java b/dspace/modules/xmlui/src/main/java/org/dspace/app/xmlui/aspect/viewArtifacts/Navigation.java deleted file mode 100644 index ac12e95ff5ba6ab8a0f3a018be02545903193d2b..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/java/org/dspace/app/xmlui/aspect/viewArtifacts/Navigation.java +++ /dev/null @@ -1,164 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.xmlui.aspect.viewArtifacts; - -import org.apache.cocoon.caching.CacheableProcessingComponent; -import org.apache.cocoon.environment.ObjectModelHelper; -import org.apache.cocoon.environment.Request; -import org.apache.cocoon.util.HashUtil; -import org.apache.excalibur.source.SourceValidity; -import org.apache.excalibur.source.impl.validity.NOPValidity; -import org.dspace.app.util.Util; -import org.dspace.app.xmlui.cocoon.AbstractDSpaceTransformer; -import org.dspace.app.xmlui.utils.HandleUtil; -import org.dspace.app.xmlui.utils.UIException; -import org.dspace.app.xmlui.wing.WingException; -import org.dspace.app.xmlui.wing.element.Options; -import org.dspace.app.xmlui.wing.element.PageMeta; -import org.dspace.authorize.AuthorizeException; -import org.dspace.content.Collection; -import org.dspace.content.Community; -import org.dspace.content.DSpaceObject; -import org.dspace.content.Item; -import org.dspace.core.ConfigurationManager; -import org.dspace.core.I18nUtil; -import org.xml.sax.SAXException; - -import java.io.IOException; -import java.io.Serializable; -import java.sql.SQLException; -import java.util.Locale; - -/** - * This transform applies the basic navigational links that should be available - * on all pages generated by DSpace. - * - * @author Scott Phillips - * @author Kevin Van de Velde (kevin at atmire dot com) - * @author Mark Diggory (markd at atmire dot com) - * @author Ben Bosman (ben at atmire dot com) - */ -public class Navigation extends AbstractDSpaceTransformer implements CacheableProcessingComponent { - - /** - * Generate the unique caching key. - * This key must be unique inside the space of this component. - */ - public Serializable getKey() { - try { - Request request = ObjectModelHelper.getRequest(objectModel); - String key = request.getScheme() + request.getServerName() + request.getServerPort() + request.getSitemapURI() + request.getQueryString(); - - DSpaceObject dso = HandleUtil.obtainHandle(objectModel); - if (dso != null) - { - key += "-" + dso.getHandle(); - } - - return HashUtil.hash(key); - } - catch (SQLException sqle) - { - // Ignore all errors and just return that the component is not cachable. - return "0"; - } - } - - /** - * Generate the cache validity object. - * - * The cache is always valid. - */ - public SourceValidity getValidity() { - return NOPValidity.SHARED_INSTANCE; - } - - public void addOptions(Options options) throws SAXException, WingException, - UIException, SQLException, IOException, AuthorizeException - { - /* Create skeleton menu structure to ensure consistent order between aspects, - * even if they are never used - */ - options.addList("browse"); - options.addList("account"); - options.addList("context"); - options.addList("administrative"); - } - - /** - * Ensure that the context path is added to the page meta. - */ - public void addPageMeta(PageMeta pageMeta) throws SAXException, - WingException, UIException, SQLException, IOException, - AuthorizeException - { - // FIXME: I don't think these should be set here, but they're needed and I'm - // not sure where else it could go. Perhaps the linkResolver? - Request request = ObjectModelHelper.getRequest(objectModel); - pageMeta.addMetadata("contextPath").addContent(contextPath); - pageMeta.addMetadata("request","queryString").addContent(request.getQueryString()); - pageMeta.addMetadata("request","scheme").addContent(request.getScheme()); - pageMeta.addMetadata("request","serverPort").addContent(request.getServerPort()); - pageMeta.addMetadata("request","serverName").addContent(request.getServerName()); - pageMeta.addMetadata("request","URI").addContent(request.getSitemapURI()); - - String dspaceVersion = Util.getSourceVersion(); - if (dspaceVersion != null) - { - pageMeta.addMetadata("dspace","version").addContent(dspaceVersion); - } - - String analyticsKey = ConfigurationManager.getProperty("xmlui.google.analytics.key"); - if (analyticsKey != null && analyticsKey.length() > 0) - { - analyticsKey = analyticsKey.trim(); - pageMeta.addMetadata("google","analytics").addContent(analyticsKey); - } - - // add metadata for OpenSearch auto-discovery links if enabled - if (ConfigurationManager.getBooleanProperty("websvc.opensearch.autolink")) - { - pageMeta.addMetadata("opensearch", "shortName").addContent( ConfigurationManager.getProperty("websvc.opensearch.shortname") ); - pageMeta.addMetadata("opensearch", "autolink").addContent( "open-search/description.xml" ); - } - - pageMeta.addMetadata("page","contactURL").addContent(contextPath + "/contact"); - pageMeta.addMetadata("page","feedbackURL").addContent(contextPath + "/feedback"); - - -// ############################################################################################# - // Add the locale meta data including language dependant labels - Locale[] locales = I18nUtil.getSupportedLocales(); - for (int i=0; i < locales.length; i++) - { - pageMeta.addMetadata("page", "supportedLocale").addContent(locales[i].toString()); - // now add the appropriate labels - pageMeta.addMetadata("supportedLocale", locales[i].toString()).addContent(locales[i].getDisplayName(locales[i])); - } - pageMeta.addMetadata("page","currentLocale").addContent(context.getCurrentLocale().toString()); -// ############################################################################################# - - - DSpaceObject dso = HandleUtil.obtainHandle(objectModel); - if (dso != null) - { - if (dso instanceof Item) - { - pageMeta.addMetadata("focus","object").addContent("hdl:"+dso.getHandle()); - this.getObjectManager().manageObject(dso); - dso = ((Item) dso).getOwningCollection(); - } - - if (dso instanceof Collection || dso instanceof Community) - { - pageMeta.addMetadata("focus","container").addContent("hdl:"+dso.getHandle()); - this.getObjectManager().manageObject(dso); - } - } - } -} diff --git a/dspace/modules/xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceLocaleAction.java b/dspace/modules/xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceLocaleAction.java deleted file mode 100644 index e9980e67990cd90bbeb59d2b3cea25e9f356a28f..0000000000000000000000000000000000000000 --- a/dspace/modules/xmlui/src/main/java/org/dspace/app/xmlui/cocoon/DSpaceLocaleAction.java +++ /dev/null @@ -1,198 +0,0 @@ -/** - * The contents of this file are subject to the license and copyright - * detailed in the LICENSE and NOTICE files at the root of the source - * tree and available online at - * - * http://www.dspace.org/license/ - */ -package org.dspace.app.xmlui.cocoon; - -import org.apache.avalon.framework.configuration.Configurable; -import org.apache.avalon.framework.configuration.Configuration; -import org.apache.avalon.framework.parameters.Parameters; - -import org.apache.cocoon.acting.ServiceableAction; -import org.apache.cocoon.environment.Redirector; -import org.apache.cocoon.environment.SourceResolver; -import org.apache.cocoon.i18n.I18nUtils; -import org.apache.cocoon.i18n.I18nUtils.LocaleValidator; - -import org.dspace.app.xmlui.utils.ContextUtil; -import org.dspace.core.ConfigurationManager; -import org.dspace.core.Context; -import org.dspace.core.I18nUtil; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; -import java.util.Map; - -/** - * This action looks at several places to determine what locale should be used for - * this request. We use cocoon's i18nUtils find local method which will look in - * several places continuing to the next step if no local is found.: - * - * 1. HTTP Request parameter 'locale' - * 2. Session attribute 'locale' - * 3. First matching cookie parameter 'locale' within each cookie sent - * 4. Sitemap parameter "locale" - * 5. Locale setting of the requesting browser or server default - * 6. Default - * 7. Blank - * 8. Fail - * - * Only those locales which are listed in xmlui.supported.locales will be identified, - * if no acceptable locales are found then the default locale will be used. - * - * @author Scott Phillips - */ -public class DSpaceLocaleAction extends ServiceableAction implements Configurable { - - - /** A validator class which tests if a local is a supported locale */ - private static DSpaceLocaleValidator localeValidator; - - /** The default locale if no acceptable locales are identified */ - private static Locale defaultLocale; - - - /** - * Configure the action. - */ - public void configure(Configuration config) - { - if (localeValidator == null) - { - localeValidator = new DSpaceLocaleValidator(); - } - - if (defaultLocale == null) - { - defaultLocale = I18nUtil.getDefaultLocale(); - } - } - - - /** - * Action which obtains the current environments locale information, and - * places it in the objectModel (and optionally in a session/cookie). - */ - public Map act(Redirector redirector, - SourceResolver resolver, - Map objectModel, - String source, - Parameters parameters) - throws Exception { - - Locale locale = I18nUtils.findLocale(objectModel, "locale-attribute", parameters, defaultLocale, false, true, false, localeValidator); - - if (locale == null) { - if (getLogger().isDebugEnabled()) { - getLogger().debug("No locale found, using default"); - } - locale = I18nUtil.getDefaultLocale(); - } - - String localeStr = locale.toString(); - if (getLogger().isDebugEnabled()) { - getLogger().debug("Found locale: " + localeStr); - } - -// ############################################################################################# -// I18nUtils.storeLocale(objectModel, -// "locale-attribute", -// localeStr, -// false, -// false, -// false, -// false); - I18nUtils.storeLocale(objectModel, - "locale-attribute", - localeStr, - false, - true, - false, - false); - Context context = ContextUtil.obtainContext(objectModel); - context.setCurrentLocale(locale); -// ############################################################################################# - - // Set up a map for sitemap parameters - Map<String, String> map = new HashMap<String, String>(); - map.put("language", locale.getLanguage()); - map.put("country", locale.getCountry()); - map.put("variant", locale.getVariant()); - map.put("locale", localeStr); - return map; - } - - - /** - * This validator class works with cocoon's i18nutils class to test if locales are valid. - * For dspace we define a locale as valid if it is listed in xmlui.supported.locales config - * parameter. - */ - public static class DSpaceLocaleValidator implements LocaleValidator { - - /** the list of supported locales that may be used. */ - private List<Locale> supportedLocales; - - /** - * Build a list supported locales to validate against upon object construction. - */ - public DSpaceLocaleValidator() - { -// ############################################################################################# - if (ConfigurationManager.getProperty("webui.supported.locales") != null) - { - supportedLocales = new ArrayList<Locale>(); - -// ############################################################################################# - String supportedLocalesConfig = ConfigurationManager.getProperty("webui.supported.locales"); - - String[] parts = supportedLocalesConfig.split(","); - - for (String part : parts) - { - Locale supportedLocale = I18nUtils.parseLocale(part.trim(), null); - if (supportedLocale != null) - { - supportedLocales.add(supportedLocale); - } - } - } - } - - - /** - * @param name name of the locale (for debugging) - * @param test locale to test - * @return true if locale satisfies validator's criteria - */ - public boolean test(String name, Locale test) - { - // If there are no configured locales the accept them all. - if (supportedLocales == null) - { - return true; - } - - // Otherwise check if they are listed - for (Locale locale : supportedLocales) - { - if (locale.equals(test)) - { - return true; - } - } - - // Fail if not found - return false; - - } - - } - - -} diff --git a/dspace/modules/xmlui/src/main/webapp/i18n/messages.xml b/dspace/modules/xmlui/src/main/webapp/i18n/messages.xml index 9810254b29a739a4f290434412345aea0d9cf9cb..e91aa7c5cd5e7c752302522212cf39495a255a6e 100644 --- a/dspace/modules/xmlui/src/main/webapp/i18n/messages.xml +++ b/dspace/modules/xmlui/src/main/webapp/i18n/messages.xml @@ -37,6 +37,8 @@ <message key="xmlui.general.untitled">Untitled</message> <message key="xmlui.general.perform">Perform</message> <message key="xmlui.general.queue">Queue</message> + <message key="xmlui.general.statistics">View statistics</message> + <message key="xmlui.general.share">Share: </message> <!-- Page not found keys @@ -212,6 +214,7 @@ <message key="xmlui.ArtifactBrowser.CommunityViewer.head_sub_collections">Collections in this community</message> <message key="xmlui.ArtifactBrowser.CommunityViewer.head_recent_submissions">Recent Submissions</message> + <message key="xmlui.ArtifactBrowser.AbstractRecentSubmissionTransformer.recent_submissions_more">View more</message> <!-- org.dspace.app.xmlui.artifactbrowser.Contact.java --> <message key="xmlui.ArtifactBrowser.Contact.title">Contact us</message> @@ -589,7 +592,7 @@ <message key="xmlui.Submission.Submissions.completed.column3">Collection</message> <message key="xmlui.Submission.Submissions.completed.limit">We've only listed 50 of your archived submissions above. </message> <message key="xmlui.Submission.Submissions.completed.displayall">Display all my archived submissions.</message> - + <!-- submission progress bar messages --> <message key="xmlui.Submission.submit.progressbar.initial-questions">Initial Questions</message> <message key="xmlui.Submission.submit.progressbar.describe">Describe</message> @@ -600,6 +603,10 @@ <message key="xmlui.Submission.submit.progressbar.CClicense">CC License</message> <message key="xmlui.Submission.submit.progressbar.license">License</message> <message key="xmlui.Submission.submit.progressbar.complete">Complete</message> + + <!-- submission form page's buttons --> + <message key="xmlui.Submission.submit.button.add">Add</message> + <message key="xmlui.Submission.submit.button.remove_selected">Remove selected</message> <!-- org.dspace.app.xmlui.Submission.submit.ResumeStep --> <message key="xmlui.Submission.submit.ResumeStep.submit_resume">Resume</message> @@ -1914,7 +1921,7 @@ <message key="xmlui.statistics.Navigation.usage.view">View Usage Statistics</message> <message key="xmlui.statistics.Navigation.search.view">View Search Statistics</message> <message key="xmlui.statistics.Navigation.workflow.view">View Workflow Statistics</message> - <message key="xmlui.statistics.trail">Statistics</message> + <message key="xmlui.statistics.trail">View item</message> <message key="xmlui.statistics.trail-search">Search Statistics</message> <message key="xmlui.statistics.trail-workflow">Workflow Statistics</message> <message key="xmlui.statistics.workflow.no-results">No workflow statistics available for the selected period.</message> @@ -1992,7 +1999,7 @@ <message key="xmlui.dri2xhtml.structural.contact-link">Contact Us</message> <message key="xmlui.dri2xhtml.structural.feedback-link">Send Feedback</message> - <message key="xmlui.dri2xhtml.structural.head-subtitle">DSpace/Manakin Repository</message> + <message key="xmlui.dri2xhtml.structural.head-subtitle">Biblioteca Digital - SNJ</message> <message key="xmlui.dri2xhtml.structural.profile">Profile: </message> <message key="xmlui.dri2xhtml.structural.logout">Logout</message> @@ -2286,10 +2293,6 @@ <!-- Participatorio --> <message key="participatorio.repo.title">Digital Library of Participatory</message> - <message key="participatorio.repo.text">The Digital Library of Participatory is part of the worldwide movement for open access to scientific-technical production. The adoption of this new management model for electronic documents provides better dissemination and access to publications on youth policies and other institutional collections related to the theme such as the National Youth Secretariat (SNJ).</message> - <message key="participatorio.repo.titleMissao">Mission</message> - <message key="participatorio.repo.textMissao">To store, preserve, promote and give wide access to the institutional production of the National Youth Secretariat - SNJ and other collections related to youth policies.</message> - <message key="participatorio.repo.titleObjetivo">Purpose</message> - <message key="participatorio.repo.textObjetivo">To gather in one place the digital institutional production of SNJ, contributing to the preservation of institutional memory and the visibility of the issue of policies for the youth.</message> + <message key="participatorio.repo.text">The Digital Library of Participatory aims to give broad access to the institutional production of the National Youth Secretariat (SNJ) and other collections related to youth public policies, gathering all in virtual environment. This library is inserted in the worldwide movement of open access to scientific and technical production. The adoption of this new management model for electronic documents is intended to enable better dissemination of publications on youth and public policy in the world.</message> </catalogue> diff --git a/dspace/modules/xmlui/src/main/webapp/i18n/messages_pt_BR.xml b/dspace/modules/xmlui/src/main/webapp/i18n/messages_pt_BR.xml index b8465f27b9ec2c6f0ed31c548b701cbeb50a8916..c994c3f872e8250a99835a044f1c83b4540fbb93 100644 --- a/dspace/modules/xmlui/src/main/webapp/i18n/messages_pt_BR.xml +++ b/dspace/modules/xmlui/src/main/webapp/i18n/messages_pt_BR.xml @@ -50,6 +50,8 @@ <message key="xmlui.general.untitled">Sem título</message> <message key="xmlui.general.perform">Executar</message> <message key="xmlui.general.queue">Fila</message> + <message key="xmlui.general.statistics">Ver estatísticas</message> + <message key="xmlui.general.share">Compartilhar: </message> <!-- Page not found keys @@ -224,6 +226,7 @@ <message key="xmlui.ArtifactBrowser.CommunityViewer.head_sub_collections">Coleções nesta comunidade</message> <message key="xmlui.ArtifactBrowser.CommunityViewer.head_recent_submissions">Submissões recentes</message> + <message key="xmlui.ArtifactBrowser.AbstractRecentSubmissionTransformer.recent_submissions_more">Ver mais</message> <!-- org.dspace.app.xmlui.artifactbrowser.Contact.java --> <message key="xmlui.ArtifactBrowser.Contact.title">Fale conosco</message> @@ -611,7 +614,11 @@ <message key="xmlui.Submission.submit.progressbar.CClicense">CC Licença</message> <message key="xmlui.Submission.submit.progressbar.license">Licença</message> <message key="xmlui.Submission.submit.progressbar.complete">Completar</message> - + + <!-- submission form page's buttons --> + <message key="xmlui.Submission.submit.button.add">Adicionar</message> + <message key="xmlui.Submission.submit.button.remove_selected">Remover item(s) selecionado(s)</message> + <!-- org.dspace.app.xmlui.Submission.submit.ResumeStep --> <message key="xmlui.Submission.submit.ResumeStep.submit_resume">Resumo</message> @@ -905,7 +912,7 @@ <!-- Site administrator options --> <message key="xmlui.administrative.Navigation.administrative_head">Administrativo</message> <message key="xmlui.administrative.Navigation.administrative_access_control">Controle de acesso</message> - <message key="xmlui.administrative.Navigation.administrative_people">People</message> + <message key="xmlui.administrative.Navigation.administrative_people">Usuários</message> <message key="xmlui.administrative.Navigation.administrative_groups">Grupos</message> <message key="xmlui.administrative.Navigation.administrative_authorizations">Autorizações</message> <message key="xmlui.administrative.Navigation.administrative_registries">Registros</message> @@ -1925,7 +1932,7 @@ <message key="xmlui.statistics.Navigation.usage.view">Ver as estatísticas de uso</message> <message key="xmlui.statistics.Navigation.search.view">Ver as estatísticas de busca</message> <message key="xmlui.statistics.Navigation.workflow.view">Ver as estatísticas de fluxo de submissão</message> - <message key="xmlui.statistics.trail">Estatística</message> + <message key="xmlui.statistics.trail">Ver item</message> <message key="xmlui.statistics.trail-search">Estatísticas de busca</message> <message key="xmlui.statistics.trail-workflow">Estatísticas de fluxo de submissão</message> <message key="xmlui.statistics.workflow.no-results">Nenhuma estatística de busca está disponível para o período selecionado.</message> @@ -2003,7 +2010,7 @@ <message key="xmlui.dri2xhtml.structural.contact-link">Entre em contato</message> <message key="xmlui.dri2xhtml.structural.feedback-link">Deixe sua opinião</message> - <message key="xmlui.dri2xhtml.structural.head-subtitle">DSpace/Manakin Repository</message> + <message key="xmlui.dri2xhtml.structural.head-subtitle">Biblioteca Digital - SNJ</message> <message key="xmlui.dri2xhtml.structural.profile">Perfil: </message> <message key="xmlui.dri2xhtml.structural.logout">Sair</message> @@ -2551,11 +2558,7 @@ <!-- Participatorio --> <message key="participatorio.repo.title">Biblioteca Digital</message> - <message key="participatorio.repo.text">A Biblioteca Digital está inserida no movimento mundial de acesso aberto à produção técnica-científica. A adoção desse novo modelo de gestão para documentos eletrônicos possibilitará uma melhor disseminação e acesso às publicações sobre juventude e políticas públicas, seja da própria Secretaria Nacional de Juventude (SNJ), quanto de outros acervos institucionais ligados à temática.</message> - <message key="participatorio.repo.titleMissao">Missão</message> - <message key="participatorio.repo.textMissao">Armazenar, preservar, divulgar e dar amplo acesso à produção institucional da Secretaria Nacional de Juventude – SNJ e de outros acervos relacionados com a a área de políticas públicas de juventude.</message> - <message key="participatorio.repo.titleObjetivo">Objetivo</message> - <message key="participatorio.repo.textObjetivo">Reunir num único local virtual a produção institucional da SNJ, contribuindo para a preservação da memória institucional e para a maior visibilidade da temática de políticas públicas de juventude.</message> + <message key="participatorio.repo.text">A Biblioteca Digital do Participatório tem o objetivo de dar amplo acesso à produção institucional da Secretaria Nacional de Juventude (SNJ) e de outros acervos relacionados às políticas públicas de juventude, reunindo tudo em ambiente virtual. Ela está inserida no movimento mundial de acesso aberto à produção técnico-científica. A adoção desse novo modelo de gestão para documentos eletrônicos tem o intuito de possibilitar uma melhor disseminação das publicações sobre juventude e políticas públicas no mundo.</message> </catalogue> diff --git a/dspace/pom.xml b/dspace/pom.xml index 237ea40171fbf23d0f3858c684605f49cfaf77fe..206ee1273c8d6c7b12fea6d0a2da8e2d96aa5368 100644 --- a/dspace/pom.xml +++ b/dspace/pom.xml @@ -15,7 +15,7 @@ <parent> <groupId>org.dspace</groupId> <artifactId>dspace-parent</artifactId> - <version>3.2</version> + <version>4.1</version> <relativePath>..</relativePath> </parent> @@ -29,36 +29,6 @@ <!-- Filter using the properties file defined by dspace-parent POM --> <filter>${filters.file}</filter> </filters> - <resources> - <!-- Enumerate filtered files explicitly to avoid issues with other config tech. --> - <resource> - <directory>${basedir}</directory> - <filtering>true</filtering> - <includes> - <include>config/default.context.xml</include> - <include>config/dspace.cfg</include> - <include>config/log4j-handle-plugin.properties</include> - <include>config/log4j.properties</include> - <include>config/modules/curate.cfg</include> - <include>config/modules/oai.cfg</include> - <include>config/modules/solr-statistics.cfg</include> - </includes> - </resource> - <!-- Declare a mutually exclusive resource set for non-filtered files. --> - <resource> - <directory>${basedir}</directory> - <filtering>false</filtering> - <excludes> - <exclude>config/default.context.xml</exclude> - <exclude>config/dspace.cfg</exclude> - <exclude>config/log4j-handle-plugin.properties</exclude> - <exclude>config/log4j.properties</exclude> - <exclude>config/modules/curate.cfg</exclude> - <exclude>config/modules/oai.cfg</exclude> - <exclude>config/modules/solr-statistics.cfg</exclude> - </excludes> - </resource> - </resources> <plugins> <!-- Default project assembly. Calls 'assembly.xml', which diff --git a/dspace/solr/oai/conf/schema.xml b/dspace/solr/oai/conf/schema.xml index 67780813e3cb8f126828cc8bb1e4c90d40d23872..9e959f35ac5b9951eb243fc32f94802c596f5c5a 100644 --- a/dspace/solr/oai/conf/schema.xml +++ b/dspace/solr/oai/conf/schema.xml @@ -143,6 +143,7 @@ <fields> + <field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/> <!-- Item always present information --> <field name="item.id" type="int" indexed="true" stored="true" multiValued="false" /> <field name="item.public" type="boolean" indexed="true" stored="true" multiValued="false" /> diff --git a/dspace/solr/oai/conf/solrconfig.xml b/dspace/solr/oai/conf/solrconfig.xml index 2ccd3410ccfed4c30765a1e1663f23e5435e8a1f..a364bc626098ddcb70749778f6962ed116d4a41b 100644 --- a/dspace/solr/oai/conf/solrconfig.xml +++ b/dspace/solr/oai/conf/solrconfig.xml @@ -15,568 +15,808 @@ See the License for the specific language governing permissions and limitations under the License. --> -<!-- - For more details about configurations options that may appear in this - file, see http://wiki.apache.org/solr/SolrConfigXml. - Specifically, the Solr Config can support XInclude, which may make it easier to manage - the configuration. See https://issues.apache.org/jira/browse/SOLR-1167 +<!-- + For more details about configurations options that may appear in + this file, see http://wiki.apache.org/solr/SolrConfigXml. --> <config> - <!-- Set this to 'false' if you want solr to continue working after it has - encountered an severe configuration error. In a production environment, - you may want solr to keep working even if one handler is mis-configured. + <!-- In all configuration below, a prefix of "solr." for class names + is an alias that causes solr to search appropriate packages, + including org.apache.solr.(search|update|request|core|analysis) - You may also set this to false using by setting the system property: - -Dsolr.abortOnConfigurationError=false - --> - <abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError> + You may also specify a fully qualified Java classname if you + have your own custom plugins. + --> - <!-- lib directives can be used to instruct Solr to load an Jars identified - and use them to resolve any "plugins" specified in your solrconfig.xml or - schema.xml (ie: Analyzers, Request Handlers, etc...). + <!-- Controls what version of Lucene various components of Solr + adhere to. Generally, you want to use the latest version to + get all bug fixes and improvements. It is highly recommended + that you fully re-index after changing this setting as it can + affect both how text is indexed and queried. + --> + <luceneMatchVersion>4.4</luceneMatchVersion> + + <!-- <lib/> directives can be used to instruct Solr to load an Jars + identified and use them to resolve any "plugins" specified in + your solrconfig.xml or schema.xml (ie: Analyzers, Request + Handlers, etc...). + + All directories and paths are resolved relative to the + instanceDir. + + Please note that <lib/> directives are processed in the order + that they appear in your solrconfig.xml file, and are "stacked" + on top of each other when building a ClassLoader - so if you have + plugin jars with dependencies on other jars, the "lower level" + dependency jars should be loaded first. + + If a "./lib" directory exists in your instanceDir, all files + found in it are included as if you had used the following + syntax... + + <lib dir="./lib" /> + --> - All directories and paths are resolved relative the instanceDir. + <!-- A 'dir' option by itself adds any files found in the directory + to the classpath, this is useful for including all jars in a + directory. - If a "./lib" directory exists in your instanceDir, all files found in it - are included as if you had used the following syntax... + When a 'regex' is specified in addition to a 'dir', only the + files in that directory which completely match the regex + (anchored on both ends) will be included. - <lib dir="./lib" /> - --> - <!-- A dir option by itself adds any files found in the directory to the - classpath, this is useful for including all jars in a directory. - --> - <lib dir="../../contrib/extraction/lib" /> - <!-- When a regex is specified in addition to a directory, only the files in that - directory which completely match the regex (anchored on both ends) - will be included. - --> - <lib dir="../../dist/" regex="apache-solr-cell-\d.*\.jar" /> - <lib dir="../../dist/" regex="apache-solr-clustering-\d.*\.jar" /> - <!-- If a dir option (with or without a regex) is used and nothing is found - that matches, it will be ignored - --> - <lib dir="../../contrib/clustering/lib/downloads/" /> - <lib dir="../../contrib/clustering/lib/" /> - <lib dir="/total/crap/dir/ignored" /> - <!-- an exact path can be used to specify a specific file. This will cause - a serious error to be logged if it can't be loaded. - <lib path="../a-jar-that-does-not-exist.jar" /> - --> + If a 'dir' option (with or without a regex) is used and nothing + is found that matches, a warning will be logged. + The examples below can be used to load some solr-contribs along + with their external dependencies. + --> + <lib dir="../../../contrib/extraction/lib" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-cell-\d.*\.jar" /> - <!-- Used to specify an alternate directory to hold all index data - other than the default ./data under the Solr home. - If replication is in use, this should match the replication configuration. --> - <!--<dataDir>${solr.data.dir:./solr/data}</dataDir>--> + <lib dir="../../../contrib/clustering/lib/" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-clustering-\d.*\.jar" /> + <lib dir="../../../contrib/langid/lib/" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-langid-\d.*\.jar" /> - <!-- WARNING: this <indexDefaults> section only provides defaults for index writers - in general. See also the <mainIndex> section after that when changing parameters - for Solr's main Lucene index. --> - <indexDefaults> - <!-- Values here affect all index writers and act as a default unless overridden. --> - <useCompoundFile>false</useCompoundFile> + <lib dir="../../../contrib/velocity/lib" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-velocity-\d.*\.jar" /> - <mergeFactor>10</mergeFactor> - <!-- If both ramBufferSizeMB and maxBufferedDocs is set, then Lucene will flush - based on whichever limit is hit first. --> - <!--<maxBufferedDocs>1000</maxBufferedDocs>--> - - <!-- Sets the amount of RAM that may be used by Lucene indexing - for buffering added documents and deletions before they are - flushed to the Directory. --> - <ramBufferSizeMB>32</ramBufferSizeMB> - <!-- <maxMergeDocs>2147483647</maxMergeDocs> --> - <maxFieldLength>10000</maxFieldLength> - <writeLockTimeout>1000</writeLockTimeout> - <commitLockTimeout>10000</commitLockTimeout> + <!-- an exact 'path' can be used instead of a 'dir' to specify a + specific jar file. This will cause a serious error to be logged + if it can't be loaded. + --> + <!-- + <lib path="../a-jar-that-does-not-exist.jar" /> + --> + + <!-- Data Directory - <!-- - Expert: Turn on Lucene's auto commit capability. This causes intermediate - segment flushes to write a new lucene index descriptor, enabling it to be - opened by an external IndexReader. This can greatly slow down indexing - speed. NOTE: Despite the name, this value does not have any relation to - Solr's autoCommit functionality - --> - <!--<luceneAutoCommit>false</luceneAutoCommit>--> + Used to specify an alternate directory to hold all index data + other than the default ./data under the Solr home. If + replication is in use, this should match the replication + configuration. + --> + <dataDir>${solr.data.dir:}</dataDir> - <!-- - Expert: The Merge Policy in Lucene controls how merging is handled by - Lucene. The default in 2.3 is the LogByteSizeMergePolicy, previous - versions used LogDocMergePolicy. - LogByteSizeMergePolicy chooses segments to merge based on their size. The - Lucene 2.2 default, LogDocMergePolicy chose when to merge based on number - of documents + <!-- The DirectoryFactory to use for indexes. + + solr.StandardDirectoryFactory is filesystem + based and tries to pick the best implementation for the current + JVM and platform. solr.NRTCachingDirectoryFactory, the default, + wraps solr.StandardDirectoryFactory and caches small files in memory + for better NRT performance. - Other implementations of MergePolicy must have a no-argument constructor - --> - <!--<mergePolicy class="org.apache.lucene.index.LogByteSizeMergePolicy"/>--> + One can force a particular implementation via solr.MMapDirectoryFactory, + solr.NIOFSDirectoryFactory, or solr.SimpleFSDirectoryFactory. + solr.RAMDirectoryFactory is memory based, not + persistent, and doesn't work with replication. + --> + <directoryFactory name="DirectoryFactory" + class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/> + + <!-- The CodecFactory for defining the format of the inverted index. + The default implementation is SchemaCodecFactory, which is the official Lucene + index format, but hooks into the schema to provide per-field customization of + the postings lists and per-document values in the fieldType element + (postingsFormat/docValuesFormat). Note that most of the alternative implementations + are experimental, so if you choose to customize the index format, its a good + idea to convert back to the official format e.g. via IndexWriter.addIndexes(IndexReader) + before upgrading to a newer version to avoid unnecessary reindexing. + --> + <codecFactory class="solr.SchemaCodecFactory"/> + + <!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>: + + <schemaFactory class="ManagedIndexSchemaFactory"> + <bool name="mutable">true</bool> + <str name="managedSchemaResourceName">managed-schema</str> + </schemaFactory> + + When ManagedIndexSchemaFactory is specified, Solr will load the schema from + he resource named in 'managedSchemaResourceName', rather than from schema.xml. + Note that the managed schema resource CANNOT be named schema.xml. If the managed + schema does not exist, Solr will create it after reading schema.xml, then rename + 'schema.xml' to 'schema.xml.bak'. + + Do NOT hand edit the managed schema - external modifications will be ignored and + overwritten as a result of schema modification REST API calls. + + When ManagedIndexSchemaFactory is specified with mutable = true, schema + modification REST API calls will be allowed; otherwise, error responses will be + sent back for these requests. + --> + <schemaFactory class="ClassicIndexSchemaFactory"/> + + <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Index Config - These settings control low-level behavior of indexing + Most example settings here show the default value, but are commented + out, to more easily see where customizations have been made. + + Note: This replaces <indexDefaults> and <mainIndex> from older versions + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> + <indexConfig> + <!-- maxFieldLength was removed in 4.0. To get similar behavior, include a + LimitTokenCountFilterFactory in your fieldType definition. E.g. + <filter class="solr.LimitTokenCountFilterFactory" maxTokenCount="10000"/> + --> + <!-- Maximum time to wait for a write lock (ms) for an IndexWriter. Default: 1000 --> + <!-- <writeLockTimeout>1000</writeLockTimeout> --> + + <!-- The maximum number of simultaneous threads that may be + indexing documents at once in IndexWriter; if more than this + many threads arrive they will wait for others to finish. + Default in Solr/Lucene is 8. --> + <!-- <maxIndexingThreads>8</maxIndexingThreads> --> + + <!-- Expert: Enabling compound file will use less files for the index, + using fewer file descriptors on the expense of performance decrease. + Default in Lucene is "true". Default in Solr is "false" (since 3.6) --> + <!-- <useCompoundFile>false</useCompoundFile> --> + + <!-- ramBufferSizeMB sets the amount of RAM that may be used by Lucene + indexing for buffering added documents and deletions before they are + flushed to the Directory. + maxBufferedDocs sets a limit on the number of documents buffered + before flushing. + If both ramBufferSizeMB and maxBufferedDocs is set, then + Lucene will flush based on whichever limit is hit first. + The default is 100 MB. --> + <ramBufferSizeMB>32</ramBufferSizeMB> + <maxBufferedDocs>1000</maxBufferedDocs> + + <!-- Expert: Merge Policy + The Merge Policy in Lucene controls how merging of segments is done. + The default since Solr/Lucene 3.3 is TieredMergePolicy. + The default since Lucene 2.3 was the LogByteSizeMergePolicy, + Even older versions of Lucene used LogDocMergePolicy. + --> <!-- - Expert: - The Merge Scheduler in Lucene controls how merges are performed. The - ConcurrentMergeScheduler (Lucene 2.3 default) can perform merges in the - background using separate threads. The SerialMergeScheduler (Lucene 2.2 - default) does not. + <mergePolicy class="org.apache.lucene.index.TieredMergePolicy"> + <int name="maxMergeAtOnce">10</int> + <int name="segmentsPerTier">10</int> + </mergePolicy> + --> + + <!-- Merge Factor + The merge factor controls how many segments will get merged at a time. + For TieredMergePolicy, mergeFactor is a convenience parameter which + will set both MaxMergeAtOnce and SegmentsPerTier at once. + For LogByteSizeMergePolicy, mergeFactor decides how many new segments + will be allowed before they are merged into one. + Default is 10 for both merge policies. + --> + <!-- + <mergeFactor>10</mergeFactor> + --> + + <!-- Expert: Merge Scheduler + The Merge Scheduler in Lucene controls how merges are + performed. The ConcurrentMergeScheduler (Lucene 2.3 default) + can perform merges in the background using separate threads. + The SerialMergeScheduler (Lucene 2.2 default) does not. --> - <!--<mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>--> + <!-- + <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/> + --> + <!-- LockFactory - <!-- - This option specifies which Lucene LockFactory implementation to use. + This option specifies which Lucene LockFactory implementation + to use. + + single = SingleInstanceLockFactory - suggested for a + read-only index or when there is no possibility of + another process trying to modify the index. + native = NativeFSLockFactory - uses OS native file locking. + Do not use when multiple solr webapps in the same + JVM are attempting to share a single index. + simple = SimpleFSLockFactory - uses a plain file for locking - single = SingleInstanceLockFactory - suggested for a read-only index - or when there is no possibility of another process trying - to modify the index. - native = NativeFSLockFactory - uses OS native file locking - simple = SimpleFSLockFactory - uses a plain file for locking + Defaults: 'native' is default for Solr3.6 and later, otherwise + 'simple' is the default - (For backwards compatibility with Solr 1.2, 'simple' is the default - if not specified.) + More details on the nuances of each LockFactory... + http://wiki.apache.org/lucene-java/AvailableLockFactories --> - <lockType>native</lockType> - <!-- - Expert: - Controls how often Lucene loads terms into memory --> - <!--<termIndexInterval>256</termIndexInterval>--> - </indexDefaults> - - <mainIndex> - <!-- options specific to the main on-disk lucene index --> - <useCompoundFile>false</useCompoundFile> - <ramBufferSizeMB>32</ramBufferSizeMB> - <mergeFactor>10</mergeFactor> - <!-- Deprecated --> - <!--<maxBufferedDocs>1000</maxBufferedDocs>--> - <!--<maxMergeDocs>2147483647</maxMergeDocs>--> + <lockType>${solr.lock.type:native}</lockType> - <!-- inherit from indexDefaults <maxFieldLength>10000</maxFieldLength> --> + <!-- Unlock On Startup - <!-- If true, unlock any held write or commit locks on startup. + If true, unlock any held write or commit locks on startup. This defeats the locking mechanism that allows multiple - processes to safely access a lucene index, and should be - used with care. - This is not needed if lock type is 'none' or 'single' + processes to safely access a lucene index, and should be used + with care. Default is "false". + + This is not needed if lock type is 'single' --> + <!-- <unlockOnStartup>false</unlockOnStartup> + --> + + <!-- Expert: Controls how often Lucene loads terms into memory + Default is 128 and is likely good for most everyone. + --> + <!-- <termIndexInterval>128</termIndexInterval> --> - <!-- If true, IndexReaders will be reopened (often more efficient) instead - of closed and then opened. --> + <!-- If true, IndexReaders will be reopened (often more efficient) + instead of closed and then opened. Default: true + --> + <!-- <reopenReaders>true</reopenReaders> + --> - <!-- - Expert: - Controls how often Lucene loads terms into memory. Default is 128 and is likely good for most everyone. --> - <!--<termIndexInterval>256</termIndexInterval>--> - - <!-- - Custom deletion policies can specified here. The class must - implement org.apache.lucene.index.IndexDeletionPolicy. - - http://lucene.apache.org/java/2_3_2/api/org/apache/lucene/index/IndexDeletionPolicy.html - - The standard Solr IndexDeletionPolicy implementation supports deleting - index commit points on number of commits, age of commit point and - optimized status. + <!-- Commit Deletion Policy + Custom deletion policies can be specified here. The class must + implement org.apache.lucene.index.IndexDeletionPolicy. - The latest commit point should always be preserved regardless - of the criteria. + The default Solr IndexDeletionPolicy implementation supports + deleting index commit points on number of commits, age of + commit point and optimized status. + + The latest commit point should always be preserved regardless + of the criteria. --> + <!-- <deletionPolicy class="solr.SolrDeletionPolicy"> + --> <!-- The number of commit points to be kept --> - <str name="maxCommitsToKeep">1</str> + <!-- <str name="maxCommitsToKeep">1</str> --> <!-- The number of optimized commit points to be kept --> - <str name="maxOptimizedCommitsToKeep">0</str> + <!-- <str name="maxOptimizedCommitsToKeep">0</str> --> <!-- Delete all commit points once they have reached the given age. Supports DateMathParser syntax e.g. - - <str name="maxCommitAge">30MINUTES</str> - <str name="maxCommitAge">1DAY</str> + --> + <!-- + <str name="maxCommitAge">30MINUTES</str> + <str name="maxCommitAge">1DAY</str> --> + <!-- </deletionPolicy> + --> - <!-- To aid in advanced debugging, you may turn on IndexWriter debug logging. - Setting to true will set the file that the underlying Lucene IndexWriter - will write its debug infostream to. --> - <infoStream file="INFOSTREAM.txt">false</infoStream> - - </mainIndex> + <!-- Lucene Infostream + + To aid in advanced debugging, Lucene provides an "InfoStream" + of detailed information when indexing. - <!-- Enables JMX if and only if an existing MBeanServer is found, use this - if you want to configure JMX through JVM parameters. Remove this to disable - exposing Solr configuration and statistics to JMX. + Setting the value to true will instruct the underlying Lucene + IndexWriter to write its info stream to solr's log. By default, + this is enabled here, and controlled through log4j.properties. + --> + <infoStream>true</infoStream> + </indexConfig> - If you want to connect to a particular server, specify the agentId - e.g. <jmx agentId="myAgent" /> - If you want to start a new MBeanServer, specify the serviceUrl - e.g <jmx serviceUrl="service:jmx:rmi:///jndi/rmi://localhost:9999/solr"/> + <!-- JMX + + This example enables JMX if and only if an existing MBeanServer + is found, use this if you want to configure JMX through JVM + parameters. Remove this to disable exposing Solr configuration + and statistics to JMX. - For more details see http://wiki.apache.org/solr/SolrJmx - --> + For more details see http://wiki.apache.org/solr/SolrJmx + --> <jmx /> + <!-- If you want to connect to a particular server, specify the + agentId + --> + <!-- <jmx agentId="myAgent" /> --> + <!-- If you want to start a new MBeanServer, specify the serviceUrl --> + <!-- <jmx serviceUrl="service:jmx:rmi:///jndi/rmi://localhost:9999/solr"/> + --> - <!-- the default high-performance update handler --> + <!-- The default high-performance update handler --> <updateHandler class="solr.DirectUpdateHandler2"> - <!-- A prefix of "solr." for class names is an alias that - causes solr to search appropriate packages, including - org.apache.solr.(search|update|request|core|analysis) - --> - <!-- Perform a <commit/> automatically under certain conditions: - maxDocs - number of updates since last commit is greater than this - maxTime - oldest uncommited update (in ms) is this long ago + <!-- Enables a transaction log, used for real-time get, durability, and + and solr cloud replica recovery. The log can grow as big as + uncommitted changes to the index, so use of a hard autoCommit + is recommended (see below). + "dir" - the target directory for transaction logs, defaults to the + solr data directory. --> + <updateLog> + <str name="dir">${solr.ulog.dir:}</str> + </updateLog> + + <!-- AutoCommit + + Perform a hard commit automatically under certain conditions. Instead of enabling autoCommit, consider using "commitWithin" - when adding documents. http://wiki.apache.org/solr/UpdateXmlMessages - <autoCommit> - <maxDocs>10000</maxDocs> - <maxTime>1000</maxTime> - </autoCommit> - --> - <autoCommit> - <maxDocs>10000</maxDocs> <!--Commit every 10.000 documents--> - <maxTime>10000</maxTime> <!--Commit every 10 seconds--> - </autoCommit> + when adding documents. + + http://wiki.apache.org/solr/UpdateXmlMessages + + maxDocs - Maximum number of documents to add since the last + commit before automatically triggering a new commit. + + maxTime - Maximum amount of time in ms that is allowed to pass + since a document was added before automatically + triggering a new commit. + openSearcher - if false, the commit causes recent index changes + to be flushed to stable storage, but does not cause a new + searcher to be opened to make those changes visible. + + If the updateLog is enabled, then it's highly recommended to + have some sort of hard autoCommit to limit the log size. + --> + <autoCommit> + <maxDocs>10000</maxDocs> <!--Commit every 10.000 documents--> + <maxTime>${solr.autoCommit.maxTime:10000}</maxTime> <!--Default commit every 10 seconds--> + <openSearcher>true</openSearcher> + </autoCommit> + + <!-- softAutoCommit is like autoCommit except it causes a + 'soft' commit which only ensures that changes are visible + but does not ensure that data is synced to disk. This is + faster and more near-realtime friendly than a hard commit. + --> + + <autoSoftCommit> + <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime> + </autoSoftCommit> + <!-- Update Related Event Listeners + + Various IndexWriter related events can trigger Listeners to + take actions. + postCommit - fired after every commit or optimize command + postOptimize - fired after every optimize command + --> <!-- The RunExecutableListener executes an external command from a - hook such as postCommit or postOptimize. + hook such as postCommit or postOptimize. + exe - the name of the executable to run - dir - dir to use as the current working directory. default="." - wait - the calling thread waits until the executable returns. default="true" - args - the arguments to pass to the program. default=nothing - env - environment variables to set. default=nothing + dir - dir to use as the current working directory. (default=".") + wait - the calling thread waits until the executable returns. + (default="true") + args - the arguments to pass to the program. (default is none) + env - environment variables to set. (default is none) + --> + <!-- This example shows how RunExecutableListener could be used + with the script based replication... + http://wiki.apache.org/solr/CollectionDistribution + --> + <!-- + <listener event="postCommit" class="solr.RunExecutableListener"> + <str name="exe">solr/bin/snapshooter</str> + <str name="dir">.</str> + <bool name="wait">true</bool> + <arr name="args"> <str>arg1</str> <str>arg2</str> </arr> + <arr name="env"> <str>MYVAR=val1</str> </arr> + </listener> --> - <!-- A postCommit event is fired after every commit or optimize command - <listener event="postCommit" class="solr.RunExecutableListener"> - <str name="exe">solr/bin/snapshooter</str> - <str name="dir">.</str> - <bool name="wait">true</bool> - <arr name="args"> <str>arg1</str> <str>arg2</str> </arr> - <arr name="env"> <str>MYVAR=val1</str> </arr> - </listener> - --> - <!-- A postOptimize event is fired only after every optimize command - <listener event="postOptimize" class="solr.RunExecutableListener"> - <str name="exe">snapshooter</str> - <str name="dir">solr/bin</str> - <bool name="wait">true</bool> - </listener> - --> </updateHandler> - <!-- Use the following format to specify a custom IndexReaderFactory - allows for alternate - IndexReader implementations. + + <!-- IndexReaderFactory + + Use the following format to specify a custom IndexReaderFactory, + which allows for alternate IndexReader implementations. ** Experimental Feature ** - Please note - Using a custom IndexReaderFactory may prevent certain other features - from working. The API to IndexReaderFactory may change without warning or may even - be removed from future releases if the problems cannot be resolved. + + Please note - Using a custom IndexReaderFactory may prevent + certain other features from working. The API to + IndexReaderFactory may change without warning or may even be + removed from future releases if the problems cannot be + resolved. + ** Features that may not work with custom IndexReaderFactory ** - The ReplicationHandler assumes a disk-resident index. Using a custom - IndexReader implementation may cause incompatibility with ReplicationHandler and - may cause replication to not work correctly. See SOLR-1366 for details. + The ReplicationHandler assumes a disk-resident index. Using a + custom IndexReader implementation may cause incompatibility + with ReplicationHandler and may cause replication to not work + correctly. See SOLR-1366 for details. + + --> + <!-- <indexReaderFactory name="IndexReaderFactory" class="package.class"> - Parameters as required by the implementation + <str name="someArg">Some Value</str> </indexReaderFactory > --> - <!-- To set the termInfosIndexDivisor, do this: --> - <!--<indexReaderFactory name="IndexReaderFactory" class="org.apache.solr.core.StandardIndexReaderFactory"> - <int name="termInfosIndexDivisor">12</int> - </indexReaderFactory >--> + <!-- By explicitly declaring the Factory, the termIndexDivisor can + be specified. + --> + <!-- + <indexReaderFactory name="IndexReaderFactory" + class="solr.StandardIndexReaderFactory"> + <int name="setTermIndexDivisor">12</int> + </indexReaderFactory > + --> + <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Query section - these settings control query time things like caches + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <query> - <!-- Maximum number of clauses in a boolean query... in the past, this affected - range or prefix queries that expanded to big boolean queries - built in Solr - query parsers no longer create queries with this limitation. - An exception is thrown if exceeded. --> + <!-- Max Boolean Clauses + + Maximum number of clauses in each BooleanQuery, an exception + is thrown if exceeded. + + ** WARNING ** + + This option actually modifies a global Lucene property that + will affect all SolrCores. If multiple solrconfig.xml files + disagree on this property, the value at any given moment will + be based on the last SolrCore to be initialized. + + --> <maxBooleanClauses>1024</maxBooleanClauses> - <!-- There are two implementations of cache available for Solr, + <!-- Solr Internal Query Caches + + There are two implementations of cache available for Solr, LRUCache, based on a synchronized LinkedHashMap, and - FastLRUCache, based on a ConcurrentHashMap. FastLRUCache has faster gets - and slower puts in single threaded operation and thus is generally faster - than LRUCache when the hit ratio of the cache is high (> 75%), and may be - faster under other scenarios on multi-cpu systems. --> - <!-- Cache used by SolrIndexSearcher for filters (DocSets), - unordered sets of *all* documents that match a query. - When a new searcher is opened, its caches may be prepopulated - or "autowarmed" using data from caches in the old searcher. - autowarmCount is the number of items to prepopulate. For LRUCache, - the autowarmed items will be the most recently accessed items. - Parameters: - class - the SolrCache implementation LRUCache or FastLRUCache - size - the maximum number of entries in the cache - initialSize - the initial capacity (number of entries) of - the cache. (seel java.util.HashMap) - autowarmCount - the number of entries to prepopulate from - and old cache. - --> - <filterCache - class="solr.FastLRUCache" - size="512" - initialSize="512" - autowarmCount="0"/> - - <!-- Cache used to hold field values that are quickly accessible + FastLRUCache, based on a ConcurrentHashMap. + + FastLRUCache has faster gets and slower puts in single + threaded operation and thus is generally faster than LRUCache + when the hit ratio of the cache is high (> 75%), and may be + faster under other scenarios on multi-cpu systems. + --> + + <!-- Filter Cache + + Cache used by SolrIndexSearcher for filters (DocSets), + unordered sets of *all* documents that match a query. When a + new searcher is opened, its caches may be prepopulated or + "autowarmed" using data from caches in the old searcher. + autowarmCount is the number of items to prepopulate. For + LRUCache, the autowarmed items will be the most recently + accessed items. + + Parameters: + class - the SolrCache implementation LRUCache or + (LRUCache or FastLRUCache) + size - the maximum number of entries in the cache + initialSize - the initial capacity (number of entries) of + the cache. (see java.util.HashMap) + autowarmCount - the number of entries to prepopulate from + and old cache. + --> + <filterCache class="solr.FastLRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + + <!-- Query Result Cache + + Caches results of searches - ordered lists of document ids + (DocList) based on a query, a sort, and the range of documents requested. + --> + <queryResultCache class="solr.LRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + + <!-- Document Cache + + Caches Lucene Document objects (the stored fields for each + document). Since Lucene internal document ids are transient, + this cache will not be autowarmed. + --> + <documentCache class="solr.LRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + + <!-- Field Value Cache + + Cache used to hold field values that are quickly accessible by document id. The fieldValueCache is created by default even if not configured here. - <fieldValueCache - class="solr.FastLRUCache" - size="512" - autowarmCount="128" - showItems="32" - /> - --> + --> + <!-- + <fieldValueCache class="solr.FastLRUCache" + size="512" + autowarmCount="128" + showItems="32" /> + --> - <!-- queryResultCache caches results of searches - ordered lists of - document ids (DocList) based on a query, a sort, and the range - of documents requested. --> - <queryResultCache - class="solr.LRUCache" - size="512" - initialSize="512" - autowarmCount="0"/> - - <!-- documentCache caches Lucene Document objects (the stored fields for each document). - Since Lucene internal document ids are transient, this cache will not be autowarmed. --> - <documentCache - class="solr.LRUCache" - size="512" - initialSize="512" - autowarmCount="0"/> - - <!-- If true, stored fields that are not requested will be loaded lazily. - This can result in a significant speed improvement if the usual case is to - not load all stored fields, especially if the skipped fields are large - compressed text fields. - --> - <enableLazyFieldLoading>true</enableLazyFieldLoading> + <!-- Custom Cache - <!-- Example of a generic cache. These caches may be accessed by name - through SolrIndexSearcher.getCache(),cacheLookup(), and cacheInsert(). - The purpose is to enable easy caching of user/application level data. - The regenerator argument should be specified as an implementation - of solr.search.CacheRegenerator if autowarming is desired. --> + Example of a generic cache. These caches may be accessed by + name through SolrIndexSearcher.getCache(),cacheLookup(), and + cacheInsert(). The purpose is to enable easy caching of + user/application level data. The regenerator argument should + be specified as an implementation of solr.CacheRegenerator + if autowarming is desired. + --> <!-- - <cache name="myUserCache" - class="solr.LRUCache" - size="4096" - initialSize="1024" - autowarmCount="1024" - regenerator="org.mycompany.mypackage.MyRegenerator" - /> - --> + <cache name="myUserCache" + class="solr.LRUCache" + size="4096" + initialSize="1024" + autowarmCount="1024" + regenerator="com.mycompany.MyRegenerator" + /> + --> - <!-- An optimization that attempts to use a filter to satisfy a search. - If the requested sort does not include score, then the filterCache - will be checked for a filter matching the query. If found, the filter - will be used as the source of document ids, and then the sort will be - applied to that. - <useFilterForSortedQuery>true</useFilterForSortedQuery> - --> - <!-- An optimization for use with the queryResultCache. When a search - is requested, a superset of the requested number of document ids - are collected. For example, if a search for a particular query - requests matching documents 10 through 19, and queryWindowSize is 50, - then documents 0 through 49 will be collected and cached. Any further - requests in that range can be satisfied via the cache. --> - <queryResultWindowSize>20</queryResultWindowSize> - - <!-- Maximum number of documents to cache for any entry in the - queryResultCache. --> - <queryResultMaxDocsCached>200</queryResultMaxDocsCached> - - <!-- a newSearcher event is fired whenever a new searcher is being prepared - and there is a current searcher handling requests (aka registered). - It can be used to prime certain caches to prevent long request times for - certain requests. + <!-- Lazy Field Loading + + If true, stored fields that are not requested will be loaded + lazily. This can result in a significant speed improvement + if the usual case is to not load all stored fields, + especially if the skipped fields are large compressed text + fields. --> + <enableLazyFieldLoading>true</enableLazyFieldLoading> + + <!-- Use Filter For Sorted Query + + A possible optimization that attempts to use a filter to + satisfy a search. If the requested sort does not include + score, then the filterCache will be checked for a filter + matching the query. If found, the filter will be used as the + source of document ids, and then the sort will be applied to + that. + + For most situations, this will not be useful unless you + frequently get the same search repeatedly with different sort + options, and none of them ever use "score" + --> + <!-- + <useFilterForSortedQuery>true</useFilterForSortedQuery> + --> + + <!-- Result Window Size + + An optimization for use with the queryResultCache. When a search + is requested, a superset of the requested number of document ids + are collected. For example, if a search for a particular query + requests matching documents 10 through 19, and queryWindowSize is 50, + then documents 0 through 49 will be collected and cached. Any further + requests in that range can be satisfied via the cache. + --> + <queryResultWindowSize>20</queryResultWindowSize> + + <!-- Maximum number of documents to cache for any entry in the + queryResultCache. + --> + <queryResultMaxDocsCached>200</queryResultMaxDocsCached> + + <!-- Query Related Event Listeners + + Various IndexSearcher related events can trigger Listeners to + take actions. + + newSearcher - fired whenever a new searcher is being prepared + and there is a current searcher handling requests (aka + registered). It can be used to prime certain caches to + prevent long request times for certain requests. + + firstSearcher - fired whenever a new searcher is being + prepared but there is no current registered searcher to handle + requests or to gain autowarming data from. + + + --> <!-- QuerySenderListener takes an array of NamedList and executes a - local query request for each NamedList in sequence. --> + local query request for each NamedList in sequence. + --> <listener event="newSearcher" class="solr.QuerySenderListener"> <arr name="queries"> <!-- - <lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst> - <lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst> - <lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst> - --> + <lst><str name="q">solr</str><str name="sort">price asc</str></lst> + <lst><str name="q">rocks</str><str name="sort">weight asc</str></lst> + --> </arr> </listener> - - <!-- a firstSearcher event is fired whenever a new searcher is being - prepared but there is no current registered searcher to handle - requests or to gain autowarming data from. --> <listener event="firstSearcher" class="solr.QuerySenderListener"> <arr name="queries"> - <lst> <str name="q">solr rocks</str><str name="start">0</str><str name="rows">10</str></lst> - <lst><str name="q">static firstSearcher warming query from solrconfig.xml</str></lst> + <lst> + <str name="q">static firstSearcher warming in solrconfig.xml</str> + </lst> </arr> </listener> - <!-- If a search request comes in and there is no current registered searcher, - then immediately register the still warming searcher and use it. If - "false" then all requests will block until the first searcher is done - warming. --> + <!-- Use Cold Searcher + + If a search request comes in and there is no current + registered searcher, then immediately register the still + warming searcher and use it. If "false" then all requests + will block until the first searcher is done warming. + --> <useColdSearcher>false</useColdSearcher> - <!-- Maximum number of searchers that may be warming in the background - concurrently. An error is returned if this limit is exceeded. Recommend - 1-2 for read-only slaves, higher for masters w/o cache warming. --> + <!-- Max Warming Searchers + + Maximum number of searchers that may be warming in the + background concurrently. An error is returned if this limit + is exceeded. + + Recommend values of 1-2 for read-only slaves, higher for + masters w/o cache warming. + --> <maxWarmingSearchers>2</maxWarmingSearchers> </query> + + <!-- Request Dispatcher - <!-- - Let the dispatch filter handler /select?qt=XXX - handleSelect=true will use consistent error handling for /select and /update - handleSelect=false will use solr1.1 style error formatting - --> - <requestDispatcher handleSelect="true" > - <!--Make sure your system has some authentication before enabling remote streaming! --> - <requestParsers enableRemoteStreaming="true" multipartUploadLimitInKB="2048000" /> + This section contains instructions for how the SolrDispatchFilter + should behave when processing requests for this SolrCore. - <!-- Set HTTP caching related parameters (for proxy caches and clients). + handleSelect is a legacy option that affects the behavior of requests + such as /select?qt=XXX - To get the behaviour of Solr 1.2 (ie: no caching related headers) - use the never304="true" option and do not specify a value for - <cacheControl> - --> - <!-- <httpCaching never304="true"> --> - <httpCaching lastModifiedFrom="openTime" - etagSeed="Solr"> - <!-- lastModFrom="openTime" is the default, the Last-Modified value - (and validation against If-Modified-Since requests) will all be - relative to when the current Searcher was opened. - You can change it to lastModFrom="dirLastMod" if you want the - value to exactly corrispond to when the physical index was last - modified. - - etagSeed="..." is an option you can change to force the ETag - header (and validation against If-None-Match requests) to be - differnet even if the index has not changed (ie: when making - significant changes to your config file) - - lastModifiedFrom and etagSeed are both ignored if you use the - never304="true" option. - --> - <!-- If you include a <cacheControl> directive, it will be used to - generate a Cache-Control header, as well as an Expires header - if the value contains "max-age=" + handleSelect="true" will cause the SolrDispatchFilter to process + the request and dispatch the query to a handler specified by the + "qt" param, assuming "/select" isn't already registered. - By default, no Cache-Control header is generated. + handleSelect="false" will cause the SolrDispatchFilter to + ignore "/select" requests, resulting in a 404 unless a handler + is explicitly registered with the name "/select" - You can use the <cacheControl> option even if you have set - never304="true" - --> - <!-- <cacheControl>max-age=30, public</cacheControl> --> - </httpCaching> + handleSelect="true" is not recommended for new users, but is the default + for backwards compatibility + --> + <requestDispatcher handleSelect="false" > + <!-- Request Parsing + + These settings indicate how Solr Requests may be parsed, and + what restrictions may be placed on the ContentStreams from + those requests + + enableRemoteStreaming - enables use of the stream.file + and stream.url parameters for specifying remote streams. + + multipartUploadLimitInKB - specifies the max size (in KiB) of + Multipart File Uploads that Solr will allow in a Request. + + formdataUploadLimitInKB - specifies the max size (in KiB) of + form data (application/x-www-form-urlencoded) sent via + POST. You can use POST to pass request parameters not + fitting into the URL. + + addHttpRequestToContext - if set to true, it will instruct + the requestParsers to include the original HttpServletRequest + object in the context map of the SolrQueryRequest under the + key "httpRequest". It will not be used by any of the existing + Solr components, but may be useful when developing custom + plugins. + + *** WARNING *** + The settings below authorize Solr to fetch remote files, You + should make sure your system has some authentication before + using enableRemoteStreaming="true" + + --> + <requestParsers enableRemoteStreaming="true" + multipartUploadLimitInKB="2048000" + formdataUploadLimitInKB="2048" + addHttpRequestToContext="false"/> + + <!-- HTTP Caching + + Set HTTP caching related parameters (for proxy caches and clients). + + The options below instruct Solr not to output any HTTP Caching + related headers + --> + <httpCaching never304="true" /> + <!-- If you include a <cacheControl> directive, it will be used to + generate a Cache-Control header (as well as an Expires header + if the value contains "max-age=") + + By default, no Cache-Control header is generated. + + You can use the <cacheControl> option even if you have set + never304="true" + --> + <!-- + <httpCaching never304="true" > + <cacheControl>max-age=30, public</cacheControl> + </httpCaching> + --> + <!-- To enable Solr to respond with automatically generated HTTP + Caching headers, and to response to Cache Validation requests + correctly, set the value of never304="false" + + This will cause Solr to generate Last-Modified and ETag + headers based on the properties of the Index. + + The following options can also be specified to affect the + values of these headers... + + lastModFrom - the default value is "openTime" which means the + Last-Modified value (and validation against If-Modified-Since + requests) will all be relative to when the current Searcher + was opened. You can change it to lastModFrom="dirLastMod" if + you want the value to exactly correspond to when the physical + index was last modified. + + etagSeed="..." is an option you can change to force the ETag + header (and validation against If-None-Match requests) to be + different even if the index has not changed (ie: when making + significant changes to your config file) + + (lastModifiedFrom and etagSeed are both ignored if you use + the never304="true" option) + --> + <!-- + <httpCaching lastModifiedFrom="openTime" + etagSeed="Solr"> + <cacheControl>max-age=30, public</cacheControl> + </httpCaching> + --> </requestDispatcher> - <!-- requestHandler plugins... incoming queries will be dispatched to the - correct handler based on the path or the qt (query type) param. - Names starting with a '/' are accessed with the a path equal to the - registered name. Names without a leading '/' are accessed with: - http://host/app/select?qt=name - If no qt is defined, the requestHandler that declares default="true" - will be used. - --> - <requestHandler name="standard" class="solr.SearchHandler" default="true"> - <!-- default values for query parameters --> - <lst name="defaults"> - <str name="echoParams">explicit</str> - <!-- - <int name="rows">10</int> - <str name="fl">*</str> - <str name="version">2.1</str> - --> - </lst> - </requestHandler> + <!-- Request Handlers -<!-- Please refer to http://wiki.apache.org/solr/SolrReplication for details on configuring replication --> -<!-- remove the <lst name="master"> section if this is just a slave --> -<!-- remove the <lst name="slave"> section if this is just a master --> -<!-- -<requestHandler name="/replication" class="solr.ReplicationHandler" > - <lst name="master"> - <str name="replicateAfter">commit</str> - <str name="replicateAfter">startup</str> - <str name="confFiles">schema.xml,stopwords.txt</str> - </lst> - <lst name="slave"> - <str name="masterUrl">http://localhost:8983/solr/replication</str> - <str name="pollInterval">00:00:60</str> - </lst> -</requestHandler>--> + http://wiki.apache.org/solr/SolrRequestHandler - <!-- DisMaxRequestHandler allows easy searching across multiple fields - for simple user-entered phrases. It's implementation is now - just the standard SearchHandler with a default query type - of "dismax". - see http://wiki.apache.org/solr/DisMaxRequestHandler - --> - <requestHandler name="dismax" class="solr.SearchHandler" > - <lst name="defaults"> - <str name="defType">dismax</str> - <str name="echoParams">explicit</str> - <float name="tie">0.01</float> - <str name="qf"> - text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 - </str> - <str name="pf"> - text^0.2 features^1.1 name^1.5 manu^1.4 manu_exact^1.9 - </str> - <str name="bf"> - popularity^0.5 recip(price,1,1000,1000)^0.3 - </str> - <str name="fl"> - id,name,price,score - </str> - <str name="mm"> - 2<-1 5<-2 6<90% - </str> - <int name="ps">100</int> - <str name="q.alt">*:*</str> - <!-- example highlighter config, enable per-query with hl=true --> - <str name="hl.fl">text features name</str> - <!-- for this field, we want no fragmenting, just highlighting --> - <str name="f.name.hl.fragsize">0</str> - <!-- instructs Solr to return the field itself if no query terms are - found --> - <str name="f.name.hl.alternateField">name</str> - <str name="f.text.hl.fragmenter">regex</str> <!-- defined below --> - </lst> - </requestHandler> + Incoming queries will be dispatched to a specific handler by name + based on the path specified in the request. + + Legacy behavior: If the request path uses "/select" but no Request + Handler has that name, and if handleSelect="true" has been specified in + the requestDispatcher, then the Request Handler is dispatched based on + the qt parameter. Handlers without a leading '/' are accessed this way + like so: http://host/app/[core/]select?qt=name If no qt is + given, then the requestHandler that declares default="true" will be + used or the one named "standard". + + If a Request Handler is declared with startup="lazy", then it will + not be initialized until the first request that uses it. - <!-- Note how you can register the same handler multiple times with - different names (and different init parameters) --> - <requestHandler name="partitioned" class="solr.SearchHandler" > - <lst name="defaults"> - <str name="defType">dismax</str> - <str name="echoParams">explicit</str> - <str name="qf">text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0</str> - <str name="mm">2<-1 5<-2 6<90%</str> - <!-- This is an example of using Date Math to specify a constantly - moving date range in a config... - --> - <str name="bq">incubationdate_dt:[* TO NOW/DAY-1MONTH]^2.2</str> - </lst> + <!-- SearchHandler + + http://wiki.apache.org/solr/SearchHandler + + For processing Search Queries, the primary Request Handler + provided with Solr is "SearchHandler" It delegates to a sequent + of SearchComponents (see below) and supports distributed + queries across multiple shards + --> + <requestHandler name="/select" class="solr.SearchHandler"> + <!-- default values for query parameters can be specified, these + will be overridden by parameters in the request + --> + <lst name="defaults"> + <str name="echoParams">explicit</str> + <int name="rows">10</int> + <str name="df">item.handle</str> + </lst> <!-- In addition to defaults, "appends" params can be specified to identify values which should be appended to the list of multi-val params from the query (or the existing "defaults"). - - In this example, the param "fq=instock:true" will be appended to + --> + <!-- In this example, the param "fq=instock:true" would be appended to any query time fq params the user may specify, as a mechanism for partitioning the index, independent of any user selected filtering that may also be desired (perhaps as a result of faceted searching). @@ -585,33 +825,373 @@ "appends" values from being used, so don't use this mechanism unless you are sure you always want it. --> - <lst name="appends"> - <str name="fq">inStock:true</str> - </lst> + <!-- + <lst name="appends"> + <str name="fq">inStock:true</str> + </lst> + --> <!-- "invariants" are a way of letting the Solr maintainer lock down the options available to Solr clients. Any params values specified here are used regardless of what values may be specified in either the query, the "defaults", or the "appends" params. - In this example, the facet.field and facet.query params are fixed, - limiting the facets clients can use. Faceting is not turned on by - default - but if the client does specify facet=true in the request, - these are the only facets they will be able to see counts for; - regardless of what other facet.field or facet.query params they - may specify. + In this example, the facet.field and facet.query params would + be fixed, limiting the facets clients can use. Faceting is + not turned on by default - but if the client does specify + facet=true in the request, these are the only facets they + will be able to see counts for; regardless of what other + facet.field or facet.query params they may specify. NOTE: there is *absolutely* nothing a client can do to prevent these "invariants" values from being used, so don't use this mechanism unless you are sure you always want it. --> + <!-- + <lst name="invariants"> + <str name="facet.field">cat</str> + <str name="facet.field">manu_exact</str> + <str name="facet.query">price:[* TO 500]</str> + <str name="facet.query">price:[500 TO *]</str> + </lst> + --> + <!-- If the default list of SearchComponents is not desired, that + list can either be overridden completely, or components can be + prepended or appended to the default list. (see below) + --> + <!-- + <arr name="components"> + <str>nameOfCustomComponent1</str> + <str>nameOfCustomComponent2</str> + </arr> + --> + </requestHandler> + + <!-- A request handler that returns indented JSON by default --> + <requestHandler name="/query" class="solr.SearchHandler"> + <lst name="defaults"> + <str name="echoParams">explicit</str> + <str name="wt">json</str> + <str name="indent">true</str> + <str name="df">item.handle</str> + </lst> + </requestHandler> + + + <!-- realtime get handler, guaranteed to return the latest stored fields of + any document, without the need to commit or open a new searcher. The + current implementation relies on the updateLog feature being enabled. --> + <requestHandler name="/get" class="solr.RealTimeGetHandler"> + <lst name="defaults"> + <str name="omitHeader">true</str> + <str name="wt">json</str> + <str name="indent">true</str> + </lst> + </requestHandler> + + + <!-- A Robust Example + + This example SearchHandler declaration shows off usage of the + SearchHandler with many defaults declared + + Note that multiple instances of the same Request Handler + (SearchHandler) can be registered multiple times with different + names (and different init parameters) + --> + <requestHandler name="/browse" class="solr.SearchHandler"> + <lst name="defaults"> + <str name="echoParams">explicit</str> + + <!-- VelocityResponseWriter settings --> + <str name="wt">velocity</str> + <str name="v.template">browse</str> + <str name="v.layout">layout</str> + <str name="title">Solritas</str> + + <!-- Query settings --> + <str name="defType">edismax</str> + <str name="qf"> + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0 + </str> + <str name="df">item.handle</str> + <str name="mm">100%</str> + <str name="q.alt">*:*</str> + <str name="rows">10</str> + <str name="fl">*,score</str> + + <str name="mlt.qf"> + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0 + </str> + <str name="mlt.fl">text,features,name,sku,id,manu,cat,title,description,keywords,author,resourcename</str> + <int name="mlt.count">3</int> + + <!-- Faceting defaults --> + <str name="facet">on</str> + <str name="facet.field">cat</str> + <str name="facet.field">manu_exact</str> + <str name="facet.field">content_type</str> + <str name="facet.field">author_s</str> + <str name="facet.query">ipod</str> + <str name="facet.query">GB</str> + <str name="facet.mincount">1</str> + <str name="facet.pivot">cat,inStock</str> + <str name="facet.range.other">after</str> + <str name="facet.range">price</str> + <int name="f.price.facet.range.start">0</int> + <int name="f.price.facet.range.end">600</int> + <int name="f.price.facet.range.gap">50</int> + <str name="facet.range">popularity</str> + <int name="f.popularity.facet.range.start">0</int> + <int name="f.popularity.facet.range.end">10</int> + <int name="f.popularity.facet.range.gap">3</int> + <str name="facet.range">manufacturedate_dt</str> + <str name="f.manufacturedate_dt.facet.range.start">NOW/YEAR-10YEARS</str> + <str name="f.manufacturedate_dt.facet.range.end">NOW</str> + <str name="f.manufacturedate_dt.facet.range.gap">+1YEAR</str> + <str name="f.manufacturedate_dt.facet.range.other">before</str> + <str name="f.manufacturedate_dt.facet.range.other">after</str> + + <!-- Highlighting defaults --> + <str name="hl">on</str> + <str name="hl.fl">content features title name</str> + <str name="hl.encoder">html</str> + <str name="hl.simple.pre"><b></str> + <str name="hl.simple.post"></b></str> + <str name="f.title.hl.fragsize">0</str> + <str name="f.title.hl.alternateField">title</str> + <str name="f.name.hl.fragsize">0</str> + <str name="f.name.hl.alternateField">name</str> + <str name="f.content.hl.snippets">3</str> + <str name="f.content.hl.fragsize">200</str> + <str name="f.content.hl.alternateField">content</str> + <str name="f.content.hl.maxAlternateFieldLength">750</str> + + <!-- Spell checking defaults --> + <str name="spellcheck">on</str> + <str name="spellcheck.extendedResults">false</str> + <str name="spellcheck.count">5</str> + <str name="spellcheck.alternativeTermCount">2</str> + <str name="spellcheck.maxResultsForSuggest">5</str> + <str name="spellcheck.collate">true</str> + <str name="spellcheck.collateExtendedResults">true</str> + <str name="spellcheck.maxCollationTries">5</str> + <str name="spellcheck.maxCollations">3</str> + </lst> + + <!-- append spellchecking to our list of components --> + <arr name="last-components"> + <str>spellcheck</str> + </arr> + </requestHandler> + + <!-- Update Request Handler. + + http://wiki.apache.org/solr/UpdateXmlMessages + + The canonical Request Handler for Modifying the Index through + commands specified using XML, JSON, CSV, or JAVABIN + + Note: Since solr1.1 requestHandlers requires a valid content + type header if posted in the body. For example, curl now + requires: -H 'Content-type:text/xml; charset=utf-8' + + To override the request content type and force a specific + Content-type, use the request parameter: + ?update.contentType=text/csv + + This handler will pick a response format to match the input + if the 'wt' parameter is not explicit + --> + <requestHandler name="/update" class="solr.UpdateRequestHandler"> + <!-- See below for information on defining + updateRequestProcessorChains that can be used by name + on each Update Request + --> + <!-- + <lst name="defaults"> + <str name="update.chain">dedupe</str> + </lst> + --> + </requestHandler> + + <!-- for back compat with clients using /update/json and /update/csv --> + <requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler"> + <lst name="defaults"> + <str name="stream.contentType">application/json</str> + </lst> + </requestHandler> + <requestHandler name="/update/csv" class="solr.CSVRequestHandler"> + <lst name="defaults"> + <str name="stream.contentType">application/csv</str> + </lst> + </requestHandler> + + <!-- Solr Cell Update Request Handler + + http://wiki.apache.org/solr/ExtractingRequestHandler + + --> + <requestHandler name="/update/extract" + startup="lazy" + class="solr.extraction.ExtractingRequestHandler" > + <lst name="defaults"> + <str name="lowernames">true</str> + <str name="uprefix">ignored_</str> + + <!-- capture link hrefs but ignore div attributes --> + <str name="captureAttr">true</str> + <str name="fmap.a">links</str> + <str name="fmap.div">ignored_</str> + </lst> + </requestHandler> + + + <!-- Field Analysis Request Handler + + RequestHandler that provides much the same functionality as + analysis.jsp. Provides the ability to specify multiple field + types and field names in the same request and outputs + index-time and query-time analysis for each of them. + + Request parameters are: + analysis.fieldname - field name whose analyzers are to be used + + analysis.fieldtype - field type whose analyzers are to be used + analysis.fieldvalue - text for index-time analysis + q (or analysis.q) - text for query time analysis + analysis.showmatch (true|false) - When set to true and when + query analysis is performed, the produced tokens of the + field value analysis will be marked as "matched" for every + token that is produces by the query analysis + --> + <requestHandler name="/analysis/field" + startup="lazy" + class="solr.FieldAnalysisRequestHandler" /> + + + <!-- Document Analysis Handler + + http://wiki.apache.org/solr/AnalysisRequestHandler + + An analysis handler that provides a breakdown of the analysis + process of provided documents. This handler expects a (single) + content stream with the following format: + + <docs> + <doc> + <field name="id">1</field> + <field name="name">The Name</field> + <field name="text">The Text Value</field> + </doc> + <doc>...</doc> + <doc>...</doc> + ... + </docs> + + Note: Each document must contain a field which serves as the + unique key. This key is used in the returned response to associate + an analysis breakdown to the analyzed document. + + Like the FieldAnalysisRequestHandler, this handler also supports + query analysis by sending either an "analysis.query" or "q" + request parameter that holds the query text to be analyzed. It + also supports the "analysis.showmatch" parameter which when set to + true, all field tokens that match the query tokens will be marked + as a "match". + --> + <requestHandler name="/analysis/document" + class="solr.DocumentAnalysisRequestHandler" + startup="lazy" /> + + <!-- Admin Handlers + + Admin Handlers - This will register all the standard admin + RequestHandlers. + --> + <requestHandler name="/admin/" + class="solr.admin.AdminHandlers" /> + <!-- This single handler is equivalent to the following... --> + <!-- + <requestHandler name="/admin/luke" class="solr.admin.LukeRequestHandler" /> + <requestHandler name="/admin/system" class="solr.admin.SystemInfoHandler" /> + <requestHandler name="/admin/plugins" class="solr.admin.PluginInfoHandler" /> + <requestHandler name="/admin/threads" class="solr.admin.ThreadDumpHandler" /> + <requestHandler name="/admin/properties" class="solr.admin.PropertiesRequestHandler" /> + <requestHandler name="/admin/file" class="solr.admin.ShowFileRequestHandler" > + --> + <!-- If you wish to hide files under ${solr.home}/conf, explicitly + register the ShowFileRequestHandler using: + --> + <!-- + <requestHandler name="/admin/file" + class="solr.admin.ShowFileRequestHandler" > + <lst name="invariants"> + <str name="hidden">synonyms.txt</str> + <str name="hidden">anotherfile.txt</str> + </lst> + </requestHandler> + --> + + <!-- ping/healthcheck --> + <requestHandler name="/admin/ping" class="solr.PingRequestHandler"> <lst name="invariants"> - <str name="facet.field">cat</str> - <str name="facet.field">manu_exact</str> - <str name="facet.query">price:[* TO 500]</str> - <str name="facet.query">price:[500 TO *]</str> + <str name="q">solrpingquery</str> </lst> + <lst name="defaults"> + <str name="echoParams">all</str> + </lst> + <!-- An optional feature of the PingRequestHandler is to configure the + handler with a "healthcheckFile" which can be used to enable/disable + the PingRequestHandler. + relative paths are resolved against the data dir + --> + <!-- <str name="healthcheckFile">server-enabled.txt</str> --> </requestHandler> + <!-- Echo the request contents back to the client --> + <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" > + <lst name="defaults"> + <str name="echoParams">explicit</str> + <str name="echoHandler">true</str> + </lst> + </requestHandler> + + <!-- Solr Replication + + The SolrReplicationHandler supports replicating indexes from a + "master" used for indexing and "slaves" used for queries. + + http://wiki.apache.org/solr/SolrReplication + + It is also necessary for SolrCloud to function (in Cloud mode, the + replication handler is used to bulk transfer segments when nodes + are added or need to recover). + + https://wiki.apache.org/solr/SolrCloud/ + --> + <requestHandler name="/replication" class="solr.ReplicationHandler" > + <!-- + To enable simple master/slave replication, uncomment one of the + sections below, depending on whether this solr instance should be + the "master" or a "slave". If this instance is a "slave" you will + also need to fill in the masterUrl to point to a real machine. + --> + <!-- + <lst name="master"> + <str name="replicateAfter">commit</str> + <str name="replicateAfter">startup</str> + <str name="confFiles">schema.xml,stopwords.txt</str> + </lst> + --> + <!-- + <lst name="slave"> + <str name="masterUrl">http://your-master-hostname:8983/solr</str> + <str name="pollInterval">00:00:60</str> + </lst> + --> + </requestHandler> <!-- Search components are registered to SolrCore and used by Search Handlers @@ -716,56 +1296,284 @@ </arr> </requestHandler> + <!-- Search Components + + Search components are registered to SolrCore and used by + instances of SearchHandler (which can access them by name) + + By default, the following components are available: + + <searchComponent name="query" class="solr.QueryComponent" /> + <searchComponent name="facet" class="solr.FacetComponent" /> + <searchComponent name="mlt" class="solr.MoreLikeThisComponent" /> + <searchComponent name="highlight" class="solr.HighlightComponent" /> + <searchComponent name="stats" class="solr.StatsComponent" /> + <searchComponent name="debug" class="solr.DebugComponent" /> + + Default configuration in a requestHandler would look like: + + <arr name="components"> + <str>query</str> + <str>facet</str> + <str>mlt</str> + <str>highlight</str> + <str>stats</str> + <str>debug</str> + </arr> + + If you register a searchComponent to one of the standard names, + that will be used instead of the default. + + To insert components before or after the 'standard' components, use: + + <arr name="first-components"> + <str>myFirstComponentName</str> + </arr> + + <arr name="last-components"> + <str>myLastComponentName</str> + </arr> + + NOTE: The component registered with the name "debug" will + always be executed after the "last-components" + + --> + + <!-- Spell Check + + The spell check component can return a list of alternative spelling + suggestions. + + http://wiki.apache.org/solr/SpellCheckComponent + --> + <searchComponent name="spellcheck" class="solr.SpellCheckComponent"> + + <str name="queryAnalyzerFieldType">text_general</str> + + <!-- Multiple "Spell Checkers" can be declared and used by this + component + --> + + <!-- a spellchecker built from a field of the main index --> + <lst name="spellchecker"> + <str name="name">default</str> + <str name="field">item.handle</str> + <str name="classname">solr.DirectSolrSpellChecker</str> + <!-- the spellcheck distance measure used, the default is the internal levenshtein --> + <str name="distanceMeasure">internal</str> + <!-- minimum accuracy needed to be considered a valid spellcheck suggestion --> + <float name="accuracy">0.5</float> + <!-- the maximum #edits we consider when enumerating terms: can be 1 or 2 --> + <int name="maxEdits">2</int> + <!-- the minimum shared prefix when enumerating terms --> + <int name="minPrefix">1</int> + <!-- maximum number of inspections per result. --> + <int name="maxInspections">5</int> + <!-- minimum length of a query term to be considered for correction --> + <int name="minQueryLength">4</int> + <!-- maximum threshold of documents a query term can appear to be considered for correction --> + <float name="maxQueryFrequency">0.01</float> + <!-- uncomment this to require suggestions to occur in 1% of the documents + <float name="thresholdTokenFrequency">.01</float> + --> + </lst> + + <!-- a spellchecker that can break or combine words. See "/spell" handler below for usage --> + <lst name="spellchecker"> + <str name="name">wordbreak</str> + <str name="classname">solr.WordBreakSolrSpellChecker</str> + <str name="field">name</str> + <str name="combineWords">true</str> + <str name="breakWords">true</str> + <int name="maxChanges">10</int> + </lst> + + <!-- a spellchecker that uses a different distance measure --> + <!-- + <lst name="spellchecker"> + <str name="name">jarowinkler</str> + <str name="field">spell</str> + <str name="classname">solr.DirectSolrSpellChecker</str> + <str name="distanceMeasure"> + org.apache.lucene.search.spell.JaroWinklerDistance + </str> + </lst> + --> + + <!-- a spellchecker that use an alternate comparator + + comparatorClass be one of: + 1. score (default) + 2. freq (Frequency first, then score) + 3. A fully qualified class name + --> + <!-- + <lst name="spellchecker"> + <str name="name">freq</str> + <str name="field">lowerfilt</str> + <str name="classname">solr.DirectSolrSpellChecker</str> + <str name="comparatorClass">freq</str> + --> + + <!-- A spellchecker that reads the list of words from a file --> + <!-- + <lst name="spellchecker"> + <str name="classname">solr.FileBasedSpellChecker</str> + <str name="name">file</str> + <str name="sourceLocation">spellings.txt</str> + <str name="characterEncoding">UTF-8</str> + <str name="spellcheckIndexDir">spellcheckerFile</str> + </lst> + --> + </searchComponent> + + <!-- A request handler for demonstrating the spellcheck component. + + NOTE: This is purely as an example. The whole purpose of the + SpellCheckComponent is to hook it into the request handler that + handles your normal user queries so that a separate request is + not needed to get suggestions. + + IN OTHER WORDS, THERE IS REALLY GOOD CHANCE THE SETUP BELOW IS + NOT WHAT YOU WANT FOR YOUR PRODUCTION SYSTEM! + + See http://wiki.apache.org/solr/SpellCheckComponent for details + on the request parameters. + --> + <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy"> + <lst name="defaults"> + <str name="df">item.handle</str> + <!-- Solr will use suggestions from both the 'default' spellchecker + and from the 'wordbreak' spellchecker and combine them. + collations (re-written queries) can include a combination of + corrections from both spellcheckers --> + <str name="spellcheck.dictionary">default</str> + <str name="spellcheck.dictionary">wordbreak</str> + <str name="spellcheck">on</str> + <str name="spellcheck.extendedResults">true</str> + <str name="spellcheck.count">10</str> + <str name="spellcheck.alternativeTermCount">5</str> + <str name="spellcheck.maxResultsForSuggest">5</str> + <str name="spellcheck.collate">true</str> + <str name="spellcheck.collateExtendedResults">true</str> + <str name="spellcheck.maxCollationTries">10</str> + <str name="spellcheck.maxCollations">5</str> + </lst> + <arr name="last-components"> + <str>spellcheck</str> + </arr> + </requestHandler> + + <!-- Term Vector Component + + http://wiki.apache.org/solr/TermVectorComponent + --> + <searchComponent name="tvComponent" class="solr.TermVectorComponent"/> + + <!-- A request handler for demonstrating the term vector component + + This is purely as an example. + + In reality you will likely want to add the component to your + already specified request handlers. + --> + <requestHandler name="/tvrh" class="solr.SearchHandler" startup="lazy"> + <lst name="defaults"> + <str name="df">item.handle</str> + <bool name="tv">true</bool> + </lst> + <arr name="last-components"> + <str>tvComponent</str> + </arr> + </requestHandler> + <!-- Clustering Component + http://wiki.apache.org/solr/ClusteringComponent - This relies on third party jars which are not included in the release. - To use this component (and the "/clustering" handler) - Those jars will need to be downloaded, and you'll need to set the - solr.cluster.enabled system property when running solr... - java -Dsolr.clustering.enabled=true -jar start.jar + + You'll need to set the solr.clustering.enabled system property + when running solr to run with clustering enabled: + + java -Dsolr.clustering.enabled=true -jar start.jar + --> - <searchComponent - name="clusteringComponent" - enable="${solr.clustering.enabled:false}" - class="org.apache.solr.handler.clustering.ClusteringComponent" > + <searchComponent name="clustering" + enable="${solr.clustering.enabled:false}" + class="solr.clustering.ClusteringComponent" > <!-- Declare an engine --> <lst name="engine"> <!-- The name, only one can be named "default" --> <str name="name">default</str> - <!-- - Class name of Carrot2 clustering algorithm. Currently available algorithms are: + <!-- Class name of Carrot2 clustering algorithm. + + Currently available algorithms are: + * org.carrot2.clustering.lingo.LingoClusteringAlgorithm * org.carrot2.clustering.stc.STCClusteringAlgorithm - - See http://project.carrot2.org/algorithms.html for the algorithm's characteristics. + * org.carrot2.clustering.kmeans.BisectingKMeansClusteringAlgorithm + + See http://project.carrot2.org/algorithms.html for the + algorithm's characteristics. --> <str name="carrot.algorithm">org.carrot2.clustering.lingo.LingoClusteringAlgorithm</str> - <!-- - Overriding values for Carrot2 default algorithm attributes. For a description - of all available attributes, see: http://download.carrot2.org/stable/manual/#chapter.components. - Use attribute key as name attribute of str elements below. These can be further - overridden for individual requests by specifying attribute key as request - parameter name and attribute value as parameter value. + + <!-- Overriding values for Carrot2 default algorithm attributes. + + For a description of all available attributes, see: + http://download.carrot2.org/stable/manual/#chapter.components. + Use attribute key as name attribute of str elements + below. These can be further overridden for individual + requests by specifying attribute key as request parameter + name and attribute value as parameter value. --> <str name="LingoClusteringAlgorithm.desiredClusterCountBase">20</str> + + <!-- Location of Carrot2 lexical resources. + + A directory from which to load Carrot2-specific stop words + and stop labels. Absolute or relative to Solr config directory. + If a specific resource (e.g. stopwords.en) is present in the + specified dir, it will completely override the corresponding + default one that ships with Carrot2. + + For an overview of Carrot2 lexical resources, see: + http://download.carrot2.org/head/manual/#chapter.lexical-resources + --> + <str name="carrot.lexicalResourcesDir">clustering/carrot2</str> + + <!-- The language to assume for the documents. + + For a list of allowed values, see: + http://download.carrot2.org/stable/manual/#section.attribute.lingo.MultilingualClustering.defaultLanguage + --> + <str name="MultilingualClustering.defaultLanguage">ENGLISH</str> </lst> <lst name="engine"> <str name="name">stc</str> <str name="carrot.algorithm">org.carrot2.clustering.stc.STCClusteringAlgorithm</str> </lst> </searchComponent> + + <!-- A request handler for demonstrating the clustering component + + This is purely as an example. + + In reality you will likely want to add the component to your + already specified request handlers. + --> <requestHandler name="/clustering" + startup="lazy" enable="${solr.clustering.enabled:false}" class="solr.SearchHandler"> - <lst name="defaults"> - <bool name="clustering">true</bool> - <str name="clustering.engine">default</str> - <bool name="clustering.results">true</bool> - <!-- The title field --> - <str name="carrot.title">name</str> - <str name="carrot.url">id</str> - <!-- The field to cluster on --> + <lst name="defaults"> + <bool name="clustering">true</bool> + <str name="clustering.engine">default</str> + <bool name="clustering.results">true</bool> + <!-- The title field --> + <str name="carrot.title">name</str> + <str name="carrot.url">id</str> + <!-- The field to cluster on --> <str name="carrot.snippet">features</str> <!-- produce summaries --> <bool name="carrot.produceSummary">true</bool> @@ -773,265 +1581,347 @@ <!--<int name="carrot.numDescriptions">5</int>--> <!-- produce sub clusters --> <bool name="carrot.outputSubClusters">false</bool> - </lst> + + <str name="defType">edismax</str> + <str name="qf"> + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + </str> + <str name="q.alt">*:*</str> + <str name="rows">10</str> + <str name="fl">*,score</str> + </lst> <arr name="last-components"> - <str>clusteringComponent</str> + <str>clustering</str> </arr> </requestHandler> + + <!-- Terms Component - <!-- Solr Cell: http://wiki.apache.org/solr/ExtractingRequestHandler --> - <requestHandler name="/update/extract" class="org.apache.solr.handler.extraction.ExtractingRequestHandler" startup="lazy"> - <lst name="defaults"> - <!-- All the main content goes into "text"... if you need to return - the extracted text or do highlighting, use a stored field. --> - <str name="fmap.content">text</str> - <str name="lowernames">true</str> - <str name="uprefix">ignored_</str> + http://wiki.apache.org/solr/TermsComponent - <!-- capture link hrefs but ignore div attributes --> - <str name="captureAttr">true</str> - <str name="fmap.a">links</str> - <str name="fmap.div">ignored_</str> - </lst> - </requestHandler> - - - <!-- A component to return terms and document frequency of those terms. - This component does not yet support distributed search. --> - <searchComponent name="termsComponent" class="org.apache.solr.handler.component.TermsComponent"/> + A component to return terms and document frequency of those + terms + --> + <searchComponent name="terms" class="solr.TermsComponent"/> - <requestHandler name="/terms" class="org.apache.solr.handler.component.SearchHandler"> + <!-- A request handler for demonstrating the terms component --> + <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy"> <lst name="defaults"> <bool name="terms">true</bool> - </lst> + <bool name="distrib">false</bool> + </lst> <arr name="components"> - <str>termsComponent</str> + <str>terms</str> </arr> </requestHandler> - <!-- a search component that enables you to configure the top results for - a given query regardless of the normal lucene scoring.--> + <!-- Query Elevation Component + + http://wiki.apache.org/solr/QueryElevationComponent + + a search component that enables you to configure the top + results for a given query regardless of the normal lucene + scoring. + --> <searchComponent name="elevator" class="solr.QueryElevationComponent" > <!-- pick a fieldType to analyze queries --> <str name="queryFieldType">string</str> <str name="config-file">elevate.xml</str> </searchComponent> - <!-- a request handler utilizing the elevator component --> + <!-- A request handler for demonstrating the elevator component --> <requestHandler name="/elevate" class="solr.SearchHandler" startup="lazy"> <lst name="defaults"> <str name="echoParams">explicit</str> + <str name="df">item.handle</str> </lst> <arr name="last-components"> <str>elevator</str> </arr> </requestHandler> + <!-- Highlighting Component - <!-- Update request handler. - - Note: Since solr1.1 requestHandlers requires a valid content type header if posted in - the body. For example, curl now requires: -H 'Content-type:text/xml; charset=utf-8' - The response format differs from solr1.1 formatting and returns a standard error code. - To enable solr1.1 behavior, remove the /update handler or change its path + http://wiki.apache.org/solr/HighlightingParameters --> - <requestHandler name="/update" class="solr.XmlUpdateRequestHandler" /> - - - <requestHandler name="/update/javabin" class="solr.BinaryUpdateRequestHandler" /> - - <!-- - Analysis request handler. Since Solr 1.3. Use to return how a document is analyzed. Useful - for debugging and as a token server for other types of applications. - - This is deprecated in favor of the improved DocumentAnalysisRequestHandler and FieldAnalysisRequestHandler - - <requestHandler name="/analysis" class="solr.AnalysisRequestHandler" /> - --> - - <!-- - An analysis handler that provides a breakdown of the analysis process of provided docuemnts. This handler expects a - (single) content stream with the following format: - - <docs> - <doc> - <field name="id">1</field> - <field name="name">The Name</field> - <field name="text">The Text Value</field> - <doc> - <doc>...</doc> - <doc>...</doc> - ... - </docs> - - Note: Each document must contain a field which serves as the unique key. This key is used in the returned - response to assoicate an analysis breakdown to the analyzed document. - - Like the FieldAnalysisRequestHandler, this handler also supports query analysis by - sending either an "analysis.query" or "q" request paraemter that holds the query text to be analyized. It also - supports the "analysis.showmatch" parameter which when set to true, all field tokens that match the query - tokens will be marked as a "match". - --> - <requestHandler name="/analysis/document" class="solr.DocumentAnalysisRequestHandler" /> + <searchComponent class="solr.HighlightComponent" name="highlight"> + <highlighting> + <!-- Configure the standard fragmenter --> + <!-- This could most likely be commented out in the "default" case --> + <fragmenter name="gap" + default="true" + class="solr.highlight.GapFragmenter"> + <lst name="defaults"> + <int name="hl.fragsize">100</int> + </lst> + </fragmenter> + + <!-- A regular-expression-based fragmenter + (for sentence extraction) + --> + <fragmenter name="regex" + class="solr.highlight.RegexFragmenter"> + <lst name="defaults"> + <!-- slightly smaller fragsizes work better because of slop --> + <int name="hl.fragsize">70</int> + <!-- allow 50% slop on fragment sizes --> + <float name="hl.regex.slop">0.5</float> + <!-- a basic sentence pattern --> + <str name="hl.regex.pattern">[-\w ,/\n\"']{20,200}</str> + </lst> + </fragmenter> + + <!-- Configure the standard formatter --> + <formatter name="html" + default="true" + class="solr.highlight.HtmlFormatter"> + <lst name="defaults"> + <str name="hl.simple.pre"><![CDATA[<em>]]></str> + <str name="hl.simple.post"><![CDATA[</em>]]></str> + </lst> + </formatter> + + <!-- Configure the standard encoder --> + <encoder name="html" + class="solr.highlight.HtmlEncoder" /> + + <!-- Configure the standard fragListBuilder --> + <fragListBuilder name="simple" + class="solr.highlight.SimpleFragListBuilder"/> + + <!-- Configure the single fragListBuilder --> + <fragListBuilder name="single" + class="solr.highlight.SingleFragListBuilder"/> + + <!-- Configure the weighted fragListBuilder --> + <fragListBuilder name="weighted" + default="true" + class="solr.highlight.WeightedFragListBuilder"/> + + <!-- default tag FragmentsBuilder --> + <fragmentsBuilder name="default" + default="true" + class="solr.highlight.ScoreOrderFragmentsBuilder"> + <!-- + <lst name="defaults"> + <str name="hl.multiValuedSeparatorChar">/</str> + </lst> + --> + </fragmentsBuilder> + + <!-- multi-colored tag FragmentsBuilder --> + <fragmentsBuilder name="colored" + class="solr.highlight.ScoreOrderFragmentsBuilder"> + <lst name="defaults"> + <str name="hl.tag.pre"><![CDATA[ + <b style="background:yellow">,<b style="background:lawgreen">, + <b style="background:aquamarine">,<b style="background:magenta">, + <b style="background:palegreen">,<b style="background:coral">, + <b style="background:wheat">,<b style="background:khaki">, + <b style="background:lime">,<b style="background:deepskyblue">]]></str> + <str name="hl.tag.post"><![CDATA[</b>]]></str> + </lst> + </fragmentsBuilder> + + <boundaryScanner name="default" + default="true" + class="solr.highlight.SimpleBoundaryScanner"> + <lst name="defaults"> + <str name="hl.bs.maxScan">10</str> + <str name="hl.bs.chars">.,!? 	 </str> + </lst> + </boundaryScanner> + + <boundaryScanner name="breakIterator" + class="solr.highlight.BreakIteratorBoundaryScanner"> + <lst name="defaults"> + <!-- type should be one of CHARACTER, WORD(default), LINE and SENTENCE --> + <str name="hl.bs.type">WORD</str> + <!-- language and country are used when constructing Locale object. --> + <!-- And the Locale object will be used when getting instance of BreakIterator --> + <str name="hl.bs.language">en</str> + <str name="hl.bs.country">US</str> + </lst> + </boundaryScanner> + </highlighting> + </searchComponent> - <!-- - RequestHandler that provides much the same functionality as analysis.jsp. Provides the ability - to specify multiple field types and field names in the same request and outputs index-time and - query-time analysis for each of them. - - Request parameters are: - analysis.fieldname - The field name whose analyzers are to be used - analysis.fieldtype - The field type whose analyzers are to be used - analysis.fieldvalue - The text for index-time analysis - q (or analysis.q) - The text for query time analysis - analysis.showmatch (true|false) - When set to true and when query analysis is performed, the produced - tokens of the field value analysis will be marked as "matched" for every - token that is produces by the query analysis - --> - <requestHandler name="/analysis/field" class="solr.FieldAnalysisRequestHandler" /> + <!-- Update Processors + Chains of Update Processor Factories for dealing with Update + Requests can be declared, and then used by name in Update + Request Processors - <!-- CSV update handler, loaded on demand --> - <requestHandler name="/update/csv" class="solr.CSVRequestHandler" startup="lazy" /> + http://wiki.apache.org/solr/UpdateRequestProcessor + --> + <!-- Deduplication + An example dedup update processor that creates the "id" field + on the fly based on the hash code of some other fields. This + example has overwriteDupes set to false since we are using the + id field as the signatureField and Solr will maintain + uniqueness based on that anyway. + + --> <!-- - Admin Handlers - This will register all the standard admin RequestHandlers. Adding - this single handler is equivalent to registering: - - <requestHandler name="/admin/luke" class="org.apache.solr.handler.admin.LukeRequestHandler" /> - <requestHandler name="/admin/system" class="org.apache.solr.handler.admin.SystemInfoHandler" /> - <requestHandler name="/admin/plugins" class="org.apache.solr.handler.admin.PluginInfoHandler" /> - <requestHandler name="/admin/threads" class="org.apache.solr.handler.admin.ThreadDumpHandler" /> - <requestHandler name="/admin/properties" class="org.apache.solr.handler.admin.PropertiesRequestHandler" /> - <requestHandler name="/admin/file" class="org.apache.solr.handler.admin.ShowFileRequestHandler" > - - If you wish to hide files under ${solr.home}/conf, explicitly register the ShowFileRequestHandler using: - <requestHandler name="/admin/file" class="org.apache.solr.handler.admin.ShowFileRequestHandler" > - <lst name="invariants"> - <str name="hidden">synonyms.txt</str> - <str name="hidden">anotherfile.txt</str> - </lst> - </requestHandler> - --> - <requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" /> - - <!-- ping/healthcheck --> - <requestHandler name="/admin/ping" class="PingRequestHandler"> - <lst name="defaults"> - <str name="qt">standard</str> - <str name="q">solrpingquery</str> - <str name="echoParams">all</str> - </lst> - </requestHandler> - - <!-- Echo the request contents back to the client --> - <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" > - <lst name="defaults"> - <str name="echoParams">explicit</str> <!-- for all params (including the default etc) use: 'all' --> - <str name="echoHandler">true</str> - </lst> - </requestHandler> + <updateRequestProcessorChain name="dedupe"> + <processor class="solr.processor.SignatureUpdateProcessorFactory"> + <bool name="enabled">true</bool> + <str name="signatureField">id</str> + <bool name="overwriteDupes">false</bool> + <str name="fields">name,features,cat</str> + <str name="signatureClass">solr.processor.Lookup3Signature</str> + </processor> + <processor class="solr.LogUpdateProcessorFactory" /> + <processor class="solr.RunUpdateProcessorFactory" /> + </updateRequestProcessorChain> + --> + + <!-- Language identification + + This example update chain identifies the language of the incoming + documents using the langid contrib. The detected language is + written to field language_s. No field name mapping is done. + The fields used for detection are text, title, subject and description, + making this example suitable for detecting languages form full-text + rich documents injected via ExtractingRequestHandler. + See more about langId at http://wiki.apache.org/solr/LanguageDetection + --> + <!-- + <updateRequestProcessorChain name="langid"> + <processor class="org.apache.solr.update.processor.TikaLanguageIdentifierUpdateProcessorFactory"> + <str name="langid.fl">text,title,subject,description</str> + <str name="langid.langField">language_s</str> + <str name="langid.fallback">en</str> + </processor> + <processor class="solr.LogUpdateProcessorFactory" /> + <processor class="solr.RunUpdateProcessorFactory" /> + </updateRequestProcessorChain> + --> - <highlighting> - <!-- Configure the standard fragmenter --> - <!-- This could most likely be commented out in the "default" case --> - <fragmenter name="gap" class="org.apache.solr.highlight.GapFragmenter" default="true"> - <lst name="defaults"> - <int name="hl.fragsize">100</int> - </lst> - </fragmenter> + <!-- Script update processor - <!-- A regular-expression-based fragmenter (f.i., for sentence extraction) --> - <fragmenter name="regex" class="org.apache.solr.highlight.RegexFragmenter"> - <lst name="defaults"> - <!-- slightly smaller fragsizes work better because of slop --> - <int name="hl.fragsize">70</int> - <!-- allow 50% slop on fragment sizes --> - <float name="hl.regex.slop">0.5</float> - <!-- a basic sentence pattern --> - <str name="hl.regex.pattern">[-\w ,/\n\"']{20,200}</str> - </lst> - </fragmenter> + This example hooks in an update processor implemented using JavaScript. - <!-- Configure the standard formatter --> - <formatter name="html" class="org.apache.solr.highlight.HtmlFormatter" default="true"> - <lst name="defaults"> - <str name="hl.simple.pre"><![CDATA[<em>]]></str> - <str name="hl.simple.post"><![CDATA[</em>]]></str> - </lst> - </formatter> - </highlighting> - - <!-- An example dedup update processor that creates the "id" field on the fly - based on the hash code of some other fields. This example has overwriteDupes - set to false since we are using the id field as the signatureField and Solr - will maintain uniqueness based on that anyway. - - You have to link the chain to an update handler above to use it ie: - <requestHandler name="/update "class="solr.XmlUpdateRequestHandler"> - <lst name="defaults"> - <str name="update.processor">dedupe</str> - </lst> - </requestHandler> + See more about the script update processor at http://wiki.apache.org/solr/ScriptUpdateProcessor --> <!-- - <updateRequestProcessorChain name="dedupe"> - <processor class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory"> - <bool name="enabled">true</bool> - <str name="signatureField">id</str> - <bool name="overwriteDupes">false</bool> - <str name="fields">name,features,cat</str> - <str name="signatureClass">org.apache.solr.update.processor.Lookup3Signature</str> - </processor> - <processor class="solr.LogUpdateProcessorFactory" /> - <processor class="solr.RunUpdateProcessorFactory" /> - </updateRequestProcessorChain> + <updateRequestProcessorChain name="script"> + <processor class="solr.StatelessScriptUpdateProcessorFactory"> + <str name="script">update-script.js</str> + <lst name="params"> + <str name="config_param">example config parameter</str> + </lst> + </processor> + <processor class="solr.RunUpdateProcessorFactory" /> + </updateRequestProcessorChain> --> + + <!-- Response Writers + http://wiki.apache.org/solr/QueryResponseWriter - <!-- queryResponseWriter plugins... query responses will be written using the - writer specified by the 'wt' request parameter matching the name of a registered - writer. - The "default" writer is the default and will be used if 'wt' is not specified - in the request. XMLResponseWriter will be used if nothing is specified here. - The json, python, and ruby writers are also available by default. + Request responses will be written using the writer specified by + the 'wt' request parameter matching the name of a registered + writer. - <queryResponseWriter name="xml" class="org.apache.solr.request.XMLResponseWriter" default="true"/> - <queryResponseWriter name="json" class="org.apache.solr.request.JSONResponseWriter"/> - <queryResponseWriter name="python" class="org.apache.solr.request.PythonResponseWriter"/> - <queryResponseWriter name="ruby" class="org.apache.solr.request.RubyResponseWriter"/> - <queryResponseWriter name="php" class="org.apache.solr.request.PHPResponseWriter"/> - <queryResponseWriter name="phps" class="org.apache.solr.request.PHPSerializedResponseWriter"/> + The "default" writer is the default and will be used if 'wt' is + not specified in the request. + --> + <!-- The following response writers are implicitly configured unless + overridden... + --> + <!-- + <queryResponseWriter name="xml" + default="true" + class="solr.XMLResponseWriter" /> + <queryResponseWriter name="json" class="solr.JSONResponseWriter"/> + <queryResponseWriter name="python" class="solr.PythonResponseWriter"/> + <queryResponseWriter name="ruby" class="solr.RubyResponseWriter"/> + <queryResponseWriter name="php" class="solr.PHPResponseWriter"/> + <queryResponseWriter name="phps" class="solr.PHPSerializedResponseWriter"/> + <queryResponseWriter name="csv" class="solr.CSVResponseWriter"/> + <queryResponseWriter name="schema.xml" class="solr.SchemaXmlResponseWriter"/> + --> - <queryResponseWriter name="custom" class="com.example.MyResponseWriter"/> - --> + <queryResponseWriter name="json" class="solr.JSONResponseWriter"> + <!-- For the purposes of the tutorial, JSON responses are written as + plain text so that they are easy to read in *any* browser. + If you expect a MIME type of "application/json" just remove this override. + --> + <str name="content-type">text/plain; charset=UTF-8</str> + </queryResponseWriter> + + <!-- + Custom response writers can be declared as needed... + --> + <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy"/> + <!-- XSLT response writer transforms the XML output by any xslt file found in Solr's conf/xslt directory. Changes to xslt files are checked for - every xsltCacheLifetimeSeconds. - --> - <queryResponseWriter name="xslt" class="org.apache.solr.request.XSLTResponseWriter"> + every xsltCacheLifetimeSeconds. + --> + <queryResponseWriter name="xslt" class="solr.XSLTResponseWriter"> <int name="xsltCacheLifetimeSeconds">5</int> </queryResponseWriter> + <!-- Query Parsers - <!-- example of registering a query parser - <queryParser name="lucene" class="org.apache.solr.search.LuceneQParserPlugin"/> - --> + http://wiki.apache.org/solr/SolrQuerySyntax - <!-- example of registering a custom function parser - <valueSourceParser name="myfunc" class="com.mycompany.MyValueSourceParser" /> - --> + Multiple QParserPlugins can be registered by name, and then + used in either the "defType" param for the QueryComponent (used + by SearchHandler) or in LocalParams + --> + <!-- example of registering a query parser --> + <!-- + <queryParser name="myparser" class="com.mycompany.MyQParserPlugin"/> + --> - <!-- config for the admin interface --> - <admin> - <defaultQuery>solr</defaultQuery> + <!-- Function Parsers - <!-- configure a healthcheck file for servers behind a loadbalancer - <healthcheck type="file">server-enabled</healthcheck> + http://wiki.apache.org/solr/FunctionQuery + + Multiple ValueSourceParsers can be registered by name, and then + used as function names when using the "func" QParser. --> - </admin> + <!-- example of registering a custom function parser --> + <!-- + <valueSourceParser name="myfunc" + class="com.mycompany.MyValueSourceParser" /> + --> + + + <!-- Document Transformers + http://wiki.apache.org/solr/DocTransformers + --> + <!-- + Could be something like: + <transformer name="db" class="com.mycompany.LoadFromDatabaseTransformer" > + <int name="connection">jdbc://....</int> + </transformer> + + To add a constant value to all docs, use: + <transformer name="mytrans2" class="org.apache.solr.response.transform.ValueAugmenterFactory" > + <int name="value">5</int> + </transformer> + + If you want the user to still be able to change it with _value:something_ use this: + <transformer name="mytrans3" class="org.apache.solr.response.transform.ValueAugmenterFactory" > + <double name="defaultValue">5</double> + </transformer> + + If you are using the QueryElevationComponent, you may wish to mark documents that get boosted. The + EditorialMarkerFactory will do exactly that: + <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" /> + --> + -</config> + <!-- Legacy config for the admin interface --> + <admin> + <defaultQuery>*:*</defaultQuery> + </admin> +</config> \ No newline at end of file diff --git a/dspace/solr/search/conf/schema.xml b/dspace/solr/search/conf/schema.xml index e1d4ac179b0489247893178f60eae362721cd636..6c66d00ba9e6acdb6ba985d8868510e8f3f6cf92 100644 --- a/dspace/solr/search/conf/schema.xml +++ b/dspace/solr/search/conf/schema.xml @@ -45,7 +45,7 @@ that avoids logging every request --> -<schema name="example" version="1.4"> +<schema name="example" version="1.5"> <!-- attribute "name" is the name of this schema and is only used for display purposes. Applications should change this to reflect the nature of the search collection. version="1.4" is Solr's version number for the schema syntax and semantics. It should @@ -55,6 +55,7 @@ 1.2: omitTermFreqAndPositions attribute introduced, true by default except for text fields. 1.3: removed optional field compress feature 1.4: default auto-phrase (QueryParser feature) to off + 1.5: omitNorms defaults to true for primitive field types (int, float, boolean, string...) --> <types> @@ -221,7 +222,7 @@ Duplicate tokens at the same position (which may result from Stemmed Synonyms or WordDelim parts) are removed. --> - <fieldType name="text" class="solr.TextField" positionIncrementGap="100"> + <fieldType name="text" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="solr.WhitespaceTokenizerFactory"/> <!-- in this example, we will only use synonyms at query time @@ -237,8 +238,8 @@ enablePositionIncrements="true" /> <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/> - <filter class="solr.LowerCaseFilterFactory"/> - <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/> + <filter class="solr.ICUFoldingFilterFactory"/> + <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> </analyzer> <analyzer type="query"> @@ -250,13 +251,12 @@ enablePositionIncrements="true" /> <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/> - <filter class="solr.LowerCaseFilterFactory"/> - <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/> + <filter class="solr.ICUFoldingFilterFactory"/> + <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> </analyzer> </fieldType> - <!-- Less flexible matching, but less false matches. Probably not ideal for product names, but may be good for SKUs. Can insert dashes in the wrong place and still match. --> <fieldType name="textTight" class="solr.TextField" positionIncrementGap="100" > @@ -266,7 +266,7 @@ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/> <filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/> <filter class="solr.LowerCaseFilterFactory"/> - <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/> + <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> <!-- this filter can remove any duplicate tokens that appear at the same position - sometimes possible with WordDelimiterFilter in conjuncton with stemming. --> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> @@ -455,10 +455,37 @@ <filter class="solr.TrimFilterFactory" /> </analyzer> </fieldType> + + <!-- + SpellCheck analysis config based off of http://wiki.apache.org/solr/ + SpellCheckingAnalysis + --> + <fieldType name="textSpell" class="solr.TextField" + positionIncrementGap="100" stored="false" multiValued="true"> + <analyzer type="index"> + <tokenizer class="solr.StandardTokenizerFactory"/> + <filter class="solr.LowerCaseFilterFactory"/> + <filter class="solr.SynonymFilterFactory" + synonyms="synonyms.txt" ignoreCase="true" + expand="true"/> + <filter class="solr.StopFilterFactory" ignoreCase="true" + words="stopwords.txt"/> + <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> + </analyzer> + <analyzer type="query"> + <tokenizer class="solr.StandardTokenizerFactory"/> + <filter class="solr.LowerCaseFilterFactory"/> + <filter class="solr.StopFilterFactory" ignoreCase="true" + words="stopwords.txt"/> + <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> +  </analyzer> + </fieldType> </types> <fields> + + <field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/> <!-- Valid attributes for fields: name: mandatory - the name for the field type: mandatory - the name of a previously defined type from the @@ -487,7 +514,7 @@ <!-- catchall field, containing all other searchable text fields (implemented via copyField further on in this schema --> - <field name="text" type="text" indexed="true" stored="false" multiValued="true"/> + <field name="search_text" type="text" indexed="true" stored="false" multiValued="true"/> <field name="fulltext" type="text" indexed="true" stored="true" multiValued="true"/> @@ -515,6 +542,9 @@ <field name="location.comm" type="lowerCaseSort" indexed="true" stored="true" multiValued="true" required="false" omitNorms="true" /> <field name="location.coll" type="lowerCaseSort" indexed="true" stored="true" multiValued="true" required="false" omitNorms="true" /> + <field name="a_spell" type="textSpell" /> + <copyField source="fulltext" dest="a_spell" /> + <!-- used by the DSpace Discovery Solr Indexer to track the last time a document was indexed --> <field name="SolrIndexer.lastIndexed" type="date" indexed="true" stored="true" default="NOW" multiValued="false" omitNorms="true" /> @@ -597,7 +627,7 @@ <uniqueKey>search.uniqueid</uniqueKey> <!-- field for the QueryParser to use when an explicit fieldname is absent --> - <defaultSearchField>text</defaultSearchField> + <defaultSearchField>search_text</defaultSearchField> <!-- SolrQueryParser configuration: defaultOperator="AND|OR" --> <solrQueryParser defaultOperator="OR"/> @@ -606,7 +636,7 @@ is added to the index. It's used either to index the same field differently, or to add multiple fields to the same field for easier/faster searching. --> - <copyField source="*" dest="text"/> + <copyField source="*" dest="search_text"/> <!-- Above, multiple source fields are copied to the [text] field. Another way to map multiple source fields to the same diff --git a/dspace/solr/search/conf/solrconfig.xml b/dspace/solr/search/conf/solrconfig.xml index d203e19b199ee6c7a88dfef12c47139e0bd321bf..157ea6956f6b92b6f5fa319234ad65504733415a 100644 --- a/dspace/solr/search/conf/solrconfig.xml +++ b/dspace/solr/search/conf/solrconfig.xml @@ -15,257 +15,316 @@ See the License for the specific language governing permissions and limitations under the License. --> -<!-- - For more details about configurations options that may appear in this - file, see http://wiki.apache.org/solr/SolrConfigXml. - Specifically, the Solr Config can support XInclude, which may make it easier to manage - the configuration. See https://issues.apache.org/jira/browse/SOLR-1167 +<!-- + For more details about configurations options that may appear in + this file, see http://wiki.apache.org/solr/SolrConfigXml. --> <config> - <!-- Set this to 'false' if you want solr to continue working after it has - encountered an severe configuration error. In a production environment, - you may want solr to keep working even if one handler is mis-configured. - - You may also set this to false using by setting the system property: - -Dsolr.abortOnConfigurationError=false - --> - <abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError> + <!-- In all configuration below, a prefix of "solr." for class names + is an alias that causes solr to search appropriate packages, + including org.apache.solr.(search|update|request|core|analysis) + You may also specify a fully qualified Java classname if you + have your own custom plugins. + --> - <!-- Controls what version of Lucene various components of Solr + <!-- Controls what version of Lucene various components of Solr adhere to. Generally, you want to use the latest version to get all bug fixes and improvements. It is highly recommended that you fully re-index after changing this setting as it can affect both how text is indexed and queried. + --> + <luceneMatchVersion>4.4</luceneMatchVersion> + + <!-- <lib/> directives can be used to instruct Solr to load an Jars + identified and use them to resolve any "plugins" specified in + your solrconfig.xml or schema.xml (ie: Analyzers, Request + Handlers, etc...). + + All directories and paths are resolved relative to the + instanceDir. + + Please note that <lib/> directives are processed in the order + that they appear in your solrconfig.xml file, and are "stacked" + on top of each other when building a ClassLoader - so if you have + plugin jars with dependencies on other jars, the "lower level" + dependency jars should be loaded first. + + If a "./lib" directory exists in your instanceDir, all files + found in it are included as if you had used the following + syntax... + + <lib dir="./lib" /> --> - <luceneMatchVersion>LUCENE_35</luceneMatchVersion> - <!-- lib directives can be used to instruct Solr to load an Jars identified - and use them to resolve any "plugins" specified in your solrconfig.xml or - schema.xml (ie: Analyzers, Request Handlers, etc...). + <!-- A 'dir' option by itself adds any files found in the directory + to the classpath, this is useful for including all jars in a + directory. - All directories and paths are resolved relative the instanceDir. + When a 'regex' is specified in addition to a 'dir', only the + files in that directory which completely match the regex + (anchored on both ends) will be included. - If a "./lib" directory exists in your instanceDir, all files found in it - are included as if you had used the following syntax... + If a 'dir' option (with or without a regex) is used and nothing + is found that matches, a warning will be logged. - <lib dir="./lib" /> - --> - <!-- A dir option by itself adds any files found in the directory to the - classpath, this is useful for including all jars in a directory. + The examples below can be used to load some solr-contribs along + with their external dependencies. --> - <lib dir="../../contrib/extraction/lib" /> - <lib dir="../../contrib/clustering/lib/" /> - <lib dir="../../contrib/velocity/lib" /> + <lib dir="../../../contrib/extraction/lib" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-cell-\d.*\.jar" /> - <!-- When a regex is specified in addition to a directory, only the - files in that directory which completely match the regex - (anchored on both ends) will be included. - --> - <lib dir="../../dist/" regex="apache-solr-cell-\d.*\.jar" /> - <lib dir="../../dist/" regex="apache-solr-clustering-\d.*\.jar" /> - <lib dir="../../dist/" regex="apache-solr-dataimporthandler-\d.*\.jar" /> - <lib dir="../../dist/" regex="apache-solr-langid-\d.*\.jar" /> - <lib dir="../../dist/" regex="apache-solr-velocity-\d.*\.jar" /> - - <!-- If a dir option (with or without a regex) is used and nothing - is found that matches, it will be ignored + <lib dir="../../../contrib/clustering/lib/" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-clustering-\d.*\.jar" /> + + <lib dir="../../../contrib/langid/lib/" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-langid-\d.*\.jar" /> + + <lib dir="../../../contrib/velocity/lib" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-velocity-\d.*\.jar" /> + + <!-- an exact 'path' can be used instead of a 'dir' to specify a + specific jar file. This will cause a serious error to be logged + if it can't be loaded. --> - <lib dir="../../contrib/clustering/lib/downloads/" /> - <lib dir="../../contrib/clustering/lib/" /> - <lib dir="/total/crap/dir/ignored" /> - <!-- an exact path can be used to specify a specific file. This will cause - a serious error to be logged if it can't be loaded. - <lib path="../a-jar-that-does-not-exist.jar" /> + <!-- + <lib path="../a-jar-that-does-not-exist.jar" /> --> + + <!-- Data Directory - - <!-- Used to specify an alternate directory to hold all index data - other than the default ./data under the Solr home. - If replication is in use, this should match the replication configuration. --> - <!--<dataDir>${solr.data.dir:./solr/data}</dataDir>--> + Used to specify an alternate directory to hold all index data + other than the default ./data under the Solr home. If + replication is in use, this should match the replication + configuration. + --> + <dataDir>${solr.data.dir:}</dataDir> <!-- The DirectoryFactory to use for indexes. - - solr.StandardDirectoryFactory, the default, is filesystem + + solr.StandardDirectoryFactory is filesystem based and tries to pick the best implementation for the current - JVM and platform. One can force a particular implementation - via solr.MMapDirectoryFactory, solr.NIOFSDirectoryFactory, or - solr.SimpleFSDirectoryFactory. + JVM and platform. solr.NRTCachingDirectoryFactory, the default, + wraps solr.StandardDirectoryFactory and caches small files in memory + for better NRT performance. + + One can force a particular implementation via solr.MMapDirectoryFactory, + solr.NIOFSDirectoryFactory, or solr.SimpleFSDirectoryFactory. solr.RAMDirectoryFactory is memory based, not persistent, and doesn't work with replication. --> - <directoryFactory name="DirectoryFactory" - class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/> - - - <!-- Index Defaults - - Values here affect all index writers and act as a default - unless overridden. - - WARNING: See also the <mainIndex> section below for parameters - that overfor Solr's main Lucene index. + <directoryFactory name="DirectoryFactory" + class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/> + + <!-- The CodecFactory for defining the format of the inverted index. + The default implementation is SchemaCodecFactory, which is the official Lucene + index format, but hooks into the schema to provide per-field customization of + the postings lists and per-document values in the fieldType element + (postingsFormat/docValuesFormat). Note that most of the alternative implementations + are experimental, so if you choose to customize the index format, its a good + idea to convert back to the official format e.g. via IndexWriter.addIndexes(IndexReader) + before upgrading to a newer version to avoid unnecessary reindexing. + --> + <codecFactory class="solr.SchemaCodecFactory"/> + + <!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>: + + <schemaFactory class="ManagedIndexSchemaFactory"> + <bool name="mutable">true</bool> + <str name="managedSchemaResourceName">managed-schema</str> + </schemaFactory> + + When ManagedIndexSchemaFactory is specified, Solr will load the schema from + he resource named in 'managedSchemaResourceName', rather than from schema.xml. + Note that the managed schema resource CANNOT be named schema.xml. If the managed + schema does not exist, Solr will create it after reading schema.xml, then rename + 'schema.xml' to 'schema.xml.bak'. + + Do NOT hand edit the managed schema - external modifications will be ignored and + overwritten as a result of schema modification REST API calls. + + When ManagedIndexSchemaFactory is specified with mutable = true, schema + modification REST API calls will be allowed; otherwise, error responses will be + sent back for these requests. + --> + <schemaFactory class="ClassicIndexSchemaFactory"/> + + <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Index Config - These settings control low-level behavior of indexing + Most example settings here show the default value, but are commented + out, to more easily see where customizations have been made. + + Note: This replaces <indexDefaults> and <mainIndex> from older versions + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> + <indexConfig> + <!-- maxFieldLength was removed in 4.0. To get similar behavior, include a + LimitTokenCountFilterFactory in your fieldType definition. E.g. + <filter class="solr.LimitTokenCountFilterFactory" maxTokenCount="10000"/> --> - <indexDefaults> - <!-- Values here affect all index writers and act as a default unless overridden. --> - <useCompoundFile>false</useCompoundFile> - - <mergeFactor>10</mergeFactor> - <!-- If both ramBufferSizeMB and maxBufferedDocs is set, then Lucene will flush - based on whichever limit is hit first. --> - <!--<maxBufferedDocs>1000</maxBufferedDocs>--> - - <!-- Sets the amount of RAM that may be used by Lucene indexing - for buffering added documents and deletions before they are - flushed to the Directory. --> - <ramBufferSizeMB>32</ramBufferSizeMB> - <!-- If both ramBufferSizeMB and maxBufferedDocs is set, then + <!-- Maximum time to wait for a write lock (ms) for an IndexWriter. Default: 1000 --> + <!-- <writeLockTimeout>1000</writeLockTimeout> --> + + <!-- The maximum number of simultaneous threads that may be + indexing documents at once in IndexWriter; if more than this + many threads arrive they will wait for others to finish. + Default in Solr/Lucene is 8. --> + <!-- <maxIndexingThreads>8</maxIndexingThreads> --> + + <!-- Expert: Enabling compound file will use less files for the index, + using fewer file descriptors on the expense of performance decrease. + Default in Lucene is "true". Default in Solr is "false" (since 3.6) --> + <!-- <useCompoundFile>false</useCompoundFile> --> + + <!-- ramBufferSizeMB sets the amount of RAM that may be used by Lucene + indexing for buffering added documents and deletions before they are + flushed to the Directory. + maxBufferedDocs sets a limit on the number of documents buffered + before flushing. + If both ramBufferSizeMB and maxBufferedDocs is set, then Lucene will flush based on whichever limit is hit first. + The default is 100 MB. --> + <ramBufferSizeMB>32</ramBufferSizeMB> + <maxBufferedDocs>1000</maxBufferedDocs> + + <!-- Expert: Merge Policy + The Merge Policy in Lucene controls how merging of segments is done. + The default since Solr/Lucene 3.3 is TieredMergePolicy. + The default since Lucene 2.3 was the LogByteSizeMergePolicy, + Even older versions of Lucene used LogDocMergePolicy. --> - <!-- <maxBufferedDocs>1000</maxBufferedDocs> --> - - <maxFieldLength>10000</maxFieldLength> - <writeLockTimeout>1000</writeLockTimeout> - <commitLockTimeout>10000</commitLockTimeout> - - <!-- Expert: Merge Policy - - The Merge Policy in Lucene controls how merging is handled by - Lucene. The default in Solr 3.3 is TieredMergePolicy. - - The default in 2.3 was the LogByteSizeMergePolicy, - previous versions used LogDocMergePolicy. - - LogByteSizeMergePolicy chooses segments to merge based on - their size. The Lucene 2.2 default, LogDocMergePolicy chose - when to merge based on number of documents - - Other implementations of MergePolicy must have a no-argument - constructor - --> <!-- - <mergePolicy class="org.apache.lucene.index.TieredMergePolicy"/> - --> + <mergePolicy class="org.apache.lucene.index.TieredMergePolicy"> + <int name="maxMergeAtOnce">10</int> + <int name="segmentsPerTier">10</int> + </mergePolicy> + --> + + <!-- Merge Factor + The merge factor controls how many segments will get merged at a time. + For TieredMergePolicy, mergeFactor is a convenience parameter which + will set both MaxMergeAtOnce and SegmentsPerTier at once. + For LogByteSizeMergePolicy, mergeFactor decides how many new segments + will be allowed before they are merged into one. + Default is 10 for both merge policies. + --> + <!-- + <mergeFactor>10</mergeFactor> + --> <!-- Expert: Merge Scheduler - The Merge Scheduler in Lucene controls how merges are performed. The ConcurrentMergeScheduler (Lucene 2.3 default) can perform merges in the background using separate threads. The SerialMergeScheduler (Lucene 2.2 default) does not. --> - <!-- + <!-- <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/> --> - <!-- LockFactory + <!-- LockFactory This option specifies which Lucene LockFactory implementation to use. - + single = SingleInstanceLockFactory - suggested for a read-only index or when there is no possibility of another process trying to modify the index. native = NativeFSLockFactory - uses OS native file locking. Do not use when multiple solr webapps in the same JVM are attempting to share a single index. - simple = SimpleFSLockFactory - uses a plain file for locking + simple = SimpleFSLockFactory - uses a plain file for locking - (For backwards compatibility with Solr 1.2, 'simple' is the default - if not specified.) + Defaults: 'native' is default for Solr3.6 and later, otherwise + 'simple' is the default More details on the nuances of each LockFactory... http://wiki.apache.org/lucene-java/AvailableLockFactories --> - <lockType>native</lockType> - - <!-- Expert: Controls how often Lucene loads terms into memory - Default is 128 and is likely good for most everyone. - --> - <!--<termIndexInterval>256</termIndexInterval>--> - </indexDefaults> - - <!-- Main Index - - Values here override the values in the <indexDefaults> section - for the main on disk index. - --> - <mainIndex> - <!-- options specific to the main on-disk lucene index --> - <useCompoundFile>false</useCompoundFile> - <ramBufferSizeMB>32</ramBufferSizeMB> - <mergeFactor>10</mergeFactor> + <lockType>${solr.lock.type:native}</lockType> <!-- Unlock On Startup If true, unlock any held write or commit locks on startup. This defeats the locking mechanism that allows multiple - processes to safely access a lucene index, and should be - used with care. - This is not needed if lock type is 'none' or 'single' + processes to safely access a lucene index, and should be used + with care. Default is "false". + + This is not needed if lock type is 'single' --> + <!-- <unlockOnStartup>false</unlockOnStartup> + --> + + <!-- Expert: Controls how often Lucene loads terms into memory + Default is 128 and is likely good for most everyone. + --> + <!-- <termIndexInterval>128</termIndexInterval> --> - <!-- If true, IndexReaders will be reopened (often more efficient) instead - of closed and then opened. --> + <!-- If true, IndexReaders will be reopened (often more efficient) + instead of closed and then opened. Default: true + --> + <!-- <reopenReaders>true</reopenReaders> + --> <!-- Commit Deletion Policy - - Custom deletion policies can specified here. The class must - implement org.apache.lucene.index.IndexDeletionPolicy. - - http://lucene.apache.org/java/2_9_1/api/all/org/apache/lucene/index/IndexDeletionPolicy.html - - The standard Solr IndexDeletionPolicy implementation supports deleting - index commit points on number of commits, age of commit point and - optimized status. - - The latest commit point should always be preserved regardless - of the criteria. + Custom deletion policies can be specified here. The class must + implement org.apache.lucene.index.IndexDeletionPolicy. + + The default Solr IndexDeletionPolicy implementation supports + deleting index commit points on number of commits, age of + commit point and optimized status. + + The latest commit point should always be preserved regardless + of the criteria. --> + <!-- <deletionPolicy class="solr.SolrDeletionPolicy"> + --> <!-- The number of commit points to be kept --> - <str name="maxCommitsToKeep">1</str> + <!-- <str name="maxCommitsToKeep">1</str> --> <!-- The number of optimized commit points to be kept --> - <str name="maxOptimizedCommitsToKeep">0</str> + <!-- <str name="maxOptimizedCommitsToKeep">0</str> --> <!-- Delete all commit points once they have reached the given age. Supports DateMathParser syntax e.g. - - <str name="maxCommitAge">30MINUTES</str> - <str name="maxCommitAge">1DAY</str> + --> + <!-- + <str name="maxCommitAge">30MINUTES</str> + <str name="maxCommitAge">1DAY</str> --> + <!-- </deletionPolicy> + --> <!-- Lucene Infostream - + To aid in advanced debugging, Lucene provides an "InfoStream" of detailed information when indexing. - Setting The value to true will instruct the underlying Lucene - IndexWriter to write its debugging info the specified file + Setting the value to true will instruct the underlying Lucene + IndexWriter to write its info stream to solr's log. By default, + this is enabled here, and controlled through log4j.properties. --> - <infoStream file="INFOSTREAM.txt">false</infoStream> + <infoStream>true</infoStream> + </indexConfig> - </mainIndex> <!-- JMX - + This example enables JMX if and only if an existing MBeanServer is found, use this if you want to configure JMX through JVM parameters. Remove this to disable exposing Solr configuration and statistics to JMX. - For more details see http://wiki.apache.org/solr/SolrJmx - --> + For more details see http://wiki.apache.org/solr/SolrJmx + --> <jmx /> <!-- If you want to connect to a particular server, specify the - agentId + agentId --> <!-- <jmx agentId="myAgent" /> --> <!-- If you want to start a new MBeanServer, specify the serviceUrl --> @@ -275,34 +334,55 @@ <!-- The default high-performance update handler --> <updateHandler class="solr.DirectUpdateHandler2"> + <!-- Enables a transaction log, used for real-time get, durability, and + and solr cloud replica recovery. The log can grow as big as + uncommitted changes to the index, so use of a hard autoCommit + is recommended (see below). + "dir" - the target directory for transaction logs, defaults to the + solr data directory. --> + <updateLog> + <str name="dir">${solr.ulog.dir:}</str> + </updateLog> + <!-- AutoCommit - Perform a <commit/> automatically under certain conditions. + Perform a hard commit automatically under certain conditions. Instead of enabling autoCommit, consider using "commitWithin" - when adding documents. + when adding documents. http://wiki.apache.org/solr/UpdateXmlMessages maxDocs - Maximum number of documents to add since the last commit before automatically triggering a new commit. - maxTime - Maximum amount of time that is allowed to pass - since a document was added before automaticly - triggering a new commit. + maxTime - Maximum amount of time in ms that is allowed to pass + since a document was added before automatically + triggering a new commit. + openSearcher - if false, the commit causes recent index changes + to be flushed to stable storage, but does not cause a new + searcher to be opened to make those changes visible. + + If the updateLog is enabled, then it's highly recommended to + have some sort of hard autoCommit to limit the log size. + --> + <autoCommit> + <maxDocs>10000</maxDocs> <!--Commit every 10.000 documents--> + <maxTime>${solr.autoCommit.maxTime:10000}</maxTime> <!--Default commit every 10 seconds--> + <openSearcher>true</openSearcher> + </autoCommit> + + <!-- softAutoCommit is like autoCommit except it causes a + 'soft' commit which only ensures that changes are visible + but does not ensure that data is synced to disk. This is + faster and more near-realtime friendly than a hard commit. --> - <!-- - <autoCommit> - <maxDocs>10000</maxDocs> - <maxTime>1000</maxTime> - </autoCommit> - --> - <autoCommit> - <maxDocs>10000</maxDocs> <!--Commit every 10.000 documents--> - <maxTime>10000</maxTime> <!--Commit every 10 seconds--> - </autoCommit> - <!-- Update Related Event Listeners + <autoSoftCommit> + <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime> + </autoSoftCommit> + <!-- Update Related Event Listeners + Various IndexWriter related events can trigger Listeners to take actions. @@ -310,11 +390,11 @@ postOptimize - fired after every optimize command --> <!-- The RunExecutableListener executes an external command from a - hook such as postCommit or postOptimize. - + hook such as postCommit or postOptimize. + exe - the name of the executable to run dir - dir to use as the current working directory. (default=".") - wait - the calling thread waits until the executable returns. + wait - the calling thread waits until the executable returns. (default="true") args - the arguments to pass to the program. (default is none) env - environment variables to set. (default is none) @@ -324,16 +404,18 @@ http://wiki.apache.org/solr/CollectionDistribution --> <!-- - <listener event="postCommit" class="solr.RunExecutableListener"> - <str name="exe">solr/bin/snapshooter</str> - <str name="dir">.</str> - <bool name="wait">true</bool> - <arr name="args"> <str>arg1</str> <str>arg2</str> </arr> - <arr name="env"> <str>MYVAR=val1</str> </arr> - </listener> - --> + <listener event="postCommit" class="solr.RunExecutableListener"> + <str name="exe">solr/bin/snapshooter</str> + <str name="dir">.</str> + <bool name="wait">true</bool> + <arr name="args"> <str>arg1</str> <str>arg2</str> </arr> + <arr name="env"> <str>MYVAR=val1</str> </arr> + </listener> + --> + </updateHandler> + <!-- IndexReaderFactory Use the following format to specify a custom IndexReaderFactory, @@ -365,13 +447,16 @@ be specified. --> <!-- - <indexReaderFactory name="IndexReaderFactory" + <indexReaderFactory name="IndexReaderFactory" class="solr.StandardIndexReaderFactory"> <int name="setTermIndexDivisor">12</int> </indexReaderFactory > --> + <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Query section - these settings control query time things like caches + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <query> <!-- Max Boolean Clauses @@ -379,12 +464,12 @@ is thrown if exceeded. ** WARNING ** - + This option actually modifies a global Lucene property that will affect all SolrCores. If multiple solrconfig.xml files disagree on this property, the value at any given moment will be based on the last SolrCore to be initialized. - + --> <maxBooleanClauses>1024</maxBooleanClauses> @@ -393,7 +478,7 @@ There are two implementations of cache available for Solr, LRUCache, based on a synchronized LinkedHashMap, and - FastLRUCache, based on a ConcurrentHashMap. + FastLRUCache, based on a ConcurrentHashMap. FastLRUCache has faster gets and slower puts in single threaded operation and thus is generally faster than LRUCache @@ -404,54 +489,54 @@ <!-- Filter Cache Cache used by SolrIndexSearcher for filters (DocSets), - unordered sets of *all* documents that match a query. - When a new searcher is opened, its caches may be prepopulated - or "autowarmed" using data from caches in the old searcher. - autowarmCount is the number of items to prepopulate. For LRUCache, - the autowarmed items will be the most recently accessed items. - Parameters: + unordered sets of *all* documents that match a query. When a + new searcher is opened, its caches may be prepopulated or + "autowarmed" using data from caches in the old searcher. + autowarmCount is the number of items to prepopulate. For + LRUCache, the autowarmed items will be the most recently + accessed items. + + Parameters: class - the SolrCache implementation LRUCache or (LRUCache or FastLRUCache) - size - the maximum number of entries in the cache - initialSize - the initial capacity (number of entries) of + size - the maximum number of entries in the cache + initialSize - the initial capacity (number of entries) of the cache. (see java.util.HashMap) - autowarmCount - the number of entries to prepopulate from - and old cache. - --> - <filterCache - class="solr.FastLRUCache" - size="512" - initialSize="512" - autowarmCount="0"/> + autowarmCount - the number of entries to prepopulate from + and old cache. + --> + <filterCache class="solr.FastLRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> <!-- Query Result Cache - + Caches results of searches - ordered lists of document ids - (DocList) based on a query, a sort, and the range of documents requested. - --> + (DocList) based on a query, a sort, and the range of documents requested. + --> <queryResultCache class="solr.LRUCache" - size="512" - initialSize="512" - autowarmCount="0"/> - + size="512" + initialSize="512" + autowarmCount="0"/> + <!-- Document Cache Caches Lucene Document objects (the stored fields for each document). Since Lucene internal document ids are transient, - this cache will not be autowarmed. + this cache will not be autowarmed. --> - <documentCache - class="solr.LRUCache" - size="512" - initialSize="512" - autowarmCount="0"/> - + <documentCache class="solr.LRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + <!-- Field Value Cache - + Cache used to hold field values that are quickly accessible by document id. The fieldValueCache is created by default even if not configured here. - --> + --> <!-- <fieldValueCache class="solr.FastLRUCache" size="512" @@ -465,18 +550,18 @@ name through SolrIndexSearcher.getCache(),cacheLookup(), and cacheInsert(). The purpose is to enable easy caching of user/application level data. The regenerator argument should - be specified as an implementation of solr.CacheRegenerator - if autowarming is desired. + be specified as an implementation of solr.CacheRegenerator + if autowarming is desired. --> <!-- - <cache name="myUserCache" - class="solr.LRUCache" - size="4096" - initialSize="1024" - autowarmCount="1024" + <cache name="myUserCache" + class="solr.LRUCache" + size="4096" + initialSize="1024" + autowarmCount="1024" regenerator="com.mycompany.MyRegenerator" - /> - --> + /> + --> <!-- Lazy Field Loading @@ -503,22 +588,24 @@ options, and none of them ever use "score" --> <!-- - <useFilterForSortedQuery>true</useFilterForSortedQuery> - --> + <useFilterForSortedQuery>true</useFilterForSortedQuery> + --> <!-- Result Window Size An optimization for use with the queryResultCache. When a search - is requested, a superset of the requested number of document ids - are collected. For example, if a search for a particular query - requests matching documents 10 through 19, and queryWindowSize is 50, - then documents 0 through 49 will be collected and cached. Any further - requests in that range can be satisfied via the cache. --> - <queryResultWindowSize>20</queryResultWindowSize> + is requested, a superset of the requested number of document ids + are collected. For example, if a search for a particular query + requests matching documents 10 through 19, and queryWindowSize is 50, + then documents 0 through 49 will be collected and cached. Any further + requests in that range can be satisfied via the cache. + --> + <queryResultWindowSize>20</queryResultWindowSize> - <!-- Maximum number of documents to cache for any entry in the - queryResultCache. --> - <queryResultMaxDocsCached>200</queryResultMaxDocsCached> + <!-- Maximum number of documents to cache for any entry in the + queryResultCache. + --> + <queryResultMaxDocsCached>200</queryResultMaxDocsCached> <!-- Query Related Event Listeners @@ -526,192 +613,213 @@ take actions. newSearcher - fired whenever a new searcher is being prepared - and there is a current searcher handling requests (aka registered). - It can be used to prime certain caches to prevent long request times for - certain requests. + and there is a current searcher handling requests (aka + registered). It can be used to prime certain caches to + prevent long request times for certain requests. firstSearcher - fired whenever a new searcher is being prepared but there is no current registered searcher to handle requests or to gain autowarming data from. - - --> + + --> <!-- QuerySenderListener takes an array of NamedList and executes a - local query request for each NamedList in sequence. --> + local query request for each NamedList in sequence. + --> <listener event="newSearcher" class="solr.QuerySenderListener"> <arr name="queries"> <!-- - <lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst> - <lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst> - <lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst> - --> + <lst><str name="q">solr</str><str name="sort">price asc</str></lst> + <lst><str name="q">rocks</str><str name="sort">weight asc</str></lst> + --> </arr> </listener> - - <!-- a firstSearcher event is fired whenever a new searcher is being - prepared but there is no current registered searcher to handle - requests or to gain autowarming data from. --> <listener event="firstSearcher" class="solr.QuerySenderListener"> <arr name="queries"> - <lst> <str name="q">solr rocks</str><str name="start">0</str><str name="rows">10</str></lst> - <lst><str name="q">static firstSearcher warming query from solrconfig.xml</str></lst> + <lst> + <str name="q">static firstSearcher warming in solrconfig.xml</str> + </lst> </arr> </listener> - <!-- If a search request comes in and there is no current registered searcher, - then immediately register the still warming searcher and use it. If - "false" then all requests will block until the first searcher is done - warming. --> + <!-- Use Cold Searcher + + If a search request comes in and there is no current + registered searcher, then immediately register the still + warming searcher and use it. If "false" then all requests + will block until the first searcher is done warming. + --> <useColdSearcher>false</useColdSearcher> - <!-- Maximum number of searchers that may be warming in the background - concurrently. An error is returned if this limit is exceeded. Recommend - 1-2 for read-only slaves, higher for masters w/o cache warming. --> + <!-- Max Warming Searchers + + Maximum number of searchers that may be warming in the + background concurrently. An error is returned if this limit + is exceeded. + + Recommend values of 1-2 for read-only slaves, higher for + masters w/o cache warming. + --> <maxWarmingSearchers>2</maxWarmingSearchers> </query> + + <!-- Request Dispatcher - <!-- - Let the dispatch filter handler /select?qt=XXX - handleSelect=true will use consistent error handling for /select and /update - handleSelect=false will use solr1.1 style error formatting - --> - <requestDispatcher handleSelect="true" > - <!--Make sure your system has some authentication before enabling remote streaming! --> - <requestParsers enableRemoteStreaming="true" multipartUploadLimitInKB="2048000" /> + This section contains instructions for how the SolrDispatchFilter + should behave when processing requests for this SolrCore. - <!-- Set HTTP caching related parameters (for proxy caches and clients). + handleSelect is a legacy option that affects the behavior of requests + such as /select?qt=XXX - To get the behaviour of Solr 1.2 (ie: no caching related headers) - use the never304="true" option and do not specify a value for - <cacheControl> - --> - <!-- <httpCaching never304="true"> --> - <httpCaching lastModifiedFrom="openTime" - etagSeed="Solr"> - <!-- lastModFrom="openTime" is the default, the Last-Modified value - (and validation against If-Modified-Since requests) will all be - relative to when the current Searcher was opened. - You can change it to lastModFrom="dirLastMod" if you want the - value to exactly corrispond to when the physical index was last - modified. - - etagSeed="..." is an option you can change to force the ETag - header (and validation against If-None-Match requests) to be - differnet even if the index has not changed (ie: when making - significant changes to your config file) - - lastModifiedFrom and etagSeed are both ignored if you use the - never304="true" option. - --> - <!-- If you include a <cacheControl> directive, it will be used to - generate a Cache-Control header, as well as an Expires header - if the value contains "max-age=" + handleSelect="true" will cause the SolrDispatchFilter to process + the request and dispatch the query to a handler specified by the + "qt" param, assuming "/select" isn't already registered. - By default, no Cache-Control header is generated. + handleSelect="false" will cause the SolrDispatchFilter to + ignore "/select" requests, resulting in a 404 unless a handler + is explicitly registered with the name "/select" - You can use the <cacheControl> option even if you have set - never304="true" - --> - <!-- <cacheControl>max-age=30, public</cacheControl> --> - </httpCaching> + handleSelect="true" is not recommended for new users, but is the default + for backwards compatibility + --> + <requestDispatcher handleSelect="false" > + <!-- Request Parsing + + These settings indicate how Solr Requests may be parsed, and + what restrictions may be placed on the ContentStreams from + those requests + + enableRemoteStreaming - enables use of the stream.file + and stream.url parameters for specifying remote streams. + + multipartUploadLimitInKB - specifies the max size (in KiB) of + Multipart File Uploads that Solr will allow in a Request. + + formdataUploadLimitInKB - specifies the max size (in KiB) of + form data (application/x-www-form-urlencoded) sent via + POST. You can use POST to pass request parameters not + fitting into the URL. + + addHttpRequestToContext - if set to true, it will instruct + the requestParsers to include the original HttpServletRequest + object in the context map of the SolrQueryRequest under the + key "httpRequest". It will not be used by any of the existing + Solr components, but may be useful when developing custom + plugins. + + *** WARNING *** + The settings below authorize Solr to fetch remote files, You + should make sure your system has some authentication before + using enableRemoteStreaming="true" + + --> + <requestParsers enableRemoteStreaming="true" + multipartUploadLimitInKB="2048000" + formdataUploadLimitInKB="2048" + addHttpRequestToContext="false"/> + + <!-- HTTP Caching + + Set HTTP caching related parameters (for proxy caches and clients). + + The options below instruct Solr not to output any HTTP Caching + related headers + --> + <httpCaching never304="true" /> + <!-- If you include a <cacheControl> directive, it will be used to + generate a Cache-Control header (as well as an Expires header + if the value contains "max-age=") + + By default, no Cache-Control header is generated. + + You can use the <cacheControl> option even if you have set + never304="true" + --> + <!-- + <httpCaching never304="true" > + <cacheControl>max-age=30, public</cacheControl> + </httpCaching> + --> + <!-- To enable Solr to respond with automatically generated HTTP + Caching headers, and to response to Cache Validation requests + correctly, set the value of never304="false" + + This will cause Solr to generate Last-Modified and ETag + headers based on the properties of the Index. + + The following options can also be specified to affect the + values of these headers... + + lastModFrom - the default value is "openTime" which means the + Last-Modified value (and validation against If-Modified-Since + requests) will all be relative to when the current Searcher + was opened. You can change it to lastModFrom="dirLastMod" if + you want the value to exactly correspond to when the physical + index was last modified. + + etagSeed="..." is an option you can change to force the ETag + header (and validation against If-None-Match requests) to be + different even if the index has not changed (ie: when making + significant changes to your config file) + + (lastModifiedFrom and etagSeed are both ignored if you use + the never304="true" option) + --> + <!-- + <httpCaching lastModifiedFrom="openTime" + etagSeed="Solr"> + <cacheControl>max-age=30, public</cacheControl> + </httpCaching> + --> </requestDispatcher> - <!-- requestHandler plugins... incoming queries will be dispatched to the - correct handler based on the path or the qt (query type) param. - Names starting with a '/' are accessed with the a path equal to the - registered name. Names without a leading '/' are accessed with: - http://host/app/select?qt=name - If no qt is defined, the requestHandler that declares default="true" - will be used. - --> - <requestHandler name="standard" class="solr.SearchHandler" default="true"> - <!-- default values for query parameters --> - <lst name="defaults"> - <str name="echoParams">explicit</str> - <!-- - <int name="rows">10</int> - <str name="fl">*</str> - <str name="version">2.1</str> - --> - </lst> - </requestHandler> + <!-- Request Handlers -<!-- Please refer to http://wiki.apache.org/solr/SolrReplication for details on configuring replication --> -<!-- remove the <lst name="master"> section if this is just a slave --> -<!-- remove the <lst name="slave"> section if this is just a master --> -<!-- -<requestHandler name="/replication" class="solr.ReplicationHandler" > - <lst name="master"> - <str name="replicateAfter">commit</str> - <str name="replicateAfter">startup</str> - <str name="confFiles">schema.xml,stopwords.txt</str> - </lst> - <lst name="slave"> - <str name="masterUrl">http://localhost:8983/solr/replication</str> - <str name="pollInterval">00:00:60</str> - </lst> -</requestHandler>--> + http://wiki.apache.org/solr/SolrRequestHandler - <!-- DisMaxRequestHandler allows easy searching across multiple fields - for simple user-entered phrases. It's implementation is now - just the standard SearchHandler with a default query type - of "dismax". - see http://wiki.apache.org/solr/DisMaxRequestHandler - --> - <requestHandler name="dismax" class="solr.SearchHandler" > - <lst name="defaults"> - <str name="defType">dismax</str> - <str name="echoParams">explicit</str> - <float name="tie">0.01</float> - <str name="qf"> - text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 - </str> - <str name="pf"> - text^0.2 features^1.1 name^1.5 manu^1.4 manu_exact^1.9 - </str> - <str name="bf"> - popularity^0.5 recip(price,1,1000,1000)^0.3 - </str> - <str name="fl"> - id,name,price,score - </str> - <str name="mm"> - 2<-1 5<-2 6<90% - </str> - <int name="ps">100</int> - <str name="q.alt">*:*</str> - <!-- example highlighter config, enable per-query with hl=true --> - <str name="hl.fl">text features name</str> - <!-- for this field, we want no fragmenting, just highlighting --> - <str name="f.name.hl.fragsize">0</str> - <!-- instructs Solr to return the field itself if no query terms are - found --> - <str name="f.name.hl.alternateField">name</str> - <str name="f.text.hl.fragmenter">regex</str> <!-- defined below --> - </lst> - </requestHandler> + Incoming queries will be dispatched to a specific handler by name + based on the path specified in the request. + + Legacy behavior: If the request path uses "/select" but no Request + Handler has that name, and if handleSelect="true" has been specified in + the requestDispatcher, then the Request Handler is dispatched based on + the qt parameter. Handlers without a leading '/' are accessed this way + like so: http://host/app/[core/]select?qt=name If no qt is + given, then the requestHandler that declares default="true" will be + used or the one named "standard". + + If a Request Handler is declared with startup="lazy", then it will + not be initialized until the first request that uses it. - <!-- Note how you can register the same handler multiple times with - different names (and different init parameters) --> - <requestHandler name="partitioned" class="solr.SearchHandler" > - <lst name="defaults"> - <str name="defType">dismax</str> - <str name="echoParams">explicit</str> - <str name="qf">text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0</str> - <str name="mm">2<-1 5<-2 6<90%</str> - <!-- This is an example of using Date Math to specify a constantly - moving date range in a config... - --> - <str name="bq">incubationdate_dt:[* TO NOW/DAY-1MONTH]^2.2</str> - </lst> + <!-- SearchHandler + + http://wiki.apache.org/solr/SearchHandler + + For processing Search Queries, the primary Request Handler + provided with Solr is "SearchHandler" It delegates to a sequent + of SearchComponents (see below) and supports distributed + queries across multiple shards + --> + <requestHandler name="/select" class="solr.SearchHandler"> + <!-- default values for query parameters can be specified, these + will be overridden by parameters in the request + --> + <lst name="defaults"> + <str name="echoParams">explicit</str> + <int name="rows">10</int> + <str name="df">search_text</str> + </lst> + <arr name="last-components"> + <str>spellcheck</str> + </arr> <!-- In addition to defaults, "appends" params can be specified to identify values which should be appended to the list of multi-val params from the query (or the existing "defaults"). - - In this example, the param "fq=instock:true" will be appended to + --> + <!-- In this example, the param "fq=instock:true" would be appended to any query time fq params the user may specify, as a mechanism for partitioning the index, independent of any user selected filtering that may also be desired (perhaps as a result of faceted searching). @@ -720,33 +828,375 @@ "appends" values from being used, so don't use this mechanism unless you are sure you always want it. --> - <lst name="appends"> - <str name="fq">inStock:true</str> - </lst> + <!-- + <lst name="appends"> + <str name="fq">inStock:true</str> + </lst> + --> <!-- "invariants" are a way of letting the Solr maintainer lock down the options available to Solr clients. Any params values specified here are used regardless of what values may be specified in either the query, the "defaults", or the "appends" params. - In this example, the facet.field and facet.query params are fixed, - limiting the facets clients can use. Faceting is not turned on by - default - but if the client does specify facet=true in the request, - these are the only facets they will be able to see counts for; - regardless of what other facet.field or facet.query params they - may specify. + In this example, the facet.field and facet.query params would + be fixed, limiting the facets clients can use. Faceting is + not turned on by default - but if the client does specify + facet=true in the request, these are the only facets they + will be able to see counts for; regardless of what other + facet.field or facet.query params they may specify. NOTE: there is *absolutely* nothing a client can do to prevent these "invariants" values from being used, so don't use this mechanism unless you are sure you always want it. --> + <!-- + <lst name="invariants"> + <str name="facet.field">cat</str> + <str name="facet.field">manu_exact</str> + <str name="facet.query">price:[* TO 500]</str> + <str name="facet.query">price:[500 TO *]</str> + </lst> + --> + <!-- If the default list of SearchComponents is not desired, that + list can either be overridden completely, or components can be + prepended or appended to the default list. (see below) + --> + <!-- + <arr name="components"> + <str>nameOfCustomComponent1</str> + <str>nameOfCustomComponent2</str> + </arr> + + --> + + </requestHandler> + + <!-- A request handler that returns indented JSON by default --> + <requestHandler name="/query" class="solr.SearchHandler"> + <lst name="defaults"> + <str name="echoParams">explicit</str> + <str name="wt">json</str> + <str name="indent">true</str> + <str name="df">search_text</str> + </lst> + </requestHandler> + + + <!-- realtime get handler, guaranteed to return the latest stored fields of + any document, without the need to commit or open a new searcher. The + current implementation relies on the updateLog feature being enabled. --> + <requestHandler name="/get" class="solr.RealTimeGetHandler"> + <lst name="defaults"> + <str name="omitHeader">true</str> + <str name="wt">json</str> + <str name="indent">true</str> + </lst> + </requestHandler> + + + <!-- A Robust Example + + This example SearchHandler declaration shows off usage of the + SearchHandler with many defaults declared + + Note that multiple instances of the same Request Handler + (SearchHandler) can be registered multiple times with different + names (and different init parameters) + --> + <requestHandler name="/browse" class="solr.SearchHandler"> + <lst name="defaults"> + <str name="echoParams">explicit</str> + + <!-- VelocityResponseWriter settings --> + <str name="wt">velocity</str> + <str name="v.template">browse</str> + <str name="v.layout">layout</str> + <str name="title">Solritas</str> + + <!-- Query settings --> + <str name="defType">edismax</str> + <str name="qf"> + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0 + </str> + <str name="df">search_text</str> + <str name="mm">100%</str> + <str name="q.alt">*:*</str> + <str name="rows">10</str> + <str name="fl">*,score</str> + + <str name="mlt.qf"> + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0 + </str> + <str name="mlt.fl">search_text,features,name,sku,id,manu,cat,title,description,keywords,author,resourcename</str> + <int name="mlt.count">3</int> + + <!-- Faceting defaults --> + <str name="facet">on</str> + <str name="facet.field">cat</str> + <str name="facet.field">manu_exact</str> + <str name="facet.field">content_type</str> + <str name="facet.field">author_s</str> + <str name="facet.query">ipod</str> + <str name="facet.query">GB</str> + <str name="facet.mincount">1</str> + <str name="facet.pivot">cat,inStock</str> + <str name="facet.range.other">after</str> + <str name="facet.range">price</str> + <int name="f.price.facet.range.start">0</int> + <int name="f.price.facet.range.end">600</int> + <int name="f.price.facet.range.gap">50</int> + <str name="facet.range">popularity</str> + <int name="f.popularity.facet.range.start">0</int> + <int name="f.popularity.facet.range.end">10</int> + <int name="f.popularity.facet.range.gap">3</int> + <str name="facet.range">manufacturedate_dt</str> + <str name="f.manufacturedate_dt.facet.range.start">NOW/YEAR-10YEARS</str> + <str name="f.manufacturedate_dt.facet.range.end">NOW</str> + <str name="f.manufacturedate_dt.facet.range.gap">+1YEAR</str> + <str name="f.manufacturedate_dt.facet.range.other">before</str> + <str name="f.manufacturedate_dt.facet.range.other">after</str> + + <!-- Highlighting defaults --> + <str name="hl">on</str> + <str name="hl.fl">content features title name</str> + <str name="hl.encoder">html</str> + <str name="hl.simple.pre"><b></str> + <str name="hl.simple.post"></b></str> + <str name="f.title.hl.fragsize">0</str> + <str name="f.title.hl.alternateField">title</str> + <str name="f.name.hl.fragsize">0</str> + <str name="f.name.hl.alternateField">name</str> + <str name="f.content.hl.snippets">3</str> + <str name="f.content.hl.fragsize">200</str> + <str name="f.content.hl.alternateField">content</str> + <str name="f.content.hl.maxAlternateFieldLength">750</str> + + <!-- Spell checking defaults --> + <str name="spellcheck">on</str> + <str name="spellcheck.extendedResults">false</str> + <str name="spellcheck.count">5</str> + <str name="spellcheck.alternativeTermCount">2</str> + <str name="spellcheck.maxResultsForSuggest">5</str> + <str name="spellcheck.collate">true</str> + <str name="spellcheck.collateExtendedResults">true</str> + <str name="spellcheck.maxCollationTries">5</str> + <str name="spellcheck.maxCollations">3</str> + </lst> + + <!-- append spellchecking to our list of components --> + <arr name="last-components"> + <str>spellcheck</str> + </arr> + </requestHandler> + + <!-- Update Request Handler. + + http://wiki.apache.org/solr/UpdateXmlMessages + + The canonical Request Handler for Modifying the Index through + commands specified using XML, JSON, CSV, or JAVABIN + + Note: Since solr1.1 requestHandlers requires a valid content + type header if posted in the body. For example, curl now + requires: -H 'Content-type:text/xml; charset=utf-8' + + To override the request content type and force a specific + Content-type, use the request parameter: + ?update.contentType=text/csv + + This handler will pick a response format to match the input + if the 'wt' parameter is not explicit + --> + <requestHandler name="/update" class="solr.UpdateRequestHandler"> + <!-- See below for information on defining + updateRequestProcessorChains that can be used by name + on each Update Request + --> + <!-- + <lst name="defaults"> + <str name="update.chain">dedupe</str> + </lst> + --> + </requestHandler> + + <!-- for back compat with clients using /update/json and /update/csv --> + <requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler"> + <lst name="defaults"> + <str name="stream.contentType">application/json</str> + </lst> + </requestHandler> + <requestHandler name="/update/csv" class="solr.CSVRequestHandler"> + <lst name="defaults"> + <str name="stream.contentType">application/csv</str> + </lst> + </requestHandler> + + <!-- Solr Cell Update Request Handler + + http://wiki.apache.org/solr/ExtractingRequestHandler + + --> + <requestHandler name="/update/extract" + startup="lazy" + class="solr.extraction.ExtractingRequestHandler" > + <lst name="defaults"> + <str name="lowernames">true</str> + <str name="uprefix">ignored_</str> + + <!-- capture link hrefs but ignore div attributes --> + <str name="captureAttr">true</str> + <str name="fmap.a">links</str> + <str name="fmap.div">ignored_</str> + </lst> + </requestHandler> + + + <!-- Field Analysis Request Handler + + RequestHandler that provides much the same functionality as + analysis.jsp. Provides the ability to specify multiple field + types and field names in the same request and outputs + index-time and query-time analysis for each of them. + + Request parameters are: + analysis.fieldname - field name whose analyzers are to be used + + analysis.fieldtype - field type whose analyzers are to be used + analysis.fieldvalue - text for index-time analysis + q (or analysis.q) - text for query time analysis + analysis.showmatch (true|false) - When set to true and when + query analysis is performed, the produced tokens of the + field value analysis will be marked as "matched" for every + token that is produces by the query analysis + --> + <requestHandler name="/analysis/field" + startup="lazy" + class="solr.FieldAnalysisRequestHandler" /> + + + <!-- Document Analysis Handler + + http://wiki.apache.org/solr/AnalysisRequestHandler + + An analysis handler that provides a breakdown of the analysis + process of provided documents. This handler expects a (single) + content stream with the following format: + + <docs> + <doc> + <field name="id">1</field> + <field name="name">The Name</field> + <field name="text">The Text Value</field> + </doc> + <doc>...</doc> + <doc>...</doc> + ... + </docs> + + Note: Each document must contain a field which serves as the + unique key. This key is used in the returned response to associate + an analysis breakdown to the analyzed document. + + Like the FieldAnalysisRequestHandler, this handler also supports + query analysis by sending either an "analysis.query" or "q" + request parameter that holds the query text to be analyzed. It + also supports the "analysis.showmatch" parameter which when set to + true, all field tokens that match the query tokens will be marked + as a "match". + --> + <requestHandler name="/analysis/document" + class="solr.DocumentAnalysisRequestHandler" + startup="lazy" /> + + <!-- Admin Handlers + + Admin Handlers - This will register all the standard admin + RequestHandlers. + --> + <requestHandler name="/admin/" + class="solr.admin.AdminHandlers" /> + <!-- This single handler is equivalent to the following... --> + <!-- + <requestHandler name="/admin/luke" class="solr.admin.LukeRequestHandler" /> + <requestHandler name="/admin/system" class="solr.admin.SystemInfoHandler" /> + <requestHandler name="/admin/plugins" class="solr.admin.PluginInfoHandler" /> + <requestHandler name="/admin/threads" class="solr.admin.ThreadDumpHandler" /> + <requestHandler name="/admin/properties" class="solr.admin.PropertiesRequestHandler" /> + <requestHandler name="/admin/file" class="solr.admin.ShowFileRequestHandler" > + --> + <!-- If you wish to hide files under ${solr.home}/conf, explicitly + register the ShowFileRequestHandler using: + --> + <!-- + <requestHandler name="/admin/file" + class="solr.admin.ShowFileRequestHandler" > + <lst name="invariants"> + <str name="hidden">synonyms.txt</str> + <str name="hidden">anotherfile.txt</str> + </lst> + </requestHandler> + --> + + <!-- ping/healthcheck --> + <requestHandler name="/admin/ping" class="solr.PingRequestHandler"> <lst name="invariants"> - <str name="facet.field">cat</str> - <str name="facet.field">manu_exact</str> - <str name="facet.query">price:[* TO 500]</str> - <str name="facet.query">price:[500 TO *]</str> + <str name="q">solrpingquery</str> + </lst> + <lst name="defaults"> + <str name="echoParams">all</str> + </lst> + <!-- An optional feature of the PingRequestHandler is to configure the + handler with a "healthcheckFile" which can be used to enable/disable + the PingRequestHandler. + relative paths are resolved against the data dir + --> + <!-- <str name="healthcheckFile">server-enabled.txt</str> --> + </requestHandler> + + <!-- Echo the request contents back to the client --> + <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" > + <lst name="defaults"> + <str name="echoParams">explicit</str> + <str name="echoHandler">true</str> </lst> </requestHandler> + + <!-- Solr Replication + + The SolrReplicationHandler supports replicating indexes from a + "master" used for indexing and "slaves" used for queries. + http://wiki.apache.org/solr/SolrReplication + + It is also necessary for SolrCloud to function (in Cloud mode, the + replication handler is used to bulk transfer segments when nodes + are added or need to recover). + + https://wiki.apache.org/solr/SolrCloud/ + --> + <requestHandler name="/replication" class="solr.ReplicationHandler" > + <!-- + To enable simple master/slave replication, uncomment one of the + sections below, depending on whether this solr instance should be + the "master" or a "slave". If this instance is a "slave" you will + also need to fill in the masterUrl to point to a real machine. + --> + <!-- + <lst name="master"> + <str name="replicateAfter">commit</str> + <str name="replicateAfter">startup</str> + <str name="confFiles">schema.xml,stopwords.txt</str> + </lst> + --> + <!-- + <lst name="slave"> + <str name="masterUrl">http://your-master-hostname:8983/solr</str> + <str name="pollInterval">00:00:60</str> + </lst> + --> + </requestHandler> <!-- Search components are registered to SolrCore and used by Search Handlers @@ -788,10 +1238,14 @@ <str name="queryAnalyzerFieldType">textSpell</str> + <lst name="spellchecker"> + <str name="classname">solr.IndexBasedSpellChecker</str> <str name="name">default</str> - <str name="field">name</str> + <str name="field">a_spell</str> <str name="spellcheckIndexDir">./spellchecker</str> + <str name="buildOnCommit">true</str> + <str name="spellcheck.onlyMorePopular">false</str> </lst> <!-- a spellchecker that uses a different distance measure @@ -851,56 +1305,284 @@ </arr> </requestHandler> + <!-- Search Components + + Search components are registered to SolrCore and used by + instances of SearchHandler (which can access them by name) + + By default, the following components are available: + + <searchComponent name="query" class="solr.QueryComponent" /> + <searchComponent name="facet" class="solr.FacetComponent" /> + <searchComponent name="mlt" class="solr.MoreLikeThisComponent" /> + <searchComponent name="highlight" class="solr.HighlightComponent" /> + <searchComponent name="stats" class="solr.StatsComponent" /> + <searchComponent name="debug" class="solr.DebugComponent" /> + + Default configuration in a requestHandler would look like: + + <arr name="components"> + <str>query</str> + <str>facet</str> + <str>mlt</str> + <str>highlight</str> + <str>stats</str> + <str>debug</str> + </arr> + + If you register a searchComponent to one of the standard names, + that will be used instead of the default. + + To insert components before or after the 'standard' components, use: + + <arr name="first-components"> + <str>myFirstComponentName</str> + </arr> + + <arr name="last-components"> + <str>myLastComponentName</str> + </arr> + + NOTE: The component registered with the name "debug" will + always be executed after the "last-components" + + --> + + <!-- Spell Check + + The spell check component can return a list of alternative spelling + suggestions. + + http://wiki.apache.org/solr/SpellCheckComponent + --> + <searchComponent name="spellcheck" class="solr.SpellCheckComponent"> + + <str name="queryAnalyzerFieldType">text_general</str> + + <!-- Multiple "Spell Checkers" can be declared and used by this + component + --> + + <!-- a spellchecker built from a field of the main index --> + <lst name="spellchecker"> + <str name="name">default</str> + <str name="field">search_text</str> + <str name="classname">solr.DirectSolrSpellChecker</str> + <!-- the spellcheck distance measure used, the default is the internal levenshtein --> + <str name="distanceMeasure">internal</str> + <!-- minimum accuracy needed to be considered a valid spellcheck suggestion --> + <float name="accuracy">0.5</float> + <!-- the maximum #edits we consider when enumerating terms: can be 1 or 2 --> + <int name="maxEdits">2</int> + <!-- the minimum shared prefix when enumerating terms --> + <int name="minPrefix">1</int> + <!-- maximum number of inspections per result. --> + <int name="maxInspections">5</int> + <!-- minimum length of a query term to be considered for correction --> + <int name="minQueryLength">4</int> + <!-- maximum threshold of documents a query term can appear to be considered for correction --> + <float name="maxQueryFrequency">0.01</float> + <!-- uncomment this to require suggestions to occur in 1% of the documents + <float name="thresholdTokenFrequency">.01</float> + --> + </lst> + + <!-- a spellchecker that can break or combine words. See "/spell" handler below for usage --> + <lst name="spellchecker"> + <str name="name">wordbreak</str> + <str name="classname">solr.WordBreakSolrSpellChecker</str> + <str name="field">name</str> + <str name="combineWords">true</str> + <str name="breakWords">true</str> + <int name="maxChanges">10</int> + </lst> + + <!-- a spellchecker that uses a different distance measure --> + <!-- + <lst name="spellchecker"> + <str name="name">jarowinkler</str> + <str name="field">spell</str> + <str name="classname">solr.DirectSolrSpellChecker</str> + <str name="distanceMeasure"> + org.apache.lucene.search.spell.JaroWinklerDistance + </str> + </lst> + --> + + <!-- a spellchecker that use an alternate comparator + + comparatorClass be one of: + 1. score (default) + 2. freq (Frequency first, then score) + 3. A fully qualified class name + --> + <!-- + <lst name="spellchecker"> + <str name="name">freq</str> + <str name="field">lowerfilt</str> + <str name="classname">solr.DirectSolrSpellChecker</str> + <str name="comparatorClass">freq</str> + --> + + <!-- A spellchecker that reads the list of words from a file --> + <!-- + <lst name="spellchecker"> + <str name="classname">solr.FileBasedSpellChecker</str> + <str name="name">file</str> + <str name="sourceLocation">spellings.txt</str> + <str name="characterEncoding">UTF-8</str> + <str name="spellcheckIndexDir">spellcheckerFile</str> + </lst> + --> + </searchComponent> + + <!-- A request handler for demonstrating the spellcheck component. + + NOTE: This is purely as an example. The whole purpose of the + SpellCheckComponent is to hook it into the request handler that + handles your normal user queries so that a separate request is + not needed to get suggestions. + + IN OTHER WORDS, THERE IS REALLY GOOD CHANCE THE SETUP BELOW IS + NOT WHAT YOU WANT FOR YOUR PRODUCTION SYSTEM! + + See http://wiki.apache.org/solr/SpellCheckComponent for details + on the request parameters. + --> + <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy"> + <lst name="defaults"> + <str name="df">search_text</str> + <!-- Solr will use suggestions from both the 'default' spellchecker + and from the 'wordbreak' spellchecker and combine them. + collations (re-written queries) can include a combination of + corrections from both spellcheckers --> + <str name="spellcheck.dictionary">default</str> + <str name="spellcheck.dictionary">wordbreak</str> + <str name="spellcheck">on</str> + <str name="spellcheck.extendedResults">true</str> + <str name="spellcheck.count">10</str> + <str name="spellcheck.alternativeTermCount">5</str> + <str name="spellcheck.maxResultsForSuggest">5</str> + <str name="spellcheck.collate">true</str> + <str name="spellcheck.collateExtendedResults">true</str> + <str name="spellcheck.maxCollationTries">10</str> + <str name="spellcheck.maxCollations">5</str> + </lst> + <arr name="last-components"> + <str>spellcheck</str> + </arr> + </requestHandler> + + <!-- Term Vector Component + + http://wiki.apache.org/solr/TermVectorComponent + --> + <searchComponent name="tvComponent" class="solr.TermVectorComponent"/> + + <!-- A request handler for demonstrating the term vector component + + This is purely as an example. + + In reality you will likely want to add the component to your + already specified request handlers. + --> + <requestHandler name="/tvrh" class="solr.SearchHandler" startup="lazy"> + <lst name="defaults"> + <str name="df">search_text</str> + <bool name="tv">true</bool> + </lst> + <arr name="last-components"> + <str>tvComponent</str> + </arr> + </requestHandler> + <!-- Clustering Component + http://wiki.apache.org/solr/ClusteringComponent - This relies on third party jars which are not included in the release. - To use this component (and the "/clustering" handler) - Those jars will need to be downloaded, and you'll need to set the - solr.cluster.enabled system property when running solr... - java -Dsolr.clustering.enabled=true -jar start.jar + + You'll need to set the solr.clustering.enabled system property + when running solr to run with clustering enabled: + + java -Dsolr.clustering.enabled=true -jar start.jar + --> - <searchComponent - name="clusteringComponent" - enable="${solr.clustering.enabled:false}" - class="org.apache.solr.handler.clustering.ClusteringComponent" > + <searchComponent name="clustering" + enable="${solr.clustering.enabled:false}" + class="solr.clustering.ClusteringComponent" > <!-- Declare an engine --> <lst name="engine"> <!-- The name, only one can be named "default" --> <str name="name">default</str> - <!-- - Class name of Carrot2 clustering algorithm. Currently available algorithms are: + <!-- Class name of Carrot2 clustering algorithm. + + Currently available algorithms are: + * org.carrot2.clustering.lingo.LingoClusteringAlgorithm * org.carrot2.clustering.stc.STCClusteringAlgorithm - - See http://project.carrot2.org/algorithms.html for the algorithm's characteristics. + * org.carrot2.clustering.kmeans.BisectingKMeansClusteringAlgorithm + + See http://project.carrot2.org/algorithms.html for the + algorithm's characteristics. --> <str name="carrot.algorithm">org.carrot2.clustering.lingo.LingoClusteringAlgorithm</str> - <!-- - Overriding values for Carrot2 default algorithm attributes. For a description - of all available attributes, see: http://download.carrot2.org/stable/manual/#chapter.components. - Use attribute key as name attribute of str elements below. These can be further - overridden for individual requests by specifying attribute key as request - parameter name and attribute value as parameter value. + + <!-- Overriding values for Carrot2 default algorithm attributes. + + For a description of all available attributes, see: + http://download.carrot2.org/stable/manual/#chapter.components. + Use attribute key as name attribute of str elements + below. These can be further overridden for individual + requests by specifying attribute key as request parameter + name and attribute value as parameter value. --> <str name="LingoClusteringAlgorithm.desiredClusterCountBase">20</str> + + <!-- Location of Carrot2 lexical resources. + + A directory from which to load Carrot2-specific stop words + and stop labels. Absolute or relative to Solr config directory. + If a specific resource (e.g. stopwords.en) is present in the + specified dir, it will completely override the corresponding + default one that ships with Carrot2. + + For an overview of Carrot2 lexical resources, see: + http://download.carrot2.org/head/manual/#chapter.lexical-resources + --> + <str name="carrot.lexicalResourcesDir">clustering/carrot2</str> + + <!-- The language to assume for the documents. + + For a list of allowed values, see: + http://download.carrot2.org/stable/manual/#section.attribute.lingo.MultilingualClustering.defaultLanguage + --> + <str name="MultilingualClustering.defaultLanguage">ENGLISH</str> </lst> <lst name="engine"> <str name="name">stc</str> <str name="carrot.algorithm">org.carrot2.clustering.stc.STCClusteringAlgorithm</str> </lst> </searchComponent> + + <!-- A request handler for demonstrating the clustering component + + This is purely as an example. + + In reality you will likely want to add the component to your + already specified request handlers. + --> <requestHandler name="/clustering" + startup="lazy" enable="${solr.clustering.enabled:false}" class="solr.SearchHandler"> - <lst name="defaults"> - <bool name="clustering">true</bool> - <str name="clustering.engine">default</str> - <bool name="clustering.results">true</bool> - <!-- The title field --> - <str name="carrot.title">name</str> - <str name="carrot.url">id</str> - <!-- The field to cluster on --> + <lst name="defaults"> + <bool name="clustering">true</bool> + <str name="clustering.engine">default</str> + <bool name="clustering.results">true</bool> + <!-- The title field --> + <str name="carrot.title">name</str> + <str name="carrot.url">id</str> + <!-- The field to cluster on --> <str name="carrot.snippet">features</str> <!-- produce summaries --> <bool name="carrot.produceSummary">true</bool> @@ -908,265 +1590,347 @@ <!--<int name="carrot.numDescriptions">5</int>--> <!-- produce sub clusters --> <bool name="carrot.outputSubClusters">false</bool> - </lst> + + <str name="defType">edismax</str> + <str name="qf"> + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + </str> + <str name="q.alt">*:*</str> + <str name="rows">10</str> + <str name="fl">*,score</str> + </lst> <arr name="last-components"> - <str>clusteringComponent</str> + <str>clustering</str> </arr> </requestHandler> + + <!-- Terms Component - <!-- Solr Cell: http://wiki.apache.org/solr/ExtractingRequestHandler --> - <requestHandler name="/update/extract" class="org.apache.solr.handler.extraction.ExtractingRequestHandler" startup="lazy"> - <lst name="defaults"> - <!-- All the main content goes into "text"... if you need to return - the extracted text or do highlighting, use a stored field. --> - <str name="fmap.content">text</str> - <str name="lowernames">true</str> - <str name="uprefix">ignored_</str> + http://wiki.apache.org/solr/TermsComponent - <!-- capture link hrefs but ignore div attributes --> - <str name="captureAttr">true</str> - <str name="fmap.a">links</str> - <str name="fmap.div">ignored_</str> - </lst> - </requestHandler> - - - <!-- A component to return terms and document frequency of those terms. - This component does not yet support distributed search. --> - <searchComponent name="termsComponent" class="org.apache.solr.handler.component.TermsComponent"/> + A component to return terms and document frequency of those + terms + --> + <searchComponent name="terms" class="solr.TermsComponent"/> - <requestHandler name="/terms" class="org.apache.solr.handler.component.SearchHandler"> + <!-- A request handler for demonstrating the terms component --> + <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy"> <lst name="defaults"> <bool name="terms">true</bool> - </lst> + <bool name="distrib">false</bool> + </lst> <arr name="components"> - <str>termsComponent</str> + <str>terms</str> </arr> </requestHandler> - <!-- a search component that enables you to configure the top results for - a given query regardless of the normal lucene scoring.--> + <!-- Query Elevation Component + + http://wiki.apache.org/solr/QueryElevationComponent + + a search component that enables you to configure the top + results for a given query regardless of the normal lucene + scoring. + --> <searchComponent name="elevator" class="solr.QueryElevationComponent" > <!-- pick a fieldType to analyze queries --> <str name="queryFieldType">string</str> <str name="config-file">elevate.xml</str> </searchComponent> - <!-- a request handler utilizing the elevator component --> + <!-- A request handler for demonstrating the elevator component --> <requestHandler name="/elevate" class="solr.SearchHandler" startup="lazy"> <lst name="defaults"> <str name="echoParams">explicit</str> + <str name="df">search_text</str> </lst> <arr name="last-components"> <str>elevator</str> </arr> </requestHandler> + <!-- Highlighting Component - <!-- Update request handler. - - Note: Since solr1.1 requestHandlers requires a valid content type header if posted in - the body. For example, curl now requires: -H 'Content-type:text/xml; charset=utf-8' - The response format differs from solr1.1 formatting and returns a standard error code. - To enable solr1.1 behavior, remove the /update handler or change its path + http://wiki.apache.org/solr/HighlightingParameters --> - <requestHandler name="/update" class="solr.XmlUpdateRequestHandler" /> - - - <requestHandler name="/update/javabin" class="solr.BinaryUpdateRequestHandler" /> - - <!-- - Analysis request handler. Since Solr 1.3. Use to return how a document is analyzed. Useful - for debugging and as a token server for other types of applications. - - This is deprecated in favor of the improved DocumentAnalysisRequestHandler and FieldAnalysisRequestHandler - - <requestHandler name="/analysis" class="solr.AnalysisRequestHandler" /> - --> - - <!-- - An analysis handler that provides a breakdown of the analysis process of provided docuemnts. This handler expects a - (single) content stream with the following format: - - <docs> - <doc> - <field name="id">1</field> - <field name="name">The Name</field> - <field name="text">The Text Value</field> - <doc> - <doc>...</doc> - <doc>...</doc> - ... - </docs> - - Note: Each document must contain a field which serves as the unique key. This key is used in the returned - response to assoicate an analysis breakdown to the analyzed document. - - Like the FieldAnalysisRequestHandler, this handler also supports query analysis by - sending either an "analysis.query" or "q" request paraemter that holds the query text to be analyized. It also - supports the "analysis.showmatch" parameter which when set to true, all field tokens that match the query - tokens will be marked as a "match". - --> - <requestHandler name="/analysis/document" class="solr.DocumentAnalysisRequestHandler" /> + <searchComponent class="solr.HighlightComponent" name="highlight"> + <highlighting> + <!-- Configure the standard fragmenter --> + <!-- This could most likely be commented out in the "default" case --> + <fragmenter name="gap" + default="true" + class="solr.highlight.GapFragmenter"> + <lst name="defaults"> + <int name="hl.fragsize">100</int> + </lst> + </fragmenter> + + <!-- A regular-expression-based fragmenter + (for sentence extraction) + --> + <fragmenter name="regex" + class="solr.highlight.RegexFragmenter"> + <lst name="defaults"> + <!-- slightly smaller fragsizes work better because of slop --> + <int name="hl.fragsize">70</int> + <!-- allow 50% slop on fragment sizes --> + <float name="hl.regex.slop">0.5</float> + <!-- a basic sentence pattern --> + <str name="hl.regex.pattern">[-\w ,/\n\"']{20,200}</str> + </lst> + </fragmenter> + + <!-- Configure the standard formatter --> + <formatter name="html" + default="true" + class="solr.highlight.HtmlFormatter"> + <lst name="defaults"> + <str name="hl.simple.pre"><![CDATA[<em>]]></str> + <str name="hl.simple.post"><![CDATA[</em>]]></str> + </lst> + </formatter> + + <!-- Configure the standard encoder --> + <encoder name="html" + class="solr.highlight.HtmlEncoder" /> + + <!-- Configure the standard fragListBuilder --> + <fragListBuilder name="simple" + class="solr.highlight.SimpleFragListBuilder"/> + + <!-- Configure the single fragListBuilder --> + <fragListBuilder name="single" + class="solr.highlight.SingleFragListBuilder"/> + + <!-- Configure the weighted fragListBuilder --> + <fragListBuilder name="weighted" + default="true" + class="solr.highlight.WeightedFragListBuilder"/> + + <!-- default tag FragmentsBuilder --> + <fragmentsBuilder name="default" + default="true" + class="solr.highlight.ScoreOrderFragmentsBuilder"> + <!-- + <lst name="defaults"> + <str name="hl.multiValuedSeparatorChar">/</str> + </lst> + --> + </fragmentsBuilder> + + <!-- multi-colored tag FragmentsBuilder --> + <fragmentsBuilder name="colored" + class="solr.highlight.ScoreOrderFragmentsBuilder"> + <lst name="defaults"> + <str name="hl.tag.pre"><![CDATA[ + <b style="background:yellow">,<b style="background:lawgreen">, + <b style="background:aquamarine">,<b style="background:magenta">, + <b style="background:palegreen">,<b style="background:coral">, + <b style="background:wheat">,<b style="background:khaki">, + <b style="background:lime">,<b style="background:deepskyblue">]]></str> + <str name="hl.tag.post"><![CDATA[</b>]]></str> + </lst> + </fragmentsBuilder> + + <boundaryScanner name="default" + default="true" + class="solr.highlight.SimpleBoundaryScanner"> + <lst name="defaults"> + <str name="hl.bs.maxScan">10</str> + <str name="hl.bs.chars">.,!? 	 </str> + </lst> + </boundaryScanner> + + <boundaryScanner name="breakIterator" + class="solr.highlight.BreakIteratorBoundaryScanner"> + <lst name="defaults"> + <!-- type should be one of CHARACTER, WORD(default), LINE and SENTENCE --> + <str name="hl.bs.type">WORD</str> + <!-- language and country are used when constructing Locale object. --> + <!-- And the Locale object will be used when getting instance of BreakIterator --> + <str name="hl.bs.language">en</str> + <str name="hl.bs.country">US</str> + </lst> + </boundaryScanner> + </highlighting> + </searchComponent> - <!-- - RequestHandler that provides much the same functionality as analysis.jsp. Provides the ability - to specify multiple field types and field names in the same request and outputs index-time and - query-time analysis for each of them. - - Request parameters are: - analysis.fieldname - The field name whose analyzers are to be used - analysis.fieldtype - The field type whose analyzers are to be used - analysis.fieldvalue - The text for index-time analysis - q (or analysis.q) - The text for query time analysis - analysis.showmatch (true|false) - When set to true and when query analysis is performed, the produced - tokens of the field value analysis will be marked as "matched" for every - token that is produces by the query analysis - --> - <requestHandler name="/analysis/field" class="solr.FieldAnalysisRequestHandler" /> + <!-- Update Processors + Chains of Update Processor Factories for dealing with Update + Requests can be declared, and then used by name in Update + Request Processors - <!-- CSV update handler, loaded on demand --> - <requestHandler name="/update/csv" class="solr.CSVRequestHandler" startup="lazy" /> + http://wiki.apache.org/solr/UpdateRequestProcessor + --> + <!-- Deduplication + An example dedup update processor that creates the "id" field + on the fly based on the hash code of some other fields. This + example has overwriteDupes set to false since we are using the + id field as the signatureField and Solr will maintain + uniqueness based on that anyway. + + --> <!-- - Admin Handlers - This will register all the standard admin RequestHandlers. Adding - this single handler is equivalent to registering: - - <requestHandler name="/admin/luke" class="org.apache.solr.handler.admin.LukeRequestHandler" /> - <requestHandler name="/admin/system" class="org.apache.solr.handler.admin.SystemInfoHandler" /> - <requestHandler name="/admin/plugins" class="org.apache.solr.handler.admin.PluginInfoHandler" /> - <requestHandler name="/admin/threads" class="org.apache.solr.handler.admin.ThreadDumpHandler" /> - <requestHandler name="/admin/properties" class="org.apache.solr.handler.admin.PropertiesRequestHandler" /> - <requestHandler name="/admin/file" class="org.apache.solr.handler.admin.ShowFileRequestHandler" > - - If you wish to hide files under ${solr.home}/conf, explicitly register the ShowFileRequestHandler using: - <requestHandler name="/admin/file" class="org.apache.solr.handler.admin.ShowFileRequestHandler" > - <lst name="invariants"> - <str name="hidden">synonyms.txt</str> - <str name="hidden">anotherfile.txt</str> - </lst> - </requestHandler> - --> - <requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" /> - - <!-- ping/healthcheck --> - <requestHandler name="/admin/ping" class="PingRequestHandler"> - <lst name="defaults"> - <str name="qt">standard</str> - <str name="q">solrpingquery</str> - <str name="echoParams">all</str> - </lst> - </requestHandler> - - <!-- Echo the request contents back to the client --> - <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" > - <lst name="defaults"> - <str name="echoParams">explicit</str> <!-- for all params (including the default etc) use: 'all' --> - <str name="echoHandler">true</str> - </lst> - </requestHandler> + <updateRequestProcessorChain name="dedupe"> + <processor class="solr.processor.SignatureUpdateProcessorFactory"> + <bool name="enabled">true</bool> + <str name="signatureField">id</str> + <bool name="overwriteDupes">false</bool> + <str name="fields">name,features,cat</str> + <str name="signatureClass">solr.processor.Lookup3Signature</str> + </processor> + <processor class="solr.LogUpdateProcessorFactory" /> + <processor class="solr.RunUpdateProcessorFactory" /> + </updateRequestProcessorChain> + --> + + <!-- Language identification + + This example update chain identifies the language of the incoming + documents using the langid contrib. The detected language is + written to field language_s. No field name mapping is done. + The fields used for detection are text, title, subject and description, + making this example suitable for detecting languages form full-text + rich documents injected via ExtractingRequestHandler. + See more about langId at http://wiki.apache.org/solr/LanguageDetection + --> + <!-- + <updateRequestProcessorChain name="langid"> + <processor class="org.apache.solr.update.processor.TikaLanguageIdentifierUpdateProcessorFactory"> + <str name="langid.fl">text,title,subject,description</str> + <str name="langid.langField">language_s</str> + <str name="langid.fallback">en</str> + </processor> + <processor class="solr.LogUpdateProcessorFactory" /> + <processor class="solr.RunUpdateProcessorFactory" /> + </updateRequestProcessorChain> + --> - <highlighting> - <!-- Configure the standard fragmenter --> - <!-- This could most likely be commented out in the "default" case --> - <fragmenter name="gap" class="org.apache.solr.highlight.GapFragmenter" default="true"> - <lst name="defaults"> - <int name="hl.fragsize">100</int> - </lst> - </fragmenter> + <!-- Script update processor - <!-- A regular-expression-based fragmenter (f.i., for sentence extraction) --> - <fragmenter name="regex" class="org.apache.solr.highlight.RegexFragmenter"> - <lst name="defaults"> - <!-- slightly smaller fragsizes work better because of slop --> - <int name="hl.fragsize">70</int> - <!-- allow 50% slop on fragment sizes --> - <float name="hl.regex.slop">0.5</float> - <!-- a basic sentence pattern --> - <str name="hl.regex.pattern">[-\w ,/\n\"']{20,200}</str> - </lst> - </fragmenter> + This example hooks in an update processor implemented using JavaScript. - <!-- Configure the standard formatter --> - <formatter name="html" class="org.apache.solr.highlight.HtmlFormatter" default="true"> - <lst name="defaults"> - <str name="hl.simple.pre"><![CDATA[<em>]]></str> - <str name="hl.simple.post"><![CDATA[</em>]]></str> - </lst> - </formatter> - </highlighting> - - <!-- An example dedup update processor that creates the "id" field on the fly - based on the hash code of some other fields. This example has overwriteDupes - set to false since we are using the id field as the signatureField and Solr - will maintain uniqueness based on that anyway. - - You have to link the chain to an update handler above to use it ie: - <requestHandler name="/update "class="solr.XmlUpdateRequestHandler"> - <lst name="defaults"> - <str name="update.processor">dedupe</str> - </lst> - </requestHandler> + See more about the script update processor at http://wiki.apache.org/solr/ScriptUpdateProcessor --> <!-- - <updateRequestProcessorChain name="dedupe"> - <processor class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory"> - <bool name="enabled">true</bool> - <str name="signatureField">id</str> - <bool name="overwriteDupes">false</bool> - <str name="fields">name,features,cat</str> - <str name="signatureClass">org.apache.solr.update.processor.Lookup3Signature</str> - </processor> - <processor class="solr.LogUpdateProcessorFactory" /> - <processor class="solr.RunUpdateProcessorFactory" /> - </updateRequestProcessorChain> + <updateRequestProcessorChain name="script"> + <processor class="solr.StatelessScriptUpdateProcessorFactory"> + <str name="script">update-script.js</str> + <lst name="params"> + <str name="config_param">example config parameter</str> + </lst> + </processor> + <processor class="solr.RunUpdateProcessorFactory" /> + </updateRequestProcessorChain> --> + + <!-- Response Writers + http://wiki.apache.org/solr/QueryResponseWriter - <!-- queryResponseWriter plugins... query responses will be written using the - writer specified by the 'wt' request parameter matching the name of a registered - writer. - The "default" writer is the default and will be used if 'wt' is not specified - in the request. XMLResponseWriter will be used if nothing is specified here. - The json, python, and ruby writers are also available by default. + Request responses will be written using the writer specified by + the 'wt' request parameter matching the name of a registered + writer. - <queryResponseWriter name="xml" class="org.apache.solr.request.XMLResponseWriter" default="true"/> - <queryResponseWriter name="json" class="org.apache.solr.request.JSONResponseWriter"/> - <queryResponseWriter name="python" class="org.apache.solr.request.PythonResponseWriter"/> - <queryResponseWriter name="ruby" class="org.apache.solr.request.RubyResponseWriter"/> - <queryResponseWriter name="php" class="org.apache.solr.request.PHPResponseWriter"/> - <queryResponseWriter name="phps" class="org.apache.solr.request.PHPSerializedResponseWriter"/> + The "default" writer is the default and will be used if 'wt' is + not specified in the request. + --> + <!-- The following response writers are implicitly configured unless + overridden... + --> + <!-- + <queryResponseWriter name="xml" + default="true" + class="solr.XMLResponseWriter" /> + <queryResponseWriter name="json" class="solr.JSONResponseWriter"/> + <queryResponseWriter name="python" class="solr.PythonResponseWriter"/> + <queryResponseWriter name="ruby" class="solr.RubyResponseWriter"/> + <queryResponseWriter name="php" class="solr.PHPResponseWriter"/> + <queryResponseWriter name="phps" class="solr.PHPSerializedResponseWriter"/> + <queryResponseWriter name="csv" class="solr.CSVResponseWriter"/> + <queryResponseWriter name="schema.xml" class="solr.SchemaXmlResponseWriter"/> + --> - <queryResponseWriter name="custom" class="com.example.MyResponseWriter"/> - --> + <queryResponseWriter name="json" class="solr.JSONResponseWriter"> + <!-- For the purposes of the tutorial, JSON responses are written as + plain text so that they are easy to read in *any* browser. + If you expect a MIME type of "application/json" just remove this override. + --> + <str name="content-type">text/plain; charset=UTF-8</str> + </queryResponseWriter> + + <!-- + Custom response writers can be declared as needed... + --> + <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy"/> + <!-- XSLT response writer transforms the XML output by any xslt file found in Solr's conf/xslt directory. Changes to xslt files are checked for - every xsltCacheLifetimeSeconds. - --> - <queryResponseWriter name="xslt" class="org.apache.solr.request.XSLTResponseWriter"> + every xsltCacheLifetimeSeconds. + --> + <queryResponseWriter name="xslt" class="solr.XSLTResponseWriter"> <int name="xsltCacheLifetimeSeconds">5</int> </queryResponseWriter> + <!-- Query Parsers - <!-- example of registering a query parser - <queryParser name="lucene" class="org.apache.solr.search.LuceneQParserPlugin"/> - --> + http://wiki.apache.org/solr/SolrQuerySyntax - <!-- example of registering a custom function parser - <valueSourceParser name="myfunc" class="com.mycompany.MyValueSourceParser" /> - --> + Multiple QParserPlugins can be registered by name, and then + used in either the "defType" param for the QueryComponent (used + by SearchHandler) or in LocalParams + --> + <!-- example of registering a query parser --> + <!-- + <queryParser name="myparser" class="com.mycompany.MyQParserPlugin"/> + --> - <!-- config for the admin interface --> - <admin> - <defaultQuery>*:*</defaultQuery> + <!-- Function Parsers + + http://wiki.apache.org/solr/FunctionQuery - <!-- configure a healthcheck file for servers behind a loadbalancer - <healthcheck type="file">server-enabled</healthcheck> + Multiple ValueSourceParsers can be registered by name, and then + used as function names when using the "func" QParser. --> - </admin> + <!-- example of registering a custom function parser --> + <!-- + <valueSourceParser name="myfunc" + class="com.mycompany.MyValueSourceParser" /> + --> + + + <!-- Document Transformers + http://wiki.apache.org/solr/DocTransformers + --> + <!-- + Could be something like: + <transformer name="db" class="com.mycompany.LoadFromDatabaseTransformer" > + <int name="connection">jdbc://....</int> + </transformer> + + To add a constant value to all docs, use: + <transformer name="mytrans2" class="org.apache.solr.response.transform.ValueAugmenterFactory" > + <int name="value">5</int> + </transformer> + + If you want the user to still be able to change it with _value:something_ use this: + <transformer name="mytrans3" class="org.apache.solr.response.transform.ValueAugmenterFactory" > + <double name="defaultValue">5</double> + </transformer> + + If you are using the QueryElevationComponent, you may wish to mark documents that get boosted. The + EditorialMarkerFactory will do exactly that: + <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" /> + --> + -</config> + <!-- Legacy config for the admin interface --> + <admin> + <defaultQuery>*:*</defaultQuery> + </admin> +</config> \ No newline at end of file diff --git a/dspace/solr/statistics/conf/schema.xml b/dspace/solr/statistics/conf/schema.xml index a68e579a02a15bf2be298ae3c0d33648bdc6da7d..da41b68a171b06273278a667b5107d2004a77e51 100644 --- a/dspace/solr/statistics/conf/schema.xml +++ b/dspace/solr/statistics/conf/schema.xml @@ -160,15 +160,15 @@ Duplicate tokens at the same position (which may result from Stemmed Synonyms or WordDelim parts) are removed. --> - <fieldType name="text" class="solr.TextField" positionIncrementGap="100"> + <fieldType name="text" class="solr.TextField" positionIncrementGap="100"> <analyzer type="index"> <tokenizer class="solr.WhitespaceTokenizerFactory"/> <!-- in this example, we will only use synonyms at query time <filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/> --> <!-- Case insensitive stop word removal. - enablePositionIncrements=true ensures that a 'gap' is left to - allow for accurate phrase queries. + add enablePositionIncrements=true in both the index and query + analyzers to leave a 'gap' for more accurate phrase queries. --> <filter class="solr.StopFilterFactory" ignoreCase="true" @@ -177,16 +177,20 @@ /> <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/> <filter class="solr.LowerCaseFilterFactory"/> - <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/> + <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> </analyzer> <analyzer type="query"> <tokenizer class="solr.WhitespaceTokenizerFactory"/> <filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/> - <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/> + <filter class="solr.StopFilterFactory" + ignoreCase="true" + words="stopwords.txt" + enablePositionIncrements="true" + /> <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="1"/> <filter class="solr.LowerCaseFilterFactory"/> - <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/> + <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> </analyzer> </fieldType> @@ -201,7 +205,9 @@ <filter class="solr.StopFilterFactory" ignoreCase="true" words="stopwords.txt"/> <filter class="solr.WordDelimiterFilterFactory" generateWordParts="0" generateNumberParts="0" catenateWords="1" catenateNumbers="1" catenateAll="0"/> <filter class="solr.LowerCaseFilterFactory"/> - <filter class="solr.EnglishPorterFilterFactory" protected="protwords.txt"/> + <filter class="solr.SnowballPorterFilterFactory" language="English" protected="protwords.txt"/> + <!-- this filter can remove any duplicate tokens that appear at the same position - sometimes + possible with WordDelimiterFilter in conjuncton with stemming. --> <filter class="solr.RemoveDuplicatesTokenFilterFactory"/> </analyzer> </fieldType> @@ -240,7 +246,7 @@ string matched by the pattern. See the Java Regular Expression documentation for more - infomation on pattern and replacement string syntax. + information on pattern and replacement string syntax. http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/package-summary.html --> @@ -260,6 +266,7 @@ <fields> + <field name="_version_" type="long" indexed="true" stored="true" multiValued="false"/> <!-- Valid attributes for fields: name: mandatory - the name for the field type: mandatory - the name of a previously defined type from the <types> section @@ -297,7 +304,8 @@ <field name="isBot" type="boolean" indexed="true" stored="true" required="false"/> <field name="bundleName" type="string" indexed="true" stored="true" required="false" multiValued="true" /> <field name="referrer" type="string" indexed="true" stored="true" required="false"/> - <field name="uid" type="uuid" indexed="true" stored="true" default="NEW" /> + <!-- use uuid as uniqueKey update processor chain, see solrconfig.xml--> + <field name="uid" type="string" indexed="true" stored="true" required="true" /> <!--Can either be view/search/search_result/workflow--> <field name="statistics_type" type="string" indexed="true" stored="true" required="true" default="view" /> diff --git a/dspace/solr/statistics/conf/solrconfig.xml b/dspace/solr/statistics/conf/solrconfig.xml index 82f0b2898b805c906da67a473bb3013901440094..ed6d7f8c8c8b154f0e4089691c8ba048e8c2bc26 100644 --- a/dspace/solr/statistics/conf/solrconfig.xml +++ b/dspace/solr/statistics/conf/solrconfig.xml @@ -15,562 +15,808 @@ See the License for the specific language governing permissions and limitations under the License. --> -<!-- - For more details about configurations options that may appear in this - file, see http://wiki.apache.org/solr/SolrConfigXml. - Specifically, the Solr Config can support XInclude, which may make it easier to manage - the configuration. See https://issues.apache.org/jira/browse/SOLR-1167 +<!-- + For more details about configurations options that may appear in + this file, see http://wiki.apache.org/solr/SolrConfigXml. --> <config> - <!-- Set this to 'false' if you want solr to continue working after it has - encountered an severe configuration error. In a production environment, - you may want solr to keep working even if one handler is mis-configured. + <!-- In all configuration below, a prefix of "solr." for class names + is an alias that causes solr to search appropriate packages, + including org.apache.solr.(search|update|request|core|analysis) - You may also set this to false using by setting the system property: - -Dsolr.abortOnConfigurationError=false - --> - <abortOnConfigurationError>${solr.abortOnConfigurationError:true}</abortOnConfigurationError> + You may also specify a fully qualified Java classname if you + have your own custom plugins. + --> - <!-- lib directives can be used to instruct Solr to load an Jars identified - and use them to resolve any "plugins" specified in your solrconfig.xml or - schema.xml (ie: Analyzers, Request Handlers, etc...). + <!-- Controls what version of Lucene various components of Solr + adhere to. Generally, you want to use the latest version to + get all bug fixes and improvements. It is highly recommended + that you fully re-index after changing this setting as it can + affect both how text is indexed and queried. + --> + <luceneMatchVersion>4.4</luceneMatchVersion> + + <!-- <lib/> directives can be used to instruct Solr to load an Jars + identified and use them to resolve any "plugins" specified in + your solrconfig.xml or schema.xml (ie: Analyzers, Request + Handlers, etc...). + + All directories and paths are resolved relative to the + instanceDir. + + Please note that <lib/> directives are processed in the order + that they appear in your solrconfig.xml file, and are "stacked" + on top of each other when building a ClassLoader - so if you have + plugin jars with dependencies on other jars, the "lower level" + dependency jars should be loaded first. + + If a "./lib" directory exists in your instanceDir, all files + found in it are included as if you had used the following + syntax... + + <lib dir="./lib" /> + --> - All directories and paths are resolved relative the instanceDir. + <!-- A 'dir' option by itself adds any files found in the directory + to the classpath, this is useful for including all jars in a + directory. - If a "./lib" directory exists in your instanceDir, all files found in it - are included as if you had used the following syntax... + When a 'regex' is specified in addition to a 'dir', only the + files in that directory which completely match the regex + (anchored on both ends) will be included. - <lib dir="./lib" /> - --> - <!-- A dir option by itself adds any files found in the directory to the - classpath, this is useful for including all jars in a directory. - --> - <lib dir="../../contrib/extraction/lib" /> - <!-- When a regex is specified in addition to a directory, only the files in that - directory which completely match the regex (anchored on both ends) - will be included. - --> - <lib dir="../../dist/" regex="apache-solr-cell-\d.*\.jar" /> - <lib dir="../../dist/" regex="apache-solr-clustering-\d.*\.jar" /> - <!-- If a dir option (with or without a regex) is used and nothing is found - that matches, it will be ignored - --> - <lib dir="../../contrib/clustering/lib/downloads/" /> - <lib dir="../../contrib/clustering/lib/" /> - <lib dir="/total/crap/dir/ignored" /> - <!-- an exact path can be used to specify a specific file. This will cause - a serious error to be logged if it can't be loaded. - <lib path="../a-jar-that-does-not-exist.jar" /> - --> + If a 'dir' option (with or without a regex) is used and nothing + is found that matches, a warning will be logged. + The examples below can be used to load some solr-contribs along + with their external dependencies. + --> + <lib dir="../../../contrib/extraction/lib" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-cell-\d.*\.jar" /> - <!-- Used to specify an alternate directory to hold all index data - other than the default ./data under the Solr home. - If replication is in use, this should match the replication configuration. --> - <!--<dataDir>${solr.data.dir:./solr/data}</dataDir>--> + <lib dir="../../../contrib/clustering/lib/" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-clustering-\d.*\.jar" /> + <lib dir="../../../contrib/langid/lib/" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-langid-\d.*\.jar" /> - <!-- WARNING: this <indexDefaults> section only provides defaults for index writers - in general. See also the <mainIndex> section after that when changing parameters - for Solr's main Lucene index. --> - <indexDefaults> - <!-- Values here affect all index writers and act as a default unless overridden. --> - <useCompoundFile>false</useCompoundFile> + <lib dir="../../../contrib/velocity/lib" regex=".*\.jar" /> + <lib dir="../../../dist/" regex="solr-velocity-\d.*\.jar" /> - <mergeFactor>10</mergeFactor> - <!-- If both ramBufferSizeMB and maxBufferedDocs is set, then Lucene will flush - based on whichever limit is hit first. --> - <!--<maxBufferedDocs>1000</maxBufferedDocs>--> - - <!-- Sets the amount of RAM that may be used by Lucene indexing - for buffering added documents and deletions before they are - flushed to the Directory. --> - <ramBufferSizeMB>32</ramBufferSizeMB> - <!-- <maxMergeDocs>2147483647</maxMergeDocs> --> - <maxFieldLength>10000</maxFieldLength> - <writeLockTimeout>1000</writeLockTimeout> - <commitLockTimeout>10000</commitLockTimeout> + <!-- an exact 'path' can be used instead of a 'dir' to specify a + specific jar file. This will cause a serious error to be logged + if it can't be loaded. + --> + <!-- + <lib path="../a-jar-that-does-not-exist.jar" /> + --> + + <!-- Data Directory - <!-- - Expert: Turn on Lucene's auto commit capability. This causes intermediate - segment flushes to write a new lucene index descriptor, enabling it to be - opened by an external IndexReader. This can greatly slow down indexing - speed. NOTE: Despite the name, this value does not have any relation to - Solr's autoCommit functionality - --> - <!--<luceneAutoCommit>false</luceneAutoCommit>--> + Used to specify an alternate directory to hold all index data + other than the default ./data under the Solr home. If + replication is in use, this should match the replication + configuration. + --> + <dataDir>${solr.data.dir:}</dataDir> - <!-- - Expert: The Merge Policy in Lucene controls how merging is handled by - Lucene. The default in 2.3 is the LogByteSizeMergePolicy, previous - versions used LogDocMergePolicy. - LogByteSizeMergePolicy chooses segments to merge based on their size. The - Lucene 2.2 default, LogDocMergePolicy chose when to merge based on number - of documents + <!-- The DirectoryFactory to use for indexes. + + solr.StandardDirectoryFactory is filesystem + based and tries to pick the best implementation for the current + JVM and platform. solr.NRTCachingDirectoryFactory, the default, + wraps solr.StandardDirectoryFactory and caches small files in memory + for better NRT performance. - Other implementations of MergePolicy must have a no-argument constructor - --> - <!--<mergePolicy class="org.apache.lucene.index.LogByteSizeMergePolicy"/>--> + One can force a particular implementation via solr.MMapDirectoryFactory, + solr.NIOFSDirectoryFactory, or solr.SimpleFSDirectoryFactory. + solr.RAMDirectoryFactory is memory based, not + persistent, and doesn't work with replication. + --> + <directoryFactory name="DirectoryFactory" + class="${solr.directoryFactory:solr.NRTCachingDirectoryFactory}"/> + + <!-- The CodecFactory for defining the format of the inverted index. + The default implementation is SchemaCodecFactory, which is the official Lucene + index format, but hooks into the schema to provide per-field customization of + the postings lists and per-document values in the fieldType element + (postingsFormat/docValuesFormat). Note that most of the alternative implementations + are experimental, so if you choose to customize the index format, its a good + idea to convert back to the official format e.g. via IndexWriter.addIndexes(IndexReader) + before upgrading to a newer version to avoid unnecessary reindexing. + --> + <codecFactory class="solr.SchemaCodecFactory"/> + + <!-- To enable dynamic schema REST APIs, use the following for <schemaFactory>: + + <schemaFactory class="ManagedIndexSchemaFactory"> + <bool name="mutable">true</bool> + <str name="managedSchemaResourceName">managed-schema</str> + </schemaFactory> + + When ManagedIndexSchemaFactory is specified, Solr will load the schema from + he resource named in 'managedSchemaResourceName', rather than from schema.xml. + Note that the managed schema resource CANNOT be named schema.xml. If the managed + schema does not exist, Solr will create it after reading schema.xml, then rename + 'schema.xml' to 'schema.xml.bak'. + + Do NOT hand edit the managed schema - external modifications will be ignored and + overwritten as a result of schema modification REST API calls. + + When ManagedIndexSchemaFactory is specified with mutable = true, schema + modification REST API calls will be allowed; otherwise, error responses will be + sent back for these requests. + --> + <schemaFactory class="ClassicIndexSchemaFactory"/> + + <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Index Config - These settings control low-level behavior of indexing + Most example settings here show the default value, but are commented + out, to more easily see where customizations have been made. + + Note: This replaces <indexDefaults> and <mainIndex> from older versions + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> + <indexConfig> + <!-- maxFieldLength was removed in 4.0. To get similar behavior, include a + LimitTokenCountFilterFactory in your fieldType definition. E.g. + <filter class="solr.LimitTokenCountFilterFactory" maxTokenCount="10000"/> + --> + <!-- Maximum time to wait for a write lock (ms) for an IndexWriter. Default: 1000 --> + <!-- <writeLockTimeout>1000</writeLockTimeout> --> + + <!-- The maximum number of simultaneous threads that may be + indexing documents at once in IndexWriter; if more than this + many threads arrive they will wait for others to finish. + Default in Solr/Lucene is 8. --> + <!-- <maxIndexingThreads>8</maxIndexingThreads> --> + + <!-- Expert: Enabling compound file will use less files for the index, + using fewer file descriptors on the expense of performance decrease. + Default in Lucene is "true". Default in Solr is "false" (since 3.6) --> + <!-- <useCompoundFile>false</useCompoundFile> --> + + <!-- ramBufferSizeMB sets the amount of RAM that may be used by Lucene + indexing for buffering added documents and deletions before they are + flushed to the Directory. + maxBufferedDocs sets a limit on the number of documents buffered + before flushing. + If both ramBufferSizeMB and maxBufferedDocs is set, then + Lucene will flush based on whichever limit is hit first. + The default is 100 MB. --> + <ramBufferSizeMB>32</ramBufferSizeMB> + <maxBufferedDocs>1000</maxBufferedDocs> + + <!-- Expert: Merge Policy + The Merge Policy in Lucene controls how merging of segments is done. + The default since Solr/Lucene 3.3 is TieredMergePolicy. + The default since Lucene 2.3 was the LogByteSizeMergePolicy, + Even older versions of Lucene used LogDocMergePolicy. + --> <!-- - Expert: - The Merge Scheduler in Lucene controls how merges are performed. The - ConcurrentMergeScheduler (Lucene 2.3 default) can perform merges in the - background using separate threads. The SerialMergeScheduler (Lucene 2.2 - default) does not. + <mergePolicy class="org.apache.lucene.index.TieredMergePolicy"> + <int name="maxMergeAtOnce">10</int> + <int name="segmentsPerTier">10</int> + </mergePolicy> + --> + + <!-- Merge Factor + The merge factor controls how many segments will get merged at a time. + For TieredMergePolicy, mergeFactor is a convenience parameter which + will set both MaxMergeAtOnce and SegmentsPerTier at once. + For LogByteSizeMergePolicy, mergeFactor decides how many new segments + will be allowed before they are merged into one. + Default is 10 for both merge policies. + --> + <!-- + <mergeFactor>10</mergeFactor> + --> + + <!-- Expert: Merge Scheduler + The Merge Scheduler in Lucene controls how merges are + performed. The ConcurrentMergeScheduler (Lucene 2.3 default) + can perform merges in the background using separate threads. + The SerialMergeScheduler (Lucene 2.2 default) does not. --> - <!--<mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/>--> + <!-- + <mergeScheduler class="org.apache.lucene.index.ConcurrentMergeScheduler"/> + --> + <!-- LockFactory - <!-- - This option specifies which Lucene LockFactory implementation to use. + This option specifies which Lucene LockFactory implementation + to use. + + single = SingleInstanceLockFactory - suggested for a + read-only index or when there is no possibility of + another process trying to modify the index. + native = NativeFSLockFactory - uses OS native file locking. + Do not use when multiple solr webapps in the same + JVM are attempting to share a single index. + simple = SimpleFSLockFactory - uses a plain file for locking - single = SingleInstanceLockFactory - suggested for a read-only index - or when there is no possibility of another process trying - to modify the index. - native = NativeFSLockFactory - uses OS native file locking - simple = SimpleFSLockFactory - uses a plain file for locking + Defaults: 'native' is default for Solr3.6 and later, otherwise + 'simple' is the default - (For backwards compatibility with Solr 1.2, 'simple' is the default - if not specified.) + More details on the nuances of each LockFactory... + http://wiki.apache.org/lucene-java/AvailableLockFactories --> - <lockType>native</lockType> - <!-- - Expert: - Controls how often Lucene loads terms into memory --> - <!--<termIndexInterval>256</termIndexInterval>--> - </indexDefaults> - - <mainIndex> - <!-- options specific to the main on-disk lucene index --> - <useCompoundFile>false</useCompoundFile> - <ramBufferSizeMB>32</ramBufferSizeMB> - <mergeFactor>10</mergeFactor> - <!-- Deprecated --> - <!--<maxBufferedDocs>1000</maxBufferedDocs>--> - <!--<maxMergeDocs>2147483647</maxMergeDocs>--> + <lockType>${solr.lock.type:native}</lockType> - <!-- inherit from indexDefaults <maxFieldLength>10000</maxFieldLength> --> + <!-- Unlock On Startup - <!-- If true, unlock any held write or commit locks on startup. + If true, unlock any held write or commit locks on startup. This defeats the locking mechanism that allows multiple - processes to safely access a lucene index, and should be - used with care. - This is not needed if lock type is 'none' or 'single' + processes to safely access a lucene index, and should be used + with care. Default is "false". + + This is not needed if lock type is 'single' --> + <!-- <unlockOnStartup>false</unlockOnStartup> + --> + + <!-- Expert: Controls how often Lucene loads terms into memory + Default is 128 and is likely good for most everyone. + --> + <!-- <termIndexInterval>128</termIndexInterval> --> - <!-- If true, IndexReaders will be reopened (often more efficient) instead - of closed and then opened. --> + <!-- If true, IndexReaders will be reopened (often more efficient) + instead of closed and then opened. Default: true + --> + <!-- <reopenReaders>true</reopenReaders> + --> - <!-- - Expert: - Controls how often Lucene loads terms into memory. Default is 128 and is likely good for most everyone. --> - <!--<termIndexInterval>256</termIndexInterval>--> - - <!-- - Custom deletion policies can specified here. The class must - implement org.apache.lucene.index.IndexDeletionPolicy. - - http://lucene.apache.org/java/2_3_2/api/org/apache/lucene/index/IndexDeletionPolicy.html - - The standard Solr IndexDeletionPolicy implementation supports deleting - index commit points on number of commits, age of commit point and - optimized status. + <!-- Commit Deletion Policy + Custom deletion policies can be specified here. The class must + implement org.apache.lucene.index.IndexDeletionPolicy. - The latest commit point should always be preserved regardless - of the criteria. + The default Solr IndexDeletionPolicy implementation supports + deleting index commit points on number of commits, age of + commit point and optimized status. + + The latest commit point should always be preserved regardless + of the criteria. --> + <!-- <deletionPolicy class="solr.SolrDeletionPolicy"> + --> <!-- The number of commit points to be kept --> - <str name="maxCommitsToKeep">1</str> + <!-- <str name="maxCommitsToKeep">1</str> --> <!-- The number of optimized commit points to be kept --> - <str name="maxOptimizedCommitsToKeep">0</str> + <!-- <str name="maxOptimizedCommitsToKeep">0</str> --> <!-- Delete all commit points once they have reached the given age. Supports DateMathParser syntax e.g. - - <str name="maxCommitAge">30MINUTES</str> - <str name="maxCommitAge">1DAY</str> + --> + <!-- + <str name="maxCommitAge">30MINUTES</str> + <str name="maxCommitAge">1DAY</str> --> + <!-- </deletionPolicy> + --> - <!-- To aid in advanced debugging, you may turn on IndexWriter debug logging. - Setting to true will set the file that the underlying Lucene IndexWriter - will write its debug infostream to. --> - <infoStream file="INFOSTREAM.txt">false</infoStream> - - </mainIndex> + <!-- Lucene Infostream + + To aid in advanced debugging, Lucene provides an "InfoStream" + of detailed information when indexing. - <!-- Enables JMX if and only if an existing MBeanServer is found, use this - if you want to configure JMX through JVM parameters. Remove this to disable - exposing Solr configuration and statistics to JMX. + Setting the value to true will instruct the underlying Lucene + IndexWriter to write its info stream to solr's log. By default, + this is enabled here, and controlled through log4j.properties. + --> + <infoStream>true</infoStream> + </indexConfig> - If you want to connect to a particular server, specify the agentId - e.g. <jmx agentId="myAgent" /> - If you want to start a new MBeanServer, specify the serviceUrl - e.g <jmx serviceUrl="service:jmx:rmi:///jndi/rmi://localhost:9999/solr"/> + <!-- JMX + + This example enables JMX if and only if an existing MBeanServer + is found, use this if you want to configure JMX through JVM + parameters. Remove this to disable exposing Solr configuration + and statistics to JMX. - For more details see http://wiki.apache.org/solr/SolrJmx - --> + For more details see http://wiki.apache.org/solr/SolrJmx + --> <jmx /> + <!-- If you want to connect to a particular server, specify the + agentId + --> + <!-- <jmx agentId="myAgent" /> --> + <!-- If you want to start a new MBeanServer, specify the serviceUrl --> + <!-- <jmx serviceUrl="service:jmx:rmi:///jndi/rmi://localhost:9999/solr"/> + --> - <!-- the default high-performance update handler --> + <!-- The default high-performance update handler --> <updateHandler class="solr.DirectUpdateHandler2"> - <!-- A prefix of "solr." for class names is an alias that - causes solr to search appropriate packages, including - org.apache.solr.(search|update|request|core|analysis) - --> - <!-- Perform a <commit/> automatically under certain conditions: - maxDocs - number of updates since last commit is greater than this - maxTime - oldest uncommited update (in ms) is this long ago - --> - <autoCommit> - <maxDocs>10000</maxDocs> <!--Commit every 10.000 documents--> - <maxTime>900000</maxTime> <!--Commit every 15 minutes--> - </autoCommit> + <!-- Enables a transaction log, used for real-time get, durability, and + and solr cloud replica recovery. The log can grow as big as + uncommitted changes to the index, so use of a hard autoCommit + is recommended (see below). + "dir" - the target directory for transaction logs, defaults to the + solr data directory. --> + <updateLog> + <str name="dir">${solr.ulog.dir:}</str> + </updateLog> + + <!-- AutoCommit + + Perform a hard commit automatically under certain conditions. + Instead of enabling autoCommit, consider using "commitWithin" + when adding documents. + + http://wiki.apache.org/solr/UpdateXmlMessages + + maxDocs - Maximum number of documents to add since the last + commit before automatically triggering a new commit. + + maxTime - Maximum amount of time in ms that is allowed to pass + since a document was added before automatically + triggering a new commit. + openSearcher - if false, the commit causes recent index changes + to be flushed to stable storage, but does not cause a new + searcher to be opened to make those changes visible. + + If the updateLog is enabled, then it's highly recommended to + have some sort of hard autoCommit to limit the log size. + --> + <autoCommit> + <maxDocs>10000</maxDocs> <!--Commit every 10.000 documents--> + <maxTime>${solr.autoCommit.maxTime:900000}</maxTime> <!--Default commit every 15 minutes--> + <openSearcher>true</openSearcher> + </autoCommit> + + <!-- softAutoCommit is like autoCommit except it causes a + 'soft' commit which only ensures that changes are visible + but does not ensure that data is synced to disk. This is + faster and more near-realtime friendly than a hard commit. + --> + <autoSoftCommit> + <maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime> + </autoSoftCommit> + <!-- Update Related Event Listeners + + Various IndexWriter related events can trigger Listeners to + take actions. + + postCommit - fired after every commit or optimize command + postOptimize - fired after every optimize command + --> <!-- The RunExecutableListener executes an external command from a - hook such as postCommit or postOptimize. + hook such as postCommit or postOptimize. + exe - the name of the executable to run - dir - dir to use as the current working directory. default="." - wait - the calling thread waits until the executable returns. default="true" - args - the arguments to pass to the program. default=nothing - env - environment variables to set. default=nothing + dir - dir to use as the current working directory. (default=".") + wait - the calling thread waits until the executable returns. + (default="true") + args - the arguments to pass to the program. (default is none) + env - environment variables to set. (default is none) + --> + <!-- This example shows how RunExecutableListener could be used + with the script based replication... + http://wiki.apache.org/solr/CollectionDistribution + --> + <!-- + <listener event="postCommit" class="solr.RunExecutableListener"> + <str name="exe">solr/bin/snapshooter</str> + <str name="dir">.</str> + <bool name="wait">true</bool> + <arr name="args"> <str>arg1</str> <str>arg2</str> </arr> + <arr name="env"> <str>MYVAR=val1</str> </arr> + </listener> --> - <!-- A postCommit event is fired after every commit or optimize command - <listener event="postCommit" class="solr.RunExecutableListener"> - <str name="exe">solr/bin/snapshooter</str> - <str name="dir">.</str> - <bool name="wait">true</bool> - <arr name="args"> <str>arg1</str> <str>arg2</str> </arr> - <arr name="env"> <str>MYVAR=val1</str> </arr> - </listener> - --> - <!-- A postOptimize event is fired only after every optimize command - <listener event="postOptimize" class="solr.RunExecutableListener"> - <str name="exe">snapshooter</str> - <str name="dir">solr/bin</str> - <bool name="wait">true</bool> - </listener> - --> </updateHandler> - <!-- Use the following format to specify a custom IndexReaderFactory - allows for alternate - IndexReader implementations. + + <!-- IndexReaderFactory + + Use the following format to specify a custom IndexReaderFactory, + which allows for alternate IndexReader implementations. ** Experimental Feature ** - Please note - Using a custom IndexReaderFactory may prevent certain other features - from working. The API to IndexReaderFactory may change without warning or may even - be removed from future releases if the problems cannot be resolved. + + Please note - Using a custom IndexReaderFactory may prevent + certain other features from working. The API to + IndexReaderFactory may change without warning or may even be + removed from future releases if the problems cannot be + resolved. + ** Features that may not work with custom IndexReaderFactory ** - The ReplicationHandler assumes a disk-resident index. Using a custom - IndexReader implementation may cause incompatibility with ReplicationHandler and - may cause replication to not work correctly. See SOLR-1366 for details. + The ReplicationHandler assumes a disk-resident index. Using a + custom IndexReader implementation may cause incompatibility + with ReplicationHandler and may cause replication to not work + correctly. See SOLR-1366 for details. + + --> + <!-- <indexReaderFactory name="IndexReaderFactory" class="package.class"> - Parameters as required by the implementation + <str name="someArg">Some Value</str> </indexReaderFactory > --> - <!-- To set the termInfosIndexDivisor, do this: --> - <!--<indexReaderFactory name="IndexReaderFactory" class="org.apache.solr.core.StandardIndexReaderFactory"> - <int name="termInfosIndexDivisor">12</int> - </indexReaderFactory >--> + <!-- By explicitly declaring the Factory, the termIndexDivisor can + be specified. + --> + <!-- + <indexReaderFactory name="IndexReaderFactory" + class="solr.StandardIndexReaderFactory"> + <int name="setTermIndexDivisor">12</int> + </indexReaderFactory > + --> + <!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Query section - these settings control query time things like caches + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --> <query> - <!-- Maximum number of clauses in a boolean query... in the past, this affected - range or prefix queries that expanded to big boolean queries - built in Solr - query parsers no longer create queries with this limitation. - An exception is thrown if exceeded. --> + <!-- Max Boolean Clauses + + Maximum number of clauses in each BooleanQuery, an exception + is thrown if exceeded. + + ** WARNING ** + + This option actually modifies a global Lucene property that + will affect all SolrCores. If multiple solrconfig.xml files + disagree on this property, the value at any given moment will + be based on the last SolrCore to be initialized. + + --> <maxBooleanClauses>1024</maxBooleanClauses> - <!-- There are two implementations of cache available for Solr, + <!-- Solr Internal Query Caches + + There are two implementations of cache available for Solr, LRUCache, based on a synchronized LinkedHashMap, and - FastLRUCache, based on a ConcurrentHashMap. FastLRUCache has faster gets - and slower puts in single threaded operation and thus is generally faster - than LRUCache when the hit ratio of the cache is high (> 75%), and may be - faster under other scenarios on multi-cpu systems. --> - <!-- Cache used by SolrIndexSearcher for filters (DocSets), - unordered sets of *all* documents that match a query. - When a new searcher is opened, its caches may be prepopulated - or "autowarmed" using data from caches in the old searcher. - autowarmCount is the number of items to prepopulate. For LRUCache, - the autowarmed items will be the most recently accessed items. - Parameters: - class - the SolrCache implementation LRUCache or FastLRUCache - size - the maximum number of entries in the cache - initialSize - the initial capacity (number of entries) of - the cache. (seel java.util.HashMap) - autowarmCount - the number of entries to prepopulate from - and old cache. - --> - <filterCache - class="solr.FastLRUCache" - size="512" - initialSize="512" - autowarmCount="0"/> - - <!-- Cache used to hold field values that are quickly accessible + FastLRUCache, based on a ConcurrentHashMap. + + FastLRUCache has faster gets and slower puts in single + threaded operation and thus is generally faster than LRUCache + when the hit ratio of the cache is high (> 75%), and may be + faster under other scenarios on multi-cpu systems. + --> + + <!-- Filter Cache + + Cache used by SolrIndexSearcher for filters (DocSets), + unordered sets of *all* documents that match a query. When a + new searcher is opened, its caches may be prepopulated or + "autowarmed" using data from caches in the old searcher. + autowarmCount is the number of items to prepopulate. For + LRUCache, the autowarmed items will be the most recently + accessed items. + + Parameters: + class - the SolrCache implementation LRUCache or + (LRUCache or FastLRUCache) + size - the maximum number of entries in the cache + initialSize - the initial capacity (number of entries) of + the cache. (see java.util.HashMap) + autowarmCount - the number of entries to prepopulate from + and old cache. + --> + <filterCache class="solr.FastLRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + + <!-- Query Result Cache + + Caches results of searches - ordered lists of document ids + (DocList) based on a query, a sort, and the range of documents requested. + --> + <queryResultCache class="solr.LRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + + <!-- Document Cache + + Caches Lucene Document objects (the stored fields for each + document). Since Lucene internal document ids are transient, + this cache will not be autowarmed. + --> + <documentCache class="solr.LRUCache" + size="512" + initialSize="512" + autowarmCount="0"/> + + <!-- Field Value Cache + + Cache used to hold field values that are quickly accessible by document id. The fieldValueCache is created by default even if not configured here. - <fieldValueCache - class="solr.FastLRUCache" - size="512" - autowarmCount="128" - showItems="32" - /> - --> + --> + <!-- + <fieldValueCache class="solr.FastLRUCache" + size="512" + autowarmCount="128" + showItems="32" /> + --> - <!-- queryResultCache caches results of searches - ordered lists of - document ids (DocList) based on a query, a sort, and the range - of documents requested. --> - <queryResultCache - class="solr.LRUCache" - size="512" - initialSize="512" - autowarmCount="0"/> - - <!-- documentCache caches Lucene Document objects (the stored fields for each document). - Since Lucene internal document ids are transient, this cache will not be autowarmed. --> - <documentCache - class="solr.LRUCache" - size="512" - initialSize="512" - autowarmCount="0"/> - - <!-- If true, stored fields that are not requested will be loaded lazily. - This can result in a significant speed improvement if the usual case is to - not load all stored fields, especially if the skipped fields are large - compressed text fields. - --> - <enableLazyFieldLoading>true</enableLazyFieldLoading> + <!-- Custom Cache - <!-- Example of a generic cache. These caches may be accessed by name - through SolrIndexSearcher.getCache(),cacheLookup(), and cacheInsert(). - The purpose is to enable easy caching of user/application level data. - The regenerator argument should be specified as an implementation - of solr.search.CacheRegenerator if autowarming is desired. --> + Example of a generic cache. These caches may be accessed by + name through SolrIndexSearcher.getCache(),cacheLookup(), and + cacheInsert(). The purpose is to enable easy caching of + user/application level data. The regenerator argument should + be specified as an implementation of solr.CacheRegenerator + if autowarming is desired. + --> <!-- - <cache name="myUserCache" - class="solr.LRUCache" - size="4096" - initialSize="1024" - autowarmCount="1024" - regenerator="org.mycompany.mypackage.MyRegenerator" - /> - --> + <cache name="myUserCache" + class="solr.LRUCache" + size="4096" + initialSize="1024" + autowarmCount="1024" + regenerator="com.mycompany.MyRegenerator" + /> + --> - <!-- An optimization that attempts to use a filter to satisfy a search. - If the requested sort does not include score, then the filterCache - will be checked for a filter matching the query. If found, the filter - will be used as the source of document ids, and then the sort will be - applied to that. - <useFilterForSortedQuery>true</useFilterForSortedQuery> - --> - <!-- An optimization for use with the queryResultCache. When a search - is requested, a superset of the requested number of document ids - are collected. For example, if a search for a particular query - requests matching documents 10 through 19, and queryWindowSize is 50, - then documents 0 through 49 will be collected and cached. Any further - requests in that range can be satisfied via the cache. --> - <queryResultWindowSize>20</queryResultWindowSize> - - <!-- Maximum number of documents to cache for any entry in the - queryResultCache. --> - <queryResultMaxDocsCached>200</queryResultMaxDocsCached> - - <!-- a newSearcher event is fired whenever a new searcher is being prepared - and there is a current searcher handling requests (aka registered). - It can be used to prime certain caches to prevent long request times for - certain requests. + <!-- Lazy Field Loading + + If true, stored fields that are not requested will be loaded + lazily. This can result in a significant speed improvement + if the usual case is to not load all stored fields, + especially if the skipped fields are large compressed text + fields. --> + <enableLazyFieldLoading>true</enableLazyFieldLoading> + + <!-- Use Filter For Sorted Query + + A possible optimization that attempts to use a filter to + satisfy a search. If the requested sort does not include + score, then the filterCache will be checked for a filter + matching the query. If found, the filter will be used as the + source of document ids, and then the sort will be applied to + that. + + For most situations, this will not be useful unless you + frequently get the same search repeatedly with different sort + options, and none of them ever use "score" + --> + <!-- + <useFilterForSortedQuery>true</useFilterForSortedQuery> + --> + + <!-- Result Window Size + + An optimization for use with the queryResultCache. When a search + is requested, a superset of the requested number of document ids + are collected. For example, if a search for a particular query + requests matching documents 10 through 19, and queryWindowSize is 50, + then documents 0 through 49 will be collected and cached. Any further + requests in that range can be satisfied via the cache. + --> + <queryResultWindowSize>20</queryResultWindowSize> + + <!-- Maximum number of documents to cache for any entry in the + queryResultCache. + --> + <queryResultMaxDocsCached>200</queryResultMaxDocsCached> + + <!-- Query Related Event Listeners + + Various IndexSearcher related events can trigger Listeners to + take actions. + + newSearcher - fired whenever a new searcher is being prepared + and there is a current searcher handling requests (aka + registered). It can be used to prime certain caches to + prevent long request times for certain requests. + + firstSearcher - fired whenever a new searcher is being + prepared but there is no current registered searcher to handle + requests or to gain autowarming data from. + + + --> <!-- QuerySenderListener takes an array of NamedList and executes a - local query request for each NamedList in sequence. --> + local query request for each NamedList in sequence. + --> <listener event="newSearcher" class="solr.QuerySenderListener"> <arr name="queries"> <!-- - <lst> <str name="q">solr</str> <str name="start">0</str> <str name="rows">10</str> </lst> - <lst> <str name="q">rocks</str> <str name="start">0</str> <str name="rows">10</str> </lst> - <lst><str name="q">static newSearcher warming query from solrconfig.xml</str></lst> - --> + <lst><str name="q">solr</str><str name="sort">price asc</str></lst> + <lst><str name="q">rocks</str><str name="sort">weight asc</str></lst> + --> </arr> </listener> - - <!-- a firstSearcher event is fired whenever a new searcher is being - prepared but there is no current registered searcher to handle - requests or to gain autowarming data from. --> <listener event="firstSearcher" class="solr.QuerySenderListener"> <arr name="queries"> - <lst> <str name="q">solr rocks</str><str name="start">0</str><str name="rows">10</str></lst> - <lst><str name="q">static firstSearcher warming query from solrconfig.xml</str></lst> + <lst> + <str name="q">static firstSearcher warming in solrconfig.xml</str> + </lst> </arr> </listener> - <!-- If a search request comes in and there is no current registered searcher, - then immediately register the still warming searcher and use it. If - "false" then all requests will block until the first searcher is done - warming. --> + <!-- Use Cold Searcher + + If a search request comes in and there is no current + registered searcher, then immediately register the still + warming searcher and use it. If "false" then all requests + will block until the first searcher is done warming. + --> <useColdSearcher>false</useColdSearcher> - <!-- Maximum number of searchers that may be warming in the background - concurrently. An error is returned if this limit is exceeded. Recommend - 1-2 for read-only slaves, higher for masters w/o cache warming. --> + <!-- Max Warming Searchers + + Maximum number of searchers that may be warming in the + background concurrently. An error is returned if this limit + is exceeded. + + Recommend values of 1-2 for read-only slaves, higher for + masters w/o cache warming. + --> <maxWarmingSearchers>2</maxWarmingSearchers> </query> + + <!-- Request Dispatcher - <!-- - Let the dispatch filter handler /select?qt=XXX - handleSelect=true will use consistent error handling for /select and /update - handleSelect=false will use solr1.1 style error formatting - --> - <requestDispatcher handleSelect="true" > - <!--Make sure your system has some authentication before enabling remote streaming! --> - <requestParsers enableRemoteStreaming="true" multipartUploadLimitInKB="2048000" /> + This section contains instructions for how the SolrDispatchFilter + should behave when processing requests for this SolrCore. - <!-- Set HTTP caching related parameters (for proxy caches and clients). + handleSelect is a legacy option that affects the behavior of requests + such as /select?qt=XXX - To get the behaviour of Solr 1.2 (ie: no caching related headers) - use the never304="true" option and do not specify a value for - <cacheControl> - --> - <!-- <httpCaching never304="true"> --> - <httpCaching lastModifiedFrom="openTime" - etagSeed="Solr"> - <!-- lastModFrom="openTime" is the default, the Last-Modified value - (and validation against If-Modified-Since requests) will all be - relative to when the current Searcher was opened. - You can change it to lastModFrom="dirLastMod" if you want the - value to exactly corrispond to when the physical index was last - modified. - - etagSeed="..." is an option you can change to force the ETag - header (and validation against If-None-Match requests) to be - differnet even if the index has not changed (ie: when making - significant changes to your config file) - - lastModifiedFrom and etagSeed are both ignored if you use the - never304="true" option. - --> - <!-- If you include a <cacheControl> directive, it will be used to - generate a Cache-Control header, as well as an Expires header - if the value contains "max-age=" + handleSelect="true" will cause the SolrDispatchFilter to process + the request and dispatch the query to a handler specified by the + "qt" param, assuming "/select" isn't already registered. - By default, no Cache-Control header is generated. + handleSelect="false" will cause the SolrDispatchFilter to + ignore "/select" requests, resulting in a 404 unless a handler + is explicitly registered with the name "/select" - You can use the <cacheControl> option even if you have set - never304="true" - --> - <!-- <cacheControl>max-age=30, public</cacheControl> --> - </httpCaching> + handleSelect="true" is not recommended for new users, but is the default + for backwards compatibility + --> + <requestDispatcher handleSelect="false" > + <!-- Request Parsing + + These settings indicate how Solr Requests may be parsed, and + what restrictions may be placed on the ContentStreams from + those requests + + enableRemoteStreaming - enables use of the stream.file + and stream.url parameters for specifying remote streams. + + multipartUploadLimitInKB - specifies the max size (in KiB) of + Multipart File Uploads that Solr will allow in a Request. + + formdataUploadLimitInKB - specifies the max size (in KiB) of + form data (application/x-www-form-urlencoded) sent via + POST. You can use POST to pass request parameters not + fitting into the URL. + + addHttpRequestToContext - if set to true, it will instruct + the requestParsers to include the original HttpServletRequest + object in the context map of the SolrQueryRequest under the + key "httpRequest". It will not be used by any of the existing + Solr components, but may be useful when developing custom + plugins. + + *** WARNING *** + The settings below authorize Solr to fetch remote files, You + should make sure your system has some authentication before + using enableRemoteStreaming="true" + + --> + <requestParsers enableRemoteStreaming="true" + multipartUploadLimitInKB="2048000" + formdataUploadLimitInKB="2048" + addHttpRequestToContext="false"/> + + <!-- HTTP Caching + + Set HTTP caching related parameters (for proxy caches and clients). + + The options below instruct Solr not to output any HTTP Caching + related headers + --> + <httpCaching never304="true" /> + <!-- If you include a <cacheControl> directive, it will be used to + generate a Cache-Control header (as well as an Expires header + if the value contains "max-age=") + + By default, no Cache-Control header is generated. + + You can use the <cacheControl> option even if you have set + never304="true" + --> + <!-- + <httpCaching never304="true" > + <cacheControl>max-age=30, public</cacheControl> + </httpCaching> + --> + <!-- To enable Solr to respond with automatically generated HTTP + Caching headers, and to response to Cache Validation requests + correctly, set the value of never304="false" + + This will cause Solr to generate Last-Modified and ETag + headers based on the properties of the Index. + + The following options can also be specified to affect the + values of these headers... + + lastModFrom - the default value is "openTime" which means the + Last-Modified value (and validation against If-Modified-Since + requests) will all be relative to when the current Searcher + was opened. You can change it to lastModFrom="dirLastMod" if + you want the value to exactly correspond to when the physical + index was last modified. + + etagSeed="..." is an option you can change to force the ETag + header (and validation against If-None-Match requests) to be + different even if the index has not changed (ie: when making + significant changes to your config file) + + (lastModifiedFrom and etagSeed are both ignored if you use + the never304="true" option) + --> + <!-- + <httpCaching lastModifiedFrom="openTime" + etagSeed="Solr"> + <cacheControl>max-age=30, public</cacheControl> + </httpCaching> + --> </requestDispatcher> - <!-- requestHandler plugins... incoming queries will be dispatched to the - correct handler based on the path or the qt (query type) param. - Names starting with a '/' are accessed with the a path equal to the - registered name. Names without a leading '/' are accessed with: - http://host/app/select?qt=name - If no qt is defined, the requestHandler that declares default="true" - will be used. - --> - <requestHandler name="standard" class="solr.SearchHandler" default="true"> - <!-- default values for query parameters --> - <lst name="defaults"> - <str name="echoParams">explicit</str> - <!-- - <int name="rows">10</int> - <str name="fl">*</str> - <str name="version">2.1</str> - --> - </lst> - </requestHandler> + <!-- Request Handlers -<!-- Please refer to http://wiki.apache.org/solr/SolrReplication for details on configuring replication --> -<!-- remove the <lst name="master"> section if this is just a slave --> -<!-- remove the <lst name="slave"> section if this is just a master --> -<!-- -<requestHandler name="/replication" class="solr.ReplicationHandler" > - <lst name="master"> - <str name="replicateAfter">commit</str> - <str name="replicateAfter">startup</str> - <str name="confFiles">schema.xml,stopwords.txt</str> - </lst> - <lst name="slave"> - <str name="masterUrl">http://localhost:8983/solr/replication</str> - <str name="pollInterval">00:00:60</str> - </lst> -</requestHandler>--> + http://wiki.apache.org/solr/SolrRequestHandler - <!-- DisMaxRequestHandler allows easy searching across multiple fields - for simple user-entered phrases. It's implementation is now - just the standard SearchHandler with a default query type - of "dismax". - see http://wiki.apache.org/solr/DisMaxRequestHandler - --> - <requestHandler name="dismax" class="solr.SearchHandler" > - <lst name="defaults"> - <str name="defType">dismax</str> - <str name="echoParams">explicit</str> - <float name="tie">0.01</float> - <str name="qf"> - text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 - </str> - <str name="pf"> - text^0.2 features^1.1 name^1.5 manu^1.4 manu_exact^1.9 - </str> - <str name="bf"> - popularity^0.5 recip(price,1,1000,1000)^0.3 - </str> - <str name="fl"> - id,name,price,score - </str> - <str name="mm"> - 2<-1 5<-2 6<90% - </str> - <int name="ps">100</int> - <str name="q.alt">*:*</str> - <!-- example highlighter config, enable per-query with hl=true --> - <str name="hl.fl">text features name</str> - <!-- for this field, we want no fragmenting, just highlighting --> - <str name="f.name.hl.fragsize">0</str> - <!-- instructs Solr to return the field itself if no query terms are - found --> - <str name="f.name.hl.alternateField">name</str> - <str name="f.text.hl.fragmenter">regex</str> <!-- defined below --> - </lst> - </requestHandler> + Incoming queries will be dispatched to a specific handler by name + based on the path specified in the request. + + Legacy behavior: If the request path uses "/select" but no Request + Handler has that name, and if handleSelect="true" has been specified in + the requestDispatcher, then the Request Handler is dispatched based on + the qt parameter. Handlers without a leading '/' are accessed this way + like so: http://host/app/[core/]select?qt=name If no qt is + given, then the requestHandler that declares default="true" will be + used or the one named "standard". + + If a Request Handler is declared with startup="lazy", then it will + not be initialized until the first request that uses it. - <!-- Note how you can register the same handler multiple times with - different names (and different init parameters) --> - <requestHandler name="partitioned" class="solr.SearchHandler" > - <lst name="defaults"> - <str name="defType">dismax</str> - <str name="echoParams">explicit</str> - <str name="qf">text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0</str> - <str name="mm">2<-1 5<-2 6<90%</str> - <!-- This is an example of using Date Math to specify a constantly - moving date range in a config... - --> - <str name="bq">incubationdate_dt:[* TO NOW/DAY-1MONTH]^2.2</str> - </lst> + <!-- SearchHandler + + http://wiki.apache.org/solr/SearchHandler + + For processing Search Queries, the primary Request Handler + provided with Solr is "SearchHandler" It delegates to a sequent + of SearchComponents (see below) and supports distributed + queries across multiple shards + --> + <requestHandler name="/select" class="solr.SearchHandler"> + <!-- default values for query parameters can be specified, these + will be overridden by parameters in the request + --> + <lst name="defaults"> + <str name="echoParams">explicit</str> + <int name="rows">10</int> + <str name="df">id</str> + </lst> <!-- In addition to defaults, "appends" params can be specified to identify values which should be appended to the list of multi-val params from the query (or the existing "defaults"). - - In this example, the param "fq=instock:true" will be appended to + --> + <!-- In this example, the param "fq=instock:true" would be appended to any query time fq params the user may specify, as a mechanism for partitioning the index, independent of any user selected filtering that may also be desired (perhaps as a result of faceted searching). @@ -579,33 +825,377 @@ "appends" values from being used, so don't use this mechanism unless you are sure you always want it. --> - <lst name="appends"> - <str name="fq">inStock:true</str> - </lst> + <!-- + <lst name="appends"> + <str name="fq">inStock:true</str> + </lst> + --> <!-- "invariants" are a way of letting the Solr maintainer lock down the options available to Solr clients. Any params values specified here are used regardless of what values may be specified in either the query, the "defaults", or the "appends" params. - In this example, the facet.field and facet.query params are fixed, - limiting the facets clients can use. Faceting is not turned on by - default - but if the client does specify facet=true in the request, - these are the only facets they will be able to see counts for; - regardless of what other facet.field or facet.query params they - may specify. + In this example, the facet.field and facet.query params would + be fixed, limiting the facets clients can use. Faceting is + not turned on by default - but if the client does specify + facet=true in the request, these are the only facets they + will be able to see counts for; regardless of what other + facet.field or facet.query params they may specify. NOTE: there is *absolutely* nothing a client can do to prevent these "invariants" values from being used, so don't use this mechanism unless you are sure you always want it. --> + <!-- + <lst name="invariants"> + <str name="facet.field">cat</str> + <str name="facet.field">manu_exact</str> + <str name="facet.query">price:[* TO 500]</str> + <str name="facet.query">price:[500 TO *]</str> + </lst> + --> + <!-- If the default list of SearchComponents is not desired, that + list can either be overridden completely, or components can be + prepended or appended to the default list. (see below) + --> + <!-- + <arr name="components"> + <str>nameOfCustomComponent1</str> + <str>nameOfCustomComponent2</str> + </arr> + --> + </requestHandler> + + <!-- A request handler that returns indented JSON by default --> + <requestHandler name="/query" class="solr.SearchHandler"> + <lst name="defaults"> + <str name="echoParams">explicit</str> + <str name="wt">json</str> + <str name="indent">true</str> + <str name="df">id</str> + </lst> + </requestHandler> + + + <!-- realtime get handler, guaranteed to return the latest stored fields of + any document, without the need to commit or open a new searcher. The + current implementation relies on the updateLog feature being enabled. --> + <requestHandler name="/get" class="solr.RealTimeGetHandler"> + <lst name="defaults"> + <str name="omitHeader">true</str> + <str name="wt">json</str> + <str name="indent">true</str> + </lst> + </requestHandler> + + + <!-- A Robust Example + + This example SearchHandler declaration shows off usage of the + SearchHandler with many defaults declared + + Note that multiple instances of the same Request Handler + (SearchHandler) can be registered multiple times with different + names (and different init parameters) + --> + <requestHandler name="/browse" class="solr.SearchHandler"> + <lst name="defaults"> + <str name="echoParams">explicit</str> + + <!-- VelocityResponseWriter settings --> + <str name="wt">velocity</str> + <str name="v.template">browse</str> + <str name="v.layout">layout</str> + <str name="title">Solritas</str> + + <!-- Query settings --> + <str name="defType">edismax</str> + <str name="qf"> + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0 + </str> + <str name="df">id</str> + <str name="mm">100%</str> + <str name="q.alt">*:*</str> + <str name="rows">10</str> + <str name="fl">*,score</str> + + <str name="mlt.qf"> + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + title^10.0 description^5.0 keywords^5.0 author^2.0 resourcename^1.0 + </str> + <str name="mlt.fl">text,features,name,sku,id,manu,cat,title,description,keywords,author,resourcename</str> + <int name="mlt.count">3</int> + + <!-- Faceting defaults --> + <str name="facet">on</str> + <str name="facet.field">cat</str> + <str name="facet.field">manu_exact</str> + <str name="facet.field">content_type</str> + <str name="facet.field">author_s</str> + <str name="facet.query">ipod</str> + <str name="facet.query">GB</str> + <str name="facet.mincount">1</str> + <str name="facet.pivot">cat,inStock</str> + <str name="facet.range.other">after</str> + <str name="facet.range">price</str> + <int name="f.price.facet.range.start">0</int> + <int name="f.price.facet.range.end">600</int> + <int name="f.price.facet.range.gap">50</int> + <str name="facet.range">popularity</str> + <int name="f.popularity.facet.range.start">0</int> + <int name="f.popularity.facet.range.end">10</int> + <int name="f.popularity.facet.range.gap">3</int> + <str name="facet.range">manufacturedate_dt</str> + <str name="f.manufacturedate_dt.facet.range.start">NOW/YEAR-10YEARS</str> + <str name="f.manufacturedate_dt.facet.range.end">NOW</str> + <str name="f.manufacturedate_dt.facet.range.gap">+1YEAR</str> + <str name="f.manufacturedate_dt.facet.range.other">before</str> + <str name="f.manufacturedate_dt.facet.range.other">after</str> + + <!-- Highlighting defaults --> + <str name="hl">on</str> + <str name="hl.fl">content features title name</str> + <str name="hl.encoder">html</str> + <str name="hl.simple.pre"><b></str> + <str name="hl.simple.post"></b></str> + <str name="f.title.hl.fragsize">0</str> + <str name="f.title.hl.alternateField">title</str> + <str name="f.name.hl.fragsize">0</str> + <str name="f.name.hl.alternateField">name</str> + <str name="f.content.hl.snippets">3</str> + <str name="f.content.hl.fragsize">200</str> + <str name="f.content.hl.alternateField">content</str> + <str name="f.content.hl.maxAlternateFieldLength">750</str> + + <!-- Spell checking defaults --> + <str name="spellcheck">on</str> + <str name="spellcheck.extendedResults">false</str> + <str name="spellcheck.count">5</str> + <str name="spellcheck.alternativeTermCount">2</str> + <str name="spellcheck.maxResultsForSuggest">5</str> + <str name="spellcheck.collate">true</str> + <str name="spellcheck.collateExtendedResults">true</str> + <str name="spellcheck.maxCollationTries">5</str> + <str name="spellcheck.maxCollations">3</str> + </lst> + + <!-- append spellchecking to our list of components --> + <arr name="last-components"> + <str>spellcheck</str> + </arr> + </requestHandler> + + <!-- Update Request Handler. + + http://wiki.apache.org/solr/UpdateXmlMessages + + The canonical Request Handler for Modifying the Index through + commands specified using XML, JSON, CSV, or JAVABIN + + Note: Since solr1.1 requestHandlers requires a valid content + type header if posted in the body. For example, curl now + requires: -H 'Content-type:text/xml; charset=utf-8' + + To override the request content type and force a specific + Content-type, use the request parameter: + ?update.contentType=text/csv + + This handler will pick a response format to match the input + if the 'wt' parameter is not explicit + --> + <requestHandler name="/update" class="solr.UpdateRequestHandler"> + <!-- See below for information on defining + updateRequestProcessorChains that can be used by name + on each Update Request + --> + <!-- + <lst name="defaults"> + <str name="update.chain">dedupe</str> + </lst> + --> + <!-- Update chain processor required by DSpace to auto generate the UUID field in solr --> + <lst name="defaults"> + <str name="update.chain">uuid</str> + </lst> + </requestHandler> + + <!-- for back compat with clients using /update/json and /update/csv --> + <requestHandler name="/update/json" class="solr.JsonUpdateRequestHandler"> + <lst name="defaults"> + <str name="stream.contentType">application/json</str> + </lst> + </requestHandler> + <requestHandler name="/update/csv" class="solr.CSVRequestHandler"> + <lst name="defaults"> + <str name="stream.contentType">application/csv</str> + </lst> + </requestHandler> + + <!-- Solr Cell Update Request Handler + + http://wiki.apache.org/solr/ExtractingRequestHandler + + --> + <requestHandler name="/update/extract" + startup="lazy" + class="solr.extraction.ExtractingRequestHandler" > + <lst name="defaults"> + <str name="lowernames">true</str> + <str name="uprefix">ignored_</str> + + <!-- capture link hrefs but ignore div attributes --> + <str name="captureAttr">true</str> + <str name="fmap.a">links</str> + <str name="fmap.div">ignored_</str> + </lst> + </requestHandler> + + + <!-- Field Analysis Request Handler + + RequestHandler that provides much the same functionality as + analysis.jsp. Provides the ability to specify multiple field + types and field names in the same request and outputs + index-time and query-time analysis for each of them. + + Request parameters are: + analysis.fieldname - field name whose analyzers are to be used + + analysis.fieldtype - field type whose analyzers are to be used + analysis.fieldvalue - text for index-time analysis + q (or analysis.q) - text for query time analysis + analysis.showmatch (true|false) - When set to true and when + query analysis is performed, the produced tokens of the + field value analysis will be marked as "matched" for every + token that is produces by the query analysis + --> + <requestHandler name="/analysis/field" + startup="lazy" + class="solr.FieldAnalysisRequestHandler" /> + + + <!-- Document Analysis Handler + + http://wiki.apache.org/solr/AnalysisRequestHandler + + An analysis handler that provides a breakdown of the analysis + process of provided documents. This handler expects a (single) + content stream with the following format: + + <docs> + <doc> + <field name="id">1</field> + <field name="name">The Name</field> + <field name="text">The Text Value</field> + </doc> + <doc>...</doc> + <doc>...</doc> + ... + </docs> + + Note: Each document must contain a field which serves as the + unique key. This key is used in the returned response to associate + an analysis breakdown to the analyzed document. + + Like the FieldAnalysisRequestHandler, this handler also supports + query analysis by sending either an "analysis.query" or "q" + request parameter that holds the query text to be analyzed. It + also supports the "analysis.showmatch" parameter which when set to + true, all field tokens that match the query tokens will be marked + as a "match". + --> + <requestHandler name="/analysis/document" + class="solr.DocumentAnalysisRequestHandler" + startup="lazy" /> + + <!-- Admin Handlers + + Admin Handlers - This will register all the standard admin + RequestHandlers. + --> + <requestHandler name="/admin/" + class="solr.admin.AdminHandlers" /> + <!-- This single handler is equivalent to the following... --> + <!-- + <requestHandler name="/admin/luke" class="solr.admin.LukeRequestHandler" /> + <requestHandler name="/admin/system" class="solr.admin.SystemInfoHandler" /> + <requestHandler name="/admin/plugins" class="solr.admin.PluginInfoHandler" /> + <requestHandler name="/admin/threads" class="solr.admin.ThreadDumpHandler" /> + <requestHandler name="/admin/properties" class="solr.admin.PropertiesRequestHandler" /> + <requestHandler name="/admin/file" class="solr.admin.ShowFileRequestHandler" > + --> + <!-- If you wish to hide files under ${solr.home}/conf, explicitly + register the ShowFileRequestHandler using: + --> + <!-- + <requestHandler name="/admin/file" + class="solr.admin.ShowFileRequestHandler" > + <lst name="invariants"> + <str name="hidden">synonyms.txt</str> + <str name="hidden">anotherfile.txt</str> + </lst> + </requestHandler> + --> + + <!-- ping/healthcheck --> + <requestHandler name="/admin/ping" class="solr.PingRequestHandler"> <lst name="invariants"> - <str name="facet.field">cat</str> - <str name="facet.field">manu_exact</str> - <str name="facet.query">price:[* TO 500]</str> - <str name="facet.query">price:[500 TO *]</str> + <str name="q">solrpingquery</str> + </lst> + <lst name="defaults"> + <str name="echoParams">all</str> </lst> + <!-- An optional feature of the PingRequestHandler is to configure the + handler with a "healthcheckFile" which can be used to enable/disable + the PingRequestHandler. + relative paths are resolved against the data dir + --> + <!-- <str name="healthcheckFile">server-enabled.txt</str> --> </requestHandler> + <!-- Echo the request contents back to the client --> + <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" > + <lst name="defaults"> + <str name="echoParams">explicit</str> + <str name="echoHandler">true</str> + </lst> + </requestHandler> + + <!-- Solr Replication + + The SolrReplicationHandler supports replicating indexes from a + "master" used for indexing and "slaves" used for queries. + + http://wiki.apache.org/solr/SolrReplication + + It is also necessary for SolrCloud to function (in Cloud mode, the + replication handler is used to bulk transfer segments when nodes + are added or need to recover). + + https://wiki.apache.org/solr/SolrCloud/ + --> + <requestHandler name="/replication" class="solr.ReplicationHandler" > + <!-- + To enable simple master/slave replication, uncomment one of the + sections below, depending on whether this solr instance should be + the "master" or a "slave". If this instance is a "slave" you will + also need to fill in the masterUrl to point to a real machine. + --> + <!-- + <lst name="master"> + <str name="replicateAfter">commit</str> + <str name="replicateAfter">startup</str> + <str name="confFiles">schema.xml,stopwords.txt</str> + </lst> + --> + <!-- + <lst name="slave"> + <str name="masterUrl">http://your-master-hostname:8983/solr</str> + <str name="pollInterval">00:00:60</str> + </lst> + --> + </requestHandler> <!-- Search components are registered to SolrCore and used by Search Handlers @@ -710,56 +1300,284 @@ </arr> </requestHandler> + <!-- Search Components + + Search components are registered to SolrCore and used by + instances of SearchHandler (which can access them by name) + + By default, the following components are available: + + <searchComponent name="query" class="solr.QueryComponent" /> + <searchComponent name="facet" class="solr.FacetComponent" /> + <searchComponent name="mlt" class="solr.MoreLikeThisComponent" /> + <searchComponent name="highlight" class="solr.HighlightComponent" /> + <searchComponent name="stats" class="solr.StatsComponent" /> + <searchComponent name="debug" class="solr.DebugComponent" /> + + Default configuration in a requestHandler would look like: + + <arr name="components"> + <str>query</str> + <str>facet</str> + <str>mlt</str> + <str>highlight</str> + <str>stats</str> + <str>debug</str> + </arr> + + If you register a searchComponent to one of the standard names, + that will be used instead of the default. + + To insert components before or after the 'standard' components, use: + + <arr name="first-components"> + <str>myFirstComponentName</str> + </arr> + + <arr name="last-components"> + <str>myLastComponentName</str> + </arr> + + NOTE: The component registered with the name "debug" will + always be executed after the "last-components" + + --> + + <!-- Spell Check + + The spell check component can return a list of alternative spelling + suggestions. + + http://wiki.apache.org/solr/SpellCheckComponent + --> + <searchComponent name="spellcheck" class="solr.SpellCheckComponent"> + + <str name="queryAnalyzerFieldType">text_general</str> + + <!-- Multiple "Spell Checkers" can be declared and used by this + component + --> + + <!-- a spellchecker built from a field of the main index --> + <lst name="spellchecker"> + <str name="name">default</str> + <str name="field">id</str> + <str name="classname">solr.DirectSolrSpellChecker</str> + <!-- the spellcheck distance measure used, the default is the internal levenshtein --> + <str name="distanceMeasure">internal</str> + <!-- minimum accuracy needed to be considered a valid spellcheck suggestion --> + <float name="accuracy">0.5</float> + <!-- the maximum #edits we consider when enumerating terms: can be 1 or 2 --> + <int name="maxEdits">2</int> + <!-- the minimum shared prefix when enumerating terms --> + <int name="minPrefix">1</int> + <!-- maximum number of inspections per result. --> + <int name="maxInspections">5</int> + <!-- minimum length of a query term to be considered for correction --> + <int name="minQueryLength">4</int> + <!-- maximum threshold of documents a query term can appear to be considered for correction --> + <float name="maxQueryFrequency">0.01</float> + <!-- uncomment this to require suggestions to occur in 1% of the documents + <float name="thresholdTokenFrequency">.01</float> + --> + </lst> + + <!-- a spellchecker that can break or combine words. See "/spell" handler below for usage --> + <lst name="spellchecker"> + <str name="name">wordbreak</str> + <str name="classname">solr.WordBreakSolrSpellChecker</str> + <str name="field">name</str> + <str name="combineWords">true</str> + <str name="breakWords">true</str> + <int name="maxChanges">10</int> + </lst> + + <!-- a spellchecker that uses a different distance measure --> + <!-- + <lst name="spellchecker"> + <str name="name">jarowinkler</str> + <str name="field">spell</str> + <str name="classname">solr.DirectSolrSpellChecker</str> + <str name="distanceMeasure"> + org.apache.lucene.search.spell.JaroWinklerDistance + </str> + </lst> + --> + + <!-- a spellchecker that use an alternate comparator + + comparatorClass be one of: + 1. score (default) + 2. freq (Frequency first, then score) + 3. A fully qualified class name + --> + <!-- + <lst name="spellchecker"> + <str name="name">freq</str> + <str name="field">lowerfilt</str> + <str name="classname">solr.DirectSolrSpellChecker</str> + <str name="comparatorClass">freq</str> + --> + + <!-- A spellchecker that reads the list of words from a file --> + <!-- + <lst name="spellchecker"> + <str name="classname">solr.FileBasedSpellChecker</str> + <str name="name">file</str> + <str name="sourceLocation">spellings.txt</str> + <str name="characterEncoding">UTF-8</str> + <str name="spellcheckIndexDir">spellcheckerFile</str> + </lst> + --> + </searchComponent> + + <!-- A request handler for demonstrating the spellcheck component. + + NOTE: This is purely as an example. The whole purpose of the + SpellCheckComponent is to hook it into the request handler that + handles your normal user queries so that a separate request is + not needed to get suggestions. + + IN OTHER WORDS, THERE IS REALLY GOOD CHANCE THE SETUP BELOW IS + NOT WHAT YOU WANT FOR YOUR PRODUCTION SYSTEM! + + See http://wiki.apache.org/solr/SpellCheckComponent for details + on the request parameters. + --> + <requestHandler name="/spell" class="solr.SearchHandler" startup="lazy"> + <lst name="defaults"> + <str name="df">id</str> + <!-- Solr will use suggestions from both the 'default' spellchecker + and from the 'wordbreak' spellchecker and combine them. + collations (re-written queries) can include a combination of + corrections from both spellcheckers --> + <str name="spellcheck.dictionary">default</str> + <str name="spellcheck.dictionary">wordbreak</str> + <str name="spellcheck">on</str> + <str name="spellcheck.extendedResults">true</str> + <str name="spellcheck.count">10</str> + <str name="spellcheck.alternativeTermCount">5</str> + <str name="spellcheck.maxResultsForSuggest">5</str> + <str name="spellcheck.collate">true</str> + <str name="spellcheck.collateExtendedResults">true</str> + <str name="spellcheck.maxCollationTries">10</str> + <str name="spellcheck.maxCollations">5</str> + </lst> + <arr name="last-components"> + <str>spellcheck</str> + </arr> + </requestHandler> + + <!-- Term Vector Component + + http://wiki.apache.org/solr/TermVectorComponent + --> + <searchComponent name="tvComponent" class="solr.TermVectorComponent"/> + + <!-- A request handler for demonstrating the term vector component + + This is purely as an example. + + In reality you will likely want to add the component to your + already specified request handlers. + --> + <requestHandler name="/tvrh" class="solr.SearchHandler" startup="lazy"> + <lst name="defaults"> + <str name="df">id</str> + <bool name="tv">true</bool> + </lst> + <arr name="last-components"> + <str>tvComponent</str> + </arr> + </requestHandler> + <!-- Clustering Component + http://wiki.apache.org/solr/ClusteringComponent - This relies on third party jars which are not included in the release. - To use this component (and the "/clustering" handler) - Those jars will need to be downloaded, and you'll need to set the - solr.cluster.enabled system property when running solr... - java -Dsolr.clustering.enabled=true -jar start.jar + + You'll need to set the solr.clustering.enabled system property + when running solr to run with clustering enabled: + + java -Dsolr.clustering.enabled=true -jar start.jar + --> - <searchComponent - name="clusteringComponent" - enable="${solr.clustering.enabled:false}" - class="org.apache.solr.handler.clustering.ClusteringComponent" > + <searchComponent name="clustering" + enable="${solr.clustering.enabled:false}" + class="solr.clustering.ClusteringComponent" > <!-- Declare an engine --> <lst name="engine"> <!-- The name, only one can be named "default" --> <str name="name">default</str> - <!-- - Class name of Carrot2 clustering algorithm. Currently available algorithms are: + <!-- Class name of Carrot2 clustering algorithm. + + Currently available algorithms are: + * org.carrot2.clustering.lingo.LingoClusteringAlgorithm * org.carrot2.clustering.stc.STCClusteringAlgorithm - - See http://project.carrot2.org/algorithms.html for the algorithm's characteristics. + * org.carrot2.clustering.kmeans.BisectingKMeansClusteringAlgorithm + + See http://project.carrot2.org/algorithms.html for the + algorithm's characteristics. --> <str name="carrot.algorithm">org.carrot2.clustering.lingo.LingoClusteringAlgorithm</str> - <!-- - Overriding values for Carrot2 default algorithm attributes. For a description - of all available attributes, see: http://download.carrot2.org/stable/manual/#chapter.components. - Use attribute key as name attribute of str elements below. These can be further - overridden for individual requests by specifying attribute key as request - parameter name and attribute value as parameter value. + + <!-- Overriding values for Carrot2 default algorithm attributes. + + For a description of all available attributes, see: + http://download.carrot2.org/stable/manual/#chapter.components. + Use attribute key as name attribute of str elements + below. These can be further overridden for individual + requests by specifying attribute key as request parameter + name and attribute value as parameter value. --> <str name="LingoClusteringAlgorithm.desiredClusterCountBase">20</str> + + <!-- Location of Carrot2 lexical resources. + + A directory from which to load Carrot2-specific stop words + and stop labels. Absolute or relative to Solr config directory. + If a specific resource (e.g. stopwords.en) is present in the + specified dir, it will completely override the corresponding + default one that ships with Carrot2. + + For an overview of Carrot2 lexical resources, see: + http://download.carrot2.org/head/manual/#chapter.lexical-resources + --> + <str name="carrot.lexicalResourcesDir">clustering/carrot2</str> + + <!-- The language to assume for the documents. + + For a list of allowed values, see: + http://download.carrot2.org/stable/manual/#section.attribute.lingo.MultilingualClustering.defaultLanguage + --> + <str name="MultilingualClustering.defaultLanguage">ENGLISH</str> </lst> <lst name="engine"> <str name="name">stc</str> <str name="carrot.algorithm">org.carrot2.clustering.stc.STCClusteringAlgorithm</str> </lst> </searchComponent> + + <!-- A request handler for demonstrating the clustering component + + This is purely as an example. + + In reality you will likely want to add the component to your + already specified request handlers. + --> <requestHandler name="/clustering" + startup="lazy" enable="${solr.clustering.enabled:false}" class="solr.SearchHandler"> - <lst name="defaults"> - <bool name="clustering">true</bool> - <str name="clustering.engine">default</str> - <bool name="clustering.results">true</bool> - <!-- The title field --> - <str name="carrot.title">name</str> - <str name="carrot.url">id</str> - <!-- The field to cluster on --> + <lst name="defaults"> + <bool name="clustering">true</bool> + <str name="clustering.engine">default</str> + <bool name="clustering.results">true</bool> + <!-- The title field --> + <str name="carrot.title">name</str> + <str name="carrot.url">id</str> + <!-- The field to cluster on --> <str name="carrot.snippet">features</str> <!-- produce summaries --> <bool name="carrot.produceSummary">true</bool> @@ -767,268 +1585,354 @@ <!--<int name="carrot.numDescriptions">5</int>--> <!-- produce sub clusters --> <bool name="carrot.outputSubClusters">false</bool> - </lst> + + <str name="defType">edismax</str> + <str name="qf"> + text^0.5 features^1.0 name^1.2 sku^1.5 id^10.0 manu^1.1 cat^1.4 + </str> + <str name="q.alt">*:*</str> + <str name="rows">10</str> + <str name="fl">*,score</str> + </lst> <arr name="last-components"> - <str>clusteringComponent</str> + <str>clustering</str> </arr> </requestHandler> + + <!-- Terms Component - <!-- Solr Cell: http://wiki.apache.org/solr/ExtractingRequestHandler --> - <requestHandler name="/update/extract" class="org.apache.solr.handler.extraction.ExtractingRequestHandler" startup="lazy"> - <lst name="defaults"> - <!-- All the main content goes into "text"... if you need to return - the extracted text or do highlighting, use a stored field. --> - <str name="fmap.content">text</str> - <str name="lowernames">true</str> - <str name="uprefix">ignored_</str> + http://wiki.apache.org/solr/TermsComponent - <!-- capture link hrefs but ignore div attributes --> - <str name="captureAttr">true</str> - <str name="fmap.a">links</str> - <str name="fmap.div">ignored_</str> - </lst> - </requestHandler> - - - <!-- A component to return terms and document frequency of those terms. - This component does not yet support distributed search. --> - <searchComponent name="termsComponent" class="org.apache.solr.handler.component.TermsComponent"/> + A component to return terms and document frequency of those + terms + --> + <searchComponent name="terms" class="solr.TermsComponent"/> - <requestHandler name="/terms" class="org.apache.solr.handler.component.SearchHandler"> + <!-- A request handler for demonstrating the terms component --> + <requestHandler name="/terms" class="solr.SearchHandler" startup="lazy"> <lst name="defaults"> <bool name="terms">true</bool> - </lst> + <bool name="distrib">false</bool> + </lst> <arr name="components"> - <str>termsComponent</str> + <str>terms</str> </arr> </requestHandler> - <!-- a search component that enables you to configure the top results for - a given query regardless of the normal lucene scoring.--> + <!-- Query Elevation Component - <!-- - MRD: Disabled to support removing uniqueky field in statitsics + http://wiki.apache.org/solr/QueryElevationComponent + + a search component that enables you to configure the top + results for a given query regardless of the normal lucene + scoring. + --> <searchComponent name="elevator" class="solr.QueryElevationComponent" > + <!-- pick a fieldType to analyze queries --> <str name="queryFieldType">string</str> <str name="config-file">elevate.xml</str> </searchComponent> - --> - <!-- a request handler utilizing the elevator component --> + <!-- A request handler for demonstrating the elevator component --> <requestHandler name="/elevate" class="solr.SearchHandler" startup="lazy"> <lst name="defaults"> <str name="echoParams">explicit</str> + <str name="df">id</str> </lst> <arr name="last-components"> <str>elevator</str> </arr> </requestHandler> + <!-- Highlighting Component - <!-- Update request handler. - - Note: Since solr1.1 requestHandlers requires a valid content type header if posted in - the body. For example, curl now requires: -H 'Content-type:text/xml; charset=utf-8' - The response format differs from solr1.1 formatting and returns a standard error code. - To enable solr1.1 behavior, remove the /update handler or change its path + http://wiki.apache.org/solr/HighlightingParameters --> - <requestHandler name="/update" class="solr.XmlUpdateRequestHandler" /> - - - <requestHandler name="/update/javabin" class="solr.BinaryUpdateRequestHandler" /> - - <!-- - Analysis request handler. Since Solr 1.3. Use to return how a document is analyzed. Useful - for debugging and as a token server for other types of applications. - - This is deprecated in favor of the improved DocumentAnalysisRequestHandler and FieldAnalysisRequestHandler - - <requestHandler name="/analysis" class="solr.AnalysisRequestHandler" /> - --> + <searchComponent class="solr.HighlightComponent" name="highlight"> + <highlighting> + <!-- Configure the standard fragmenter --> + <!-- This could most likely be commented out in the "default" case --> + <fragmenter name="gap" + default="true" + class="solr.highlight.GapFragmenter"> + <lst name="defaults"> + <int name="hl.fragsize">100</int> + </lst> + </fragmenter> + + <!-- A regular-expression-based fragmenter + (for sentence extraction) + --> + <fragmenter name="regex" + class="solr.highlight.RegexFragmenter"> + <lst name="defaults"> + <!-- slightly smaller fragsizes work better because of slop --> + <int name="hl.fragsize">70</int> + <!-- allow 50% slop on fragment sizes --> + <float name="hl.regex.slop">0.5</float> + <!-- a basic sentence pattern --> + <str name="hl.regex.pattern">[-\w ,/\n\"']{20,200}</str> + </lst> + </fragmenter> + + <!-- Configure the standard formatter --> + <formatter name="html" + default="true" + class="solr.highlight.HtmlFormatter"> + <lst name="defaults"> + <str name="hl.simple.pre"><![CDATA[<em>]]></str> + <str name="hl.simple.post"><![CDATA[</em>]]></str> + </lst> + </formatter> + + <!-- Configure the standard encoder --> + <encoder name="html" + class="solr.highlight.HtmlEncoder" /> + + <!-- Configure the standard fragListBuilder --> + <fragListBuilder name="simple" + class="solr.highlight.SimpleFragListBuilder"/> + + <!-- Configure the single fragListBuilder --> + <fragListBuilder name="single" + class="solr.highlight.SingleFragListBuilder"/> + + <!-- Configure the weighted fragListBuilder --> + <fragListBuilder name="weighted" + default="true" + class="solr.highlight.WeightedFragListBuilder"/> + + <!-- default tag FragmentsBuilder --> + <fragmentsBuilder name="default" + default="true" + class="solr.highlight.ScoreOrderFragmentsBuilder"> + <!-- + <lst name="defaults"> + <str name="hl.multiValuedSeparatorChar">/</str> + </lst> + --> + </fragmentsBuilder> + + <!-- multi-colored tag FragmentsBuilder --> + <fragmentsBuilder name="colored" + class="solr.highlight.ScoreOrderFragmentsBuilder"> + <lst name="defaults"> + <str name="hl.tag.pre"><![CDATA[ + <b style="background:yellow">,<b style="background:lawgreen">, + <b style="background:aquamarine">,<b style="background:magenta">, + <b style="background:palegreen">,<b style="background:coral">, + <b style="background:wheat">,<b style="background:khaki">, + <b style="background:lime">,<b style="background:deepskyblue">]]></str> + <str name="hl.tag.post"><![CDATA[</b>]]></str> + </lst> + </fragmentsBuilder> + + <boundaryScanner name="default" + default="true" + class="solr.highlight.SimpleBoundaryScanner"> + <lst name="defaults"> + <str name="hl.bs.maxScan">10</str> + <str name="hl.bs.chars">.,!? 	 </str> + </lst> + </boundaryScanner> + + <boundaryScanner name="breakIterator" + class="solr.highlight.BreakIteratorBoundaryScanner"> + <lst name="defaults"> + <!-- type should be one of CHARACTER, WORD(default), LINE and SENTENCE --> + <str name="hl.bs.type">WORD</str> + <!-- language and country are used when constructing Locale object. --> + <!-- And the Locale object will be used when getting instance of BreakIterator --> + <str name="hl.bs.language">en</str> + <str name="hl.bs.country">US</str> + </lst> + </boundaryScanner> + </highlighting> + </searchComponent> - <!-- - An analysis handler that provides a breakdown of the analysis process of provided docuemnts. This handler expects a - (single) content stream with the following format: - - <docs> - <doc> - <field name="id">1</field> - <field name="name">The Name</field> - <field name="text">The Text Value</field> - <doc> - <doc>...</doc> - <doc>...</doc> - ... - </docs> - - Note: Each document must contain a field which serves as the unique key. This key is used in the returned - response to assoicate an analysis breakdown to the analyzed document. - - Like the FieldAnalysisRequestHandler, this handler also supports query analysis by - sending either an "analysis.query" or "q" request paraemter that holds the query text to be analyized. It also - supports the "analysis.showmatch" parameter which when set to true, all field tokens that match the query - tokens will be marked as a "match". - --> - <requestHandler name="/analysis/document" class="solr.DocumentAnalysisRequestHandler" /> + <!-- Update Processors - <!-- - RequestHandler that provides much the same functionality as analysis.jsp. Provides the ability - to specify multiple field types and field names in the same request and outputs index-time and - query-time analysis for each of them. - - Request parameters are: - analysis.fieldname - The field name whose analyzers are to be used - analysis.fieldtype - The field type whose analyzers are to be used - analysis.fieldvalue - The text for index-time analysis - q (or analysis.q) - The text for query time analysis - analysis.showmatch (true|false) - When set to true and when query analysis is performed, the produced - tokens of the field value analysis will be marked as "matched" for every - token that is produces by the query analysis - --> - <requestHandler name="/analysis/field" class="solr.FieldAnalysisRequestHandler" /> + Chains of Update Processor Factories for dealing with Update + Requests can be declared, and then used by name in Update + Request Processors + http://wiki.apache.org/solr/UpdateRequestProcessor - <!-- CSV update handler, loaded on demand --> - <requestHandler name="/update/csv" class="solr.CSVRequestHandler" startup="lazy" /> - + --> + <!-- Deduplication + An example dedup update processor that creates the "id" field + on the fly based on the hash code of some other fields. This + example has overwriteDupes set to false since we are using the + id field as the signatureField and Solr will maintain + uniqueness based on that anyway. + + --> <!-- - Admin Handlers - This will register all the standard admin RequestHandlers. Adding - this single handler is equivalent to registering: - - <requestHandler name="/admin/luke" class="org.apache.solr.handler.admin.LukeRequestHandler" /> - <requestHandler name="/admin/system" class="org.apache.solr.handler.admin.SystemInfoHandler" /> - <requestHandler name="/admin/plugins" class="org.apache.solr.handler.admin.PluginInfoHandler" /> - <requestHandler name="/admin/threads" class="org.apache.solr.handler.admin.ThreadDumpHandler" /> - <requestHandler name="/admin/properties" class="org.apache.solr.handler.admin.PropertiesRequestHandler" /> - <requestHandler name="/admin/file" class="org.apache.solr.handler.admin.ShowFileRequestHandler" > - - If you wish to hide files under ${solr.home}/conf, explicitly register the ShowFileRequestHandler using: - <requestHandler name="/admin/file" class="org.apache.solr.handler.admin.ShowFileRequestHandler" > - <lst name="invariants"> - <str name="hidden">synonyms.txt</str> - <str name="hidden">anotherfile.txt</str> - </lst> - </requestHandler> - --> - <requestHandler name="/admin/" class="org.apache.solr.handler.admin.AdminHandlers" /> - - <!-- ping/healthcheck --> - <requestHandler name="/admin/ping" class="PingRequestHandler"> - <lst name="defaults"> - <str name="qt">standard</str> - <str name="q">solrpingquery</str> - <str name="echoParams">all</str> - </lst> - </requestHandler> - - <!-- Echo the request contents back to the client --> - <requestHandler name="/debug/dump" class="solr.DumpRequestHandler" > - <lst name="defaults"> - <str name="echoParams">explicit</str> <!-- for all params (including the default etc) use: 'all' --> - <str name="echoHandler">true</str> - </lst> - </requestHandler> + <updateRequestProcessorChain name="dedupe"> + <processor class="solr.processor.SignatureUpdateProcessorFactory"> + <bool name="enabled">true</bool> + <str name="signatureField">id</str> + <bool name="overwriteDupes">false</bool> + <str name="fields">name,features,cat</str> + <str name="signatureClass">solr.processor.Lookup3Signature</str> + </processor> + <processor class="solr.LogUpdateProcessorFactory" /> + <processor class="solr.RunUpdateProcessorFactory" /> + </updateRequestProcessorChain> + --> + + <!-- Language identification + + This example update chain identifies the language of the incoming + documents using the langid contrib. The detected language is + written to field language_s. No field name mapping is done. + The fields used for detection are text, title, subject and description, + making this example suitable for detecting languages form full-text + rich documents injected via ExtractingRequestHandler. + See more about langId at http://wiki.apache.org/solr/LanguageDetection + --> + <!-- + <updateRequestProcessorChain name="langid"> + <processor class="org.apache.solr.update.processor.TikaLanguageIdentifierUpdateProcessorFactory"> + <str name="langid.fl">text,title,subject,description</str> + <str name="langid.langField">language_s</str> + <str name="langid.fallback">en</str> + </processor> + <processor class="solr.LogUpdateProcessorFactory" /> + <processor class="solr.RunUpdateProcessorFactory" /> + </updateRequestProcessorChain> + --> - <highlighting> - <!-- Configure the standard fragmenter --> - <!-- This could most likely be commented out in the "default" case --> - <fragmenter name="gap" class="org.apache.solr.highlight.GapFragmenter" default="true"> - <lst name="defaults"> - <int name="hl.fragsize">100</int> - </lst> - </fragmenter> + <!-- Script update processor - <!-- A regular-expression-based fragmenter (f.i., for sentence extraction) --> - <fragmenter name="regex" class="org.apache.solr.highlight.RegexFragmenter"> - <lst name="defaults"> - <!-- slightly smaller fragsizes work better because of slop --> - <int name="hl.fragsize">70</int> - <!-- allow 50% slop on fragment sizes --> - <float name="hl.regex.slop">0.5</float> - <!-- a basic sentence pattern --> - <str name="hl.regex.pattern">[-\w ,/\n\"']{20,200}</str> - </lst> - </fragmenter> + This example hooks in an update processor implemented using JavaScript. - <!-- Configure the standard formatter --> - <formatter name="html" class="org.apache.solr.highlight.HtmlFormatter" default="true"> - <lst name="defaults"> - <str name="hl.simple.pre"><![CDATA[<em>]]></str> - <str name="hl.simple.post"><![CDATA[</em>]]></str> - </lst> - </formatter> - </highlighting> - - <!-- An example dedup update processor that creates the "id" field on the fly - based on the hash code of some other fields. This example has overwriteDupes - set to false since we are using the id field as the signatureField and Solr - will maintain uniqueness based on that anyway. - - You have to link the chain to an update handler above to use it ie: - <requestHandler name="/update "class="solr.XmlUpdateRequestHandler"> - <lst name="defaults"> - <str name="update.processor">dedupe</str> - </lst> - </requestHandler> + See more about the script update processor at http://wiki.apache.org/solr/ScriptUpdateProcessor --> <!-- - <updateRequestProcessorChain name="dedupe"> - <processor class="org.apache.solr.update.processor.SignatureUpdateProcessorFactory"> - <bool name="enabled">true</bool> - <str name="signatureField">id</str> - <bool name="overwriteDupes">false</bool> - <str name="fields">name,features,cat</str> - <str name="signatureClass">org.apache.solr.update.processor.Lookup3Signature</str> - </processor> - <processor class="solr.LogUpdateProcessorFactory" /> + <updateRequestProcessorChain name="script"> + <processor class="solr.StatelessScriptUpdateProcessorFactory"> + <str name="script">update-script.js</str> + <lst name="params"> + <str name="config_param">example config parameter</str> + </lst> + </processor> + <processor class="solr.RunUpdateProcessorFactory" /> + </updateRequestProcessorChain> + --> + <!-- Required for DSpace to ensure that unique identifiers are added to each solr document --> + <updateRequestProcessorChain name="uuid"> + <processor class="solr.UUIDUpdateProcessorFactory"> + <str name="fieldName">uid</str> + </processor> <processor class="solr.RunUpdateProcessorFactory" /> </updateRequestProcessorChain> - --> + + <!-- Response Writers + http://wiki.apache.org/solr/QueryResponseWriter - <!-- queryResponseWriter plugins... query responses will be written using the - writer specified by the 'wt' request parameter matching the name of a registered - writer. - The "default" writer is the default and will be used if 'wt' is not specified - in the request. XMLResponseWriter will be used if nothing is specified here. - The json, python, and ruby writers are also available by default. + Request responses will be written using the writer specified by + the 'wt' request parameter matching the name of a registered + writer. - <queryResponseWriter name="xml" class="org.apache.solr.request.XMLResponseWriter" default="true"/> - <queryResponseWriter name="json" class="org.apache.solr.request.JSONResponseWriter"/> - <queryResponseWriter name="python" class="org.apache.solr.request.PythonResponseWriter"/> - <queryResponseWriter name="ruby" class="org.apache.solr.request.RubyResponseWriter"/> - <queryResponseWriter name="php" class="org.apache.solr.request.PHPResponseWriter"/> - <queryResponseWriter name="phps" class="org.apache.solr.request.PHPSerializedResponseWriter"/> + The "default" writer is the default and will be used if 'wt' is + not specified in the request. + --> + <!-- The following response writers are implicitly configured unless + overridden... + --> + <!-- + <queryResponseWriter name="xml" + default="true" + class="solr.XMLResponseWriter" /> + <queryResponseWriter name="json" class="solr.JSONResponseWriter"/> + <queryResponseWriter name="python" class="solr.PythonResponseWriter"/> + <queryResponseWriter name="ruby" class="solr.RubyResponseWriter"/> + <queryResponseWriter name="php" class="solr.PHPResponseWriter"/> + <queryResponseWriter name="phps" class="solr.PHPSerializedResponseWriter"/> + <queryResponseWriter name="csv" class="solr.CSVResponseWriter"/> + <queryResponseWriter name="schema.xml" class="solr.SchemaXmlResponseWriter"/> + --> - <queryResponseWriter name="custom" class="com.example.MyResponseWriter"/> - --> + <queryResponseWriter name="json" class="solr.JSONResponseWriter"> + <!-- For the purposes of the tutorial, JSON responses are written as + plain text so that they are easy to read in *any* browser. + If you expect a MIME type of "application/json" just remove this override. + --> + <str name="content-type">text/plain; charset=UTF-8</str> + </queryResponseWriter> + + <!-- + Custom response writers can be declared as needed... + --> + <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy"/> + <!-- XSLT response writer transforms the XML output by any xslt file found in Solr's conf/xslt directory. Changes to xslt files are checked for - every xsltCacheLifetimeSeconds. - --> - <queryResponseWriter name="xslt" class="org.apache.solr.request.XSLTResponseWriter"> + every xsltCacheLifetimeSeconds. + --> + <queryResponseWriter name="xslt" class="solr.XSLTResponseWriter"> <int name="xsltCacheLifetimeSeconds">5</int> </queryResponseWriter> + <!-- Query Parsers - <!-- example of registering a query parser - <queryParser name="lucene" class="org.apache.solr.search.LuceneQParserPlugin"/> - --> + http://wiki.apache.org/solr/SolrQuerySyntax - <!-- example of registering a custom function parser - <valueSourceParser name="myfunc" class="com.mycompany.MyValueSourceParser" /> - --> + Multiple QParserPlugins can be registered by name, and then + used in either the "defType" param for the QueryComponent (used + by SearchHandler) or in LocalParams + --> + <!-- example of registering a query parser --> + <!-- + <queryParser name="myparser" class="com.mycompany.MyQParserPlugin"/> + --> - <!-- config for the admin interface --> - <admin> - <defaultQuery>solr</defaultQuery> + <!-- Function Parsers - <!-- configure a healthcheck file for servers behind a loadbalancer - <healthcheck type="file">server-enabled</healthcheck> + http://wiki.apache.org/solr/FunctionQuery + + Multiple ValueSourceParsers can be registered by name, and then + used as function names when using the "func" QParser. --> - </admin> + <!-- example of registering a custom function parser --> + <!-- + <valueSourceParser name="myfunc" + class="com.mycompany.MyValueSourceParser" /> + --> + + + <!-- Document Transformers + http://wiki.apache.org/solr/DocTransformers + --> + <!-- + Could be something like: + <transformer name="db" class="com.mycompany.LoadFromDatabaseTransformer" > + <int name="connection">jdbc://....</int> + </transformer> + + To add a constant value to all docs, use: + <transformer name="mytrans2" class="org.apache.solr.response.transform.ValueAugmenterFactory" > + <int name="value">5</int> + </transformer> + + If you want the user to still be able to change it with _value:something_ use this: + <transformer name="mytrans3" class="org.apache.solr.response.transform.ValueAugmenterFactory" > + <double name="defaultValue">5</double> + </transformer> + + If you are using the QueryElevationComponent, you may wish to mark documents that get boosted. The + EditorialMarkerFactory will do exactly that: + <transformer name="qecBooster" class="org.apache.solr.response.transform.EditorialMarkerFactory" /> + --> + + <!-- Legacy config for the admin interface --> + <admin> + <defaultQuery>*:*</defaultQuery> + </admin> </config> \ No newline at end of file diff --git a/dspace/src/main/assembly/assembly.xml b/dspace/src/main/assembly/assembly.xml index 798704b866ae984ee2af985ff85d99091e946a9b..3a8114e8534d3133dd39abce51c6718c0723fb01 100644 --- a/dspace/src/main/assembly/assembly.xml +++ b/dspace/src/main/assembly/assembly.xml @@ -48,7 +48,6 @@ <includes> <include>bin/**</include> <include>config/**</include> - <include>docs/**</include> <include>etc/**</include> <include>solr/**</include> </includes> @@ -56,6 +55,7 @@ <excludes> <exclude>src</exclude> <exclude>config/dspace.cfg</exclude> + <exclude>config/log4j.properties</exclude> <exclude>config/modules/**</exclude> </excludes> </fileSet> @@ -69,13 +69,18 @@ </fileSet> </fileSets> - <!-- Copy over the dspace.cfg & filter it --> + <!-- Copy over the dspace.cfg and log4j.properties files & filter them --> <files> <file> <source>config/dspace.cfg</source> <outputDirectory>config</outputDirectory> <filtered>true</filtered> </file> + <file> + <source>config/log4j.properties</source> + <outputDirectory>config</outputDirectory> + <filtered>true</filtered> + </file> </files> <!-- diff --git a/dspace/src/main/config/build.xml b/dspace/src/main/config/build.xml index a62badb6c3a6d23acd1c385905e4219ae5cac545..c1cf5927062b73e4aea8c18f6ceab5626dcf29a9 100644 --- a/dspace/src/main/config/build.xml +++ b/dspace/src/main/config/build.xml @@ -142,8 +142,9 @@ Common usage: <echo message="load_registries --> Load metadata & file format registries into the " /> <echo message=" database" /> <echo message="" /> - <echo message="clean_backups --> Remove .bak directories under install directory" /> + <echo message="clean_backups --> Remove .bak directories under install directory" /> <echo message="clean_database --> Remove DSpace database tables, destroying data" /> + <echo message="test_database --> Attempt to connect to the DSpace database in order to verify that configuration is correct" /> <echo message="" /> <echo message="" /> <echo message="Available parameters are:" /> @@ -357,6 +358,7 @@ Common usage: <expandproperties /> </filterchain> </copy> + <echo file='config-temp/ant.properties' message='ant.version = ${ant.version}'/> </target> @@ -696,6 +698,10 @@ Common usage: <fileset dir="${dspace.dir}/webapps/jspui/" /> </war> + <war destfile="${dspace.dir}/webapps/rest.war"> + <fileset dir="${dspace.dir}/webapps/rest/"/> + </war> + <war destfile="${dspace.dir}/webapps/sword.war"> <fileset dir="${dspace.dir}/webapps/sword/" /> </war> @@ -766,6 +772,8 @@ Common usage: <copy file="${config}" tofile="${dspace.dir}/config/dspace.cfg" preservelastmodified="true" /> + <echo file='${dspace.dir}/config/ant.properties' message='ant.version = ${ant.version}'/> + </target> @@ -863,6 +871,14 @@ Common usage: <arg line="-f '${dspace.dir}/config/registries/dublin-core-types.xml'" /> </java> + <!-- Import the new DCTerms schema --> + <java classname="org.dspace.administer.MetadataImporter" classpathref="class.path" fork="yes" failonerror="yes"> + <sysproperty key="log4j.configuration" value="file:config/log4j-console.properties" /> + <sysproperty key="dspace.log.init.disable" value="true" /> + <sysproperty key="dspace.configuration" value="${config}" /> + <arg line="-f '${dspace.dir}/config/registries/dcterms-types.xml'" /> + </java> + <!-- FIXME: this should be more modular --> <!-- import the SWORD required metadata --> <java classname="org.dspace.administer.MetadataImporter" classpathref="class.path" fork="yes" failonerror="yes"> diff --git a/pom.xml b/pom.xml deleted file mode 100644 index 90979f71c9148065b91695a1dccc3a95f3cb3c39..0000000000000000000000000000000000000000 --- a/pom.xml +++ /dev/null @@ -1,1204 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<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-parent</artifactId> - <packaging>pom</packaging> - <version>3.2</version> - <name>DSpace Parent Project</name> - <url>https://github.com/dspace/DSpace</url> - - <organization> - <name>DuraSpace</name> - <url>http://www.dspace.org</url> - </organization> - - <!-- brings the sonatype snapshot repository and signing requirement on board --> - <parent> - <groupId>org.sonatype.oss</groupId> - <artifactId>oss-parent</artifactId> - <version>7</version> - </parent> - - <!--Force UTF-8 encoding during build on all platforms--> - <properties> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <lucene.version>3.5.0</lucene.version> - <!-- 'root.basedir' is the path to the root [dspace-src] dir. It must be redefined by each child POM, - as it is used to reference the LICENSE_HEADER and *.properties file(s) in that directory. --> - <root.basedir>${basedir}</root.basedir> - </properties> - - <build> - <!-- Define Maven Plugin Settings that should be inherited to ALL submodule POMs. - (NOTE: individual POMs can override specific settings). --> - <pluginManagement> - <plugins> - <plugin> - <!-- DSpace requires Java 1.6 or higher --> - <artifactId>maven-compiler-plugin</artifactId> - <version>2.3.2</version> - <configuration> - <source>1.6</source> - <target>1.6</target> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-jar-plugin</artifactId> - <version>2.3.2</version> - <configuration> - <archive> - <manifest> - <addDefaultImplementationEntries>true</addDefaultImplementationEntries> - <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> - </manifest> - </archive> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-war-plugin</artifactId> - <!-- We'd rather this be an open-ended range of versions. - But, because of a Maven bug, we must force a specific version: - http://jira.codehaus.org/browse/MNG-2742 - Once the bug is fixed, we should put open-ended range in dspace-pom --> - <version>2.1.1</version> - <configuration> - <failOnMissingWebXml>false</failOnMissingWebXml> - <archive> - <manifest> - <addDefaultImplementationEntries>true</addDefaultImplementationEntries> - <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> - </manifest> - </archive> - </configuration> - </plugin> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-surefire-plugin</artifactId> - <version>2.6</version> - <!-- tests whose name starts by Abstract will be ignored --> - <configuration> - <excludes> - <exclude>**/Abstract*</exclude> - </excludes> - <!-- - Enable to debug Maven Surefire tests in remote proces - <debugForkedProcess>true</debugForkedProcess> - --> - <!-- required when running JMockit under Java 1.5 --> - <argLine>-javaagent:"${settings.localRepository}"/org/dspace/dependencies/jmockit/dspace-jmockit/0.999.4/dspace-jmockit-0.999.4.jar</argLine> - </configuration> - </plugin> - <plugin> - <artifactId>maven-assembly-plugin</artifactId> - <version>2.2.1</version> - </plugin> - <plugin> - <groupId>com.mycila.maven-license-plugin</groupId> - <artifactId>maven-license-plugin</artifactId> - <version>1.9.0</version> - </plugin> - </plugins> - </pluginManagement> - - <!-- These plugin settings only apply to this single POM and are not inherited - to any submodules. --> - <plugins> - <plugin> - <artifactId>maven-release-plugin</artifactId> - <version>2.3.2</version> - <configuration> - <!-- During release:perform, enable the "release" profile (see below) --> - <releaseProfiles>release</releaseProfiles> - <goals>deploy</goals> - <!-- Suggest tagging the release in SCM as "dspace-[version]" --> - <tagNameFormat>dspace-@{project.version}</tagNameFormat> - <!-- Auto-Version all modules the same as the parent module --> - <autoVersionSubmodules>true</autoVersionSubmodules> - </configuration> - </plugin> - <plugin> - <groupId>com.mycila.maven-license-plugin</groupId> - <artifactId>maven-license-plugin</artifactId> - <configuration> - <!-- License header file (can be a URL, but that's less stable if external site is down on occasion) --> - <header>${root.basedir}/LICENSE_HEADER</header> - <!--Just check headers of everything in the /src directory --> - <includes> - <include>src/**</include> - </includes> - <!--Use all default exclusions for IDE files & Maven files, see: - http://code.google.com/p/maven-license-plugin/wiki/Configuration#Default_excludes --> - <useDefaultExcludes>true</useDefaultExcludes> - <!-- Add some default DSpace exclusions not covered by <useDefaultExcludes> - Individual Maven projects may choose to override these defaults. --> - <excludes> - <exclude>**/src/test/resources/**</exclude> - <exclude>**/src/test/data/**</exclude> - <exclude>**/testEnvironment.properties</exclude> - <exclude>**/META-INF/**</exclude> - <exclude>**/robots.txt</exclude> - <exclude>**/*.LICENSE</exclude> - <exclude>**/LICENSE*</exclude> - <exclude>**/README*</exclude> - <exclude>**/readme*</exclude> - <exclude>**/.gitignore</exclude> - <exclude>**/build.properties*</exclude> - </excludes> - <mapping> - <!-- Custom DSpace file extensions which are not recognized by maven-release-plugin: - *.xmap, *.xslt, *.wsdd, *.wsdl, *.LICENSE --> - <xmap>XML_STYLE</xmap> - <xslt>XML_STYLE</xslt> - <wsdd>XML_STYLE</wsdd> - <wsdl>XML_STYLE</wsdl> - <LICENSE>TEXT</LICENSE> - </mapping> - <encoding>UTF-8</encoding> - <!-- maven-license-plugin recommends a strict check (e.g. check spaces/tabs too) --> - <strictCheck>true</strictCheck> - </configuration> - <executions> - <execution> - <id>check-headers</id> - <phase>verify</phase> - <goals> - <goal>check</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </build> - - <profiles> - - <!-- By default the main dspace.cfg file will be filtered during the build - using the "build.properties" file. This profile takes effect, unless - "-Denv" is passed in (see 'environment' profile below for more info). --> - <profile> - <id>default</id> - <activation> - <property> - <name>!env</name> - </property> - </activation> - <properties> - <!-- 'root.basedir' is the relative path to the [dspace-src] root folder --> - <filters.file>${root.basedir}/build.properties</filters.file> - </properties> - </profile> - - <!-- Users can pass in an environment flag "-Denv" to tell DSpace to use - a different properties file during its build process. - For example: "mvn package -Denv=test" would build DSpace using the - settings in "test.properties" instead of those in "build.properties" --> - <profile> - <id>environment</id> - <activation> - <property> - <name>env</name> - </property> - </activation> - <properties> - <!-- 'root.basedir' is the relative path to the [dspace-src] root folder --> - <filters.file>${root.basedir}/${env}.properties</filters.file> - </properties> - </profile> - - - <!-- This profile ensures that we ONLY generate the Unit Test Environment - if the testEnvironment.xml file is found. That way the Test Environment - is NOT built when running a 'mvn package' on a "binary" release. --> - <profile> - <id>generate-test-env</id> - <activation> - <file> - <exists>src/main/assembly/testEnvironment.xml</exists> - </file> - </activation> - <build> - <plugins> - <!-- This plugin builds the testEnvironment.zip package - based on the specifications in testEnvironment.xml --> - <plugin> - <artifactId>maven-assembly-plugin</artifactId> - <executions> - <execution> - <phase>generate-test-resources</phase> - <goals> - <goal>single</goal> - </goals> - <configuration> - <descriptors> - <descriptor>src/main/assembly/testEnvironment.xml</descriptor> - </descriptors> - <filters> - <filter>src/main/filters/testEnvironment.properties</filter> - </filters> - </configuration> - </execution> - </executions> - <inherited>false</inherited> - </plugin> - </plugins> - </build> - </profile> - - - <!-- - These profiles activate the inclusion of various modules into - the DSpace Build process. They activate automatically if the - source module is in the local file system, correctly located - relative to this file. - --> - - <!-- - Builds DSpace "Assembly & Configuration" project - --> - <profile> - <id>dspace</id> - <activation> - <file> - <exists>dspace/pom.xml</exists> - </file> - </activation> - <modules> - <module>dspace</module> - </modules> - </profile> - - <!-- - Builds central API for DSpace - --> - <profile> - <id>dspace-api</id> - <activation> - <file> - <exists>dspace-api/pom.xml</exists> - </file> - </activation> - <modules> - <module>dspace-api</module> - </modules> - </profile> - - <!-- - Builds Services for DSpace - --> - <profile> - <id>dspace-services</id> - <activation> - <file> - <exists>dspace-services/pom.xml</exists> - </file> - </activation> - <modules> - <module>dspace-services</module> - </modules> - </profile> - - <!-- - Builds XOAI Gateway WAR for DSpace - --> - <profile> - <id>dspace-oai</id> - <activation> - <file> - <exists>dspace-oai/pom.xml</exists> - </file> - </activation> - <modules> - <module>dspace-oai</module> - </modules> - </profile> - - <!-- - Builds JSPUI WAR for DSpace - --> - <profile> - <id>dspace-jspui</id> - <activation> - <file> - <exists>dspace-jspui/pom.xml</exists> - </file> - </activation> - <modules> - <module>dspace-jspui</module> - </modules> - </profile> - - - <!-- - Builds SWORD WAR for DSpace - --> - <profile> - <id>dspace-sword</id> - <activation> - <file> - <exists>dspace-sword/pom.xml</exists> - </file> - </activation> - <modules> - <module>dspace-sword</module> - </modules> - </profile> - - <!-- - Builds SWORDv2 WAR for DSpace - --> - <profile> - <id>dspace-swordv2</id> - <activation> - <file> - <exists>dspace-swordv2/pom.xml</exists> - </file> - </activation> - <modules> - <module>dspace-swordv2</module> - </modules> - </profile> - - <!-- - Builds XMLUI WAR for DSpace - --> - <profile> - <id>dspace-xmlui</id> - <activation> - <file> - <exists>dspace-xmlui/pom.xml</exists> - </file> - </activation> - <modules> - <module>dspace-xmlui</module> - </modules> - </profile> - - <!-- - Builds LNI WAR & Client for DSpace - --> - <profile> - <id>dspace-lni</id> - <activation> - <file> - <exists>dspace-lni/pom.xml</exists> - </file> - </activation> - <modules> - <module>dspace-lni</module> - <module>dspace-lni/dspace-lni-client</module> - </modules> - </profile> - - - <!-- - The 'release' profile is used by the 'maven-release-plugin' (see above) - to actually perform a DSpace software release to Maven central. - --> - <profile> - <id>release</id> - <activation> - <activeByDefault>false</activeByDefault> - </activation> - <!-- Activate all modules *except* for the 'dspace' module, - as it does not include any Java source code to release. --> - <modules> - <module>dspace-api</module> - <module>dspace-jspui</module> - <module>dspace-xmlui</module> - <module>dspace-lni</module> - <module>dspace-oai</module> - <module>dspace-sword</module> - <module>dspace-swordv2</module> - </modules> - </profile> - - <!-- Skip Unit Tests by default, but allow override on command line - by setting property "-Dmaven.test.skip=false" --> - <profile> - <id>skiptests</id> - <activation> - <!-- This profile should be active at all times, unless the user - specifies a different value for "maven.test.skip" --> - <property> - <name>!maven.test.skip</name> - </property> - </activation> - <properties> - <maven.test.skip>true</maven.test.skip> - </properties> - </profile> - </profiles> - - <!-- - Dependency management provides a means to control which - versions of dependency jars are used for compilation - and packaging into the distribution. Rather than placing - a version in your dependencies, look here first to see if - its already strongly defined in dspace-parent and dspace-api. - --> - <dependencyManagement> - <dependencies> - <!-- DSpace core and endorsed Addons --> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-api</artifactId> - <version>3.2</version> - </dependency> - <dependency> - <groupId>org.dspace.modules</groupId> - <artifactId>additions</artifactId> - <version>3.2</version> - </dependency> - - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-sword</artifactId> - <version>3.2</version> - <type>jar</type> - <classifier>classes</classifier> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-sword</artifactId> - <version>3.2</version> - <type>war</type> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-swordv2</artifactId> - <version>3.2</version> - <type>jar</type> - <classifier>classes</classifier> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-swordv2</artifactId> - <version>3.2</version> - <type>war</type> - </dependency> - - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-jspui</artifactId> - <version>3.2</version> - <type>jar</type> - <classifier>classes</classifier> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-jspui</artifactId> - <version>3.2</version> - <type>war</type> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-oai</artifactId> - <version>3.2</version> - <type>jar</type> - <classifier>classes</classifier> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-oai</artifactId> - <version>3.2</version> - <type>war</type> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-lni</artifactId> - <version>3.2</version> - <type>jar</type> - <classifier>classes</classifier> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-lni-client</artifactId> - <version>4.0-SNAPSHOT</version> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-lni</artifactId> - <version>3.2</version> - <type>war</type> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-xmlui</artifactId> - <version>3.2</version> - <type>jar</type> - <classifier>classes</classifier> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-xmlui</artifactId> - <version>3.2</version> - <type>war</type> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-services</artifactId> - <version>3.2</version> - </dependency> - <!-- DSpace Localization Packages --> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-api-lang</artifactId> - <version>[3.0.2,4.0.0)</version> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>dspace-xmlui-lang</artifactId> - <version>[3.0.2,4.0.0)</version> - <type>war</type> - </dependency> - <!-- DSpace third Party Dependencies --> - - <dependency> - <groupId>org.swordapp</groupId> - <artifactId>sword-common</artifactId> - <version>1.1</version> - </dependency> - <!-- Explicitly Specify Latest Version of Spring --> - <dependency> - <artifactId>spring-core</artifactId> - <groupId>org.springframework</groupId> - <version>3.1.1.RELEASE</version> - </dependency> - - <dependency> - <artifactId>spring-beans</artifactId> - <groupId>org.springframework</groupId> - <version>3.1.1.RELEASE</version> - </dependency> - - <dependency> - <artifactId>spring-aop</artifactId> - <groupId>org.springframework</groupId> - <version>3.1.1.RELEASE</version> - </dependency> - - <dependency> - <artifactId>spring-context</artifactId> - <groupId>org.springframework</groupId> - <version>3.1.1.RELEASE</version> - </dependency> - - <dependency> - <artifactId>spring-tx</artifactId> - <groupId>org.springframework</groupId> - <version>3.1.1.RELEASE</version> - </dependency> - - <dependency> - <artifactId>spring-jdbc</artifactId> - <groupId>org.springframework</groupId> - <version>3.1.1.RELEASE</version> - </dependency> - - <dependency> - <artifactId>spring-web</artifactId> - <groupId>org.springframework</groupId> - <version>3.1.1.RELEASE</version> - </dependency> - - <dependency> - <artifactId>spring-webmvc</artifactId> - <groupId>org.springframework</groupId> - <version>3.1.1.RELEASE</version> - </dependency> - - <dependency> - <groupId>org.apache.ant</groupId> - <artifactId>ant</artifactId> - <version>1.7.0</version> - </dependency> - <dependency> - <groupId>org.apache.lucene</groupId> - <artifactId>lucene-core</artifactId> - <version>${lucene.version}</version> - </dependency> - <dependency> - <groupId>org.apache.lucene</groupId> - <artifactId>lucene-analyzers</artifactId> - <version>${lucene.version}</version> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>handle</artifactId> - <version>6.2</version> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>jargon</artifactId> - <version>1.4.25</version> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>mets</artifactId> - <version>1.5.2</version> - </dependency> - <dependency> - <groupId>org.dspace.dependencies</groupId> - <artifactId>dspace-tm-extractors</artifactId> - <version>1.0.1</version> - </dependency> - <dependency> - <groupId>commons-cli</groupId> - <artifactId>commons-cli</artifactId> - <version>1.0</version> - </dependency> - <dependency> - <groupId>commons-codec</groupId> - <artifactId>commons-codec</artifactId> - <version>1.3</version> - </dependency> - <dependency> - <groupId>commons-collections</groupId> - <artifactId>commons-collections</artifactId> - <version>3.2</version> - <!-- <version>3.1</version> xmlui - wing --> - </dependency> - <dependency> - <groupId>commons-dbcp</groupId> - <artifactId>commons-dbcp</artifactId> - <version>1.4</version> - </dependency> - <dependency> - <groupId>commons-discovery</groupId> - <artifactId>commons-discovery</artifactId> - <version>0.2</version> - </dependency> - <dependency> - <groupId>commons-fileupload</groupId> - <artifactId>commons-fileupload</artifactId> - <version>1.2.1</version> - </dependency> - <dependency> - <groupId>commons-io</groupId> - <artifactId>commons-io</artifactId> - <version>2.3</version> - </dependency> - <dependency> - <groupId>commons-lang</groupId> - <artifactId>commons-lang</artifactId> - <version>2.6</version> - <!-- <version>2.1</version> in xmlui - wing --> - </dependency> - <dependency> - <groupId>commons-logging</groupId> - <artifactId>commons-logging</artifactId> - <version>1.1.1</version> - </dependency> - <dependency> - <groupId>commons-pool</groupId> - <artifactId>commons-pool</artifactId> - <version>1.4</version> - </dependency> - <dependency> - <groupId>commons-validator</groupId> - <artifactId>commons-validator</artifactId> - <version>1.3.1</version> - </dependency> - <dependency> - <groupId>javax.mail</groupId> - <artifactId>mail</artifactId> - <version>1.4</version> - </dependency> - <dependency> - <groupId>javax.servlet</groupId> - <artifactId>servlet-api</artifactId> - <version>2.4</version> - </dependency> - - <dependency> - <groupId>jaxen</groupId> - <artifactId>jaxen</artifactId> - <version>1.1</version> - <exclusions> - <exclusion> - <artifactId>xom</artifactId> - <groupId>xom</groupId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>jdom</groupId> - <artifactId>jdom</artifactId> - <version>1.0</version> - </dependency> - <dependency> - <groupId>log4j</groupId> - <artifactId>log4j</artifactId> - <version>1.2.14</version> - </dependency> - <dependency> - <groupId>oro</groupId> - <artifactId>oro</artifactId> - <version>2.0.8</version> - </dependency> - <dependency> - <groupId>org.apache.pdfbox</groupId> - <artifactId>pdfbox</artifactId> - <version>1.6.0</version> - </dependency> - <dependency> - <groupId>org.apache.pdfbox</groupId> - <artifactId>fontbox</artifactId> - <version>1.6.0</version> - </dependency> - <dependency> - <groupId>org.apache.pdfbox</groupId> - <artifactId>jempbox</artifactId> - <version>1.6.0</version> - </dependency> - <dependency> - <groupId>org.bouncycastle</groupId> - <artifactId>bcprov-jdk15</artifactId> - <version>1.44</version> - </dependency> - <dependency> - <groupId>org.bouncycastle</groupId> - <artifactId>bcmail-jdk15</artifactId> - <version>1.44</version> - </dependency> - <dependency> - <groupId>org.apache.poi</groupId> - <artifactId>poi</artifactId> - <version>3.6</version> - </dependency> - <dependency> - <groupId>org.apache.poi</groupId> - <artifactId>poi-scratchpad</artifactId> - <version>3.6</version> - </dependency> - <dependency> - <groupId>org.apache.poi</groupId> - <artifactId>poi-ooxml</artifactId> - <version>3.6</version> - </dependency> - <dependency> - <groupId>net.java.dev.rome</groupId> - <artifactId>rome</artifactId> - <version>1.0.0</version> - </dependency> - <dependency> - <groupId>rome</groupId> - <artifactId>opensearch</artifactId> - <version>0.1</version> - </dependency> - <dependency> - <groupId>xalan</groupId> - <artifactId>xalan</artifactId> - <version>2.7.0</version> - </dependency> - <dependency> - <groupId>xerces</groupId> - <artifactId>xercesImpl</artifactId> - <version>2.8.1</version> - <!-- <version>2.8.0</version> in xmlui --> - </dependency> - <dependency> - <groupId>xml-apis</groupId> - <artifactId>xmlParserAPIs</artifactId> - <version>2.0.2</version> - </dependency> - <dependency> - <groupId>javax.activation</groupId> - <artifactId>activation</artifactId> - <version>1.1</version> - </dependency> - - <dependency> - <groupId>wsdl4j</groupId> - <artifactId>wsdl4j</artifactId> - <version>1.5.1</version> - </dependency> - <dependency> - <groupId>javax.xml</groupId> - <artifactId>jaxrpc-api</artifactId> - <version>1.1</version> - </dependency> - <dependency> - <groupId>axis</groupId> - <artifactId>axis</artifactId> - <version>1.3</version> - </dependency> - <dependency> - <groupId>axis</groupId> - <artifactId>axis-ant</artifactId> - <version>1.3</version> - <scope>compile</scope> - </dependency> - <dependency> - <groupId>axis</groupId> - <artifactId>axis-saaj</artifactId> - <version>1.2</version> - </dependency> - <dependency> - <groupId>com.ibm.icu</groupId> - <artifactId>icu4j</artifactId> - <version>3.8</version> - </dependency> - <dependency> - <groupId>postgresql</groupId> - <artifactId>postgresql</artifactId> - <version>9.1-901-1.jdbc4</version> - </dependency> - <dependency> - <groupId>com.oracle</groupId> - <artifactId>ojdbc6</artifactId> - <version>11.2.0.2.0</version> - </dependency> - <dependency> - <groupId>com.sun.media</groupId> - <artifactId>jai_imageio</artifactId> - <version>1.0_01</version> - </dependency> - <dependency> - <groupId>javax.media</groupId> - <artifactId>jai_core</artifactId> - <version>1.1.2_01</version> - </dependency> - <dependency> - <groupId>org.dspace</groupId> - <artifactId>oclc-harvester2</artifactId> - <version>0.1.12</version> - </dependency> - <dependency> - <groupId>commons-httpclient</groupId> - <artifactId>commons-httpclient</artifactId> - <version>3.1</version> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.8.1</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.dspace.dependencies.jmockit</groupId> - <artifactId>dspace-jmockit</artifactId> - <version>0.999.4</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>com.h2database</groupId> - <artifactId>h2</artifactId> - <version>1.2.137</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.databene</groupId> - <artifactId>contiperf</artifactId> - <version>1.06</version> - <scope>test</scope> - </dependency> - </dependencies> - </dependencyManagement> - - <licenses> - <license> - <name>DuraSpace BSD License</name> - <url>https://raw.github.com/DSpace/DSpace/master/LICENSE</url> - <distribution>repo</distribution> - <comments> - A BSD 3-Clause license for the DSpace codebase. - </comments> - </license> - </licenses> - - <issueManagement> - <system>JIRA</system> - <url>https://jira.duraspace.org/browse/DS</url> - </issueManagement> - - <mailingLists> - <mailingList> - <name>DSpace Technical Users List</name> - <subscribe> - http://lists.sourceforge.net/mailman/listinfo/dspace-tech - </subscribe> - <unsubscribe> - http://lists.sourceforge.net/mailman/listinfo/dspace-tech - </unsubscribe> - <post>dspace-tech AT lists.sourceforge.net</post> - <archive> - http://sourceforge.net/mailarchive/forum.php?forum_name=dspace-tech - </archive> - </mailingList> - <mailingList> - <name>DSpace Developers List</name> - <subscribe> - http://lists.sourceforge.net/mailman/listinfo/dspace-devel - </subscribe> - <unsubscribe> - http://lists.sourceforge.net/mailman/listinfo/dspace-devel - </unsubscribe> - <post>dspace-devel AT lists.sourceforge.net</post> - <archive> - http://sourceforge.net/mailarchive/forum.php?forum_name=dspace-devel - </archive> - </mailingList> - <mailingList> - <name>DSpace General Issues List</name> - <subscribe> - http://lists.sourceforge.net/mailman/listinfo/dspace-general - </subscribe> - <unsubscribe> - http://lists.sourceforge.net/mailman/listinfo/dspace-general - </unsubscribe> - <post>dspace-general AT lists.sourceforge.net</post> - <archive> - http://sourceforge.net/mailarchive/forum.php?forum_name=dspace-general - </archive> - </mailingList> - <mailingList> - <name>DSpace SCM Commit Change-Log</name> - <subscribe> - http://lists.sourceforge.net/mailman/listinfo/dspace-changelog - </subscribe> - <unsubscribe> - http://lists.sourceforge.net/mailman/listinfo/dspace-changelog - </unsubscribe> - <post>noreply AT lists.sourceforge.net</post> - <archive> - http://sourceforge.net/mailarchive/forum.php?forum_name=dspace-changelog - </archive> - </mailingList> - </mailingLists> - - <developers> - <developer> - <name>Andrea Bollini</name> - <email>bollini at users.sourceforge.net</email> - <url>http://www.linkedin.com/in/andreabollini</url> - <organization>CILEA</organization> - <organizationUrl>http://www.cilea.it</organizationUrl> - <roles> - <role>commiter</role> - </roles> - <timezone>+1</timezone> - </developer> - <developer> - <name>Ben Bosman</name> - <email>benbosman at atmire.com</email> - <organization>@mire NV</organization> - <organizationUrl>http://www.atmire.com</organizationUrl> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Mark Diggory</name> - <email>mdiggory at atmire.com</email> - <url>http://purl.org/net/mdiggory/homepage</url> - <organization>@mire NV</organization> - <organizationUrl>http://www.atmire.com</organizationUrl> - <roles> - <role>commiter</role> - </roles> - <timezone>-8</timezone> - </developer> - <developer> - <name>Tim Donohue</name> - <email>tdonohue at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Jim Downing</name> - <email>jimdowning at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Richard Jones</name> - <email>richard-jones at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Claudia Juergen</name> - <email>cjuergen at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Stuart Lewis</name> - <email>stuart at stuartlewis.com</email> - <url>http://stuartlewis.com/</url> - <organization>University of Auckland Library</organization> - <organizationUrl>http://www.library.auckland.ac.nz/</organizationUrl> - <roles> - <role>commiter</role> - </roles> - <timezone>+12</timezone> - </developer> - <developer> - <name>Gabriela Mircea</name> - <email>mirceag at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Scott Phillips</name> - <email>scottphillips at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Richard Rodgers</name> - <email>rrodgers at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>James Rutherford</name> - <email>jrutherford at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Kim Shepherd</name> - <email>kims at waikato.ac.nz</email> - <organization>Library Consortium of New Zealand</organization> - <organizationUrl>http://www.lconz.ac.nz/</organizationUrl> - <roles> - <role>commiter</role> - </roles> - <timezone>+12</timezone> - </developer> - <developer> - <name>Larry Stone</name> - <email>lcs at mit.edu</email> - <organization>MIT Libraries</organization> - <organizationUrl>http://libraries.mit.edu</organizationUrl> - <roles> - <role>commiter</role> - </roles> - <timezone>-5</timezone> - </developer> - <developer> - <name>Robert Tansley</name> - <email>rtansley at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Graham Triggs</name> - <email>grahamtriggs at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Jeffrey Trimble</name> - <email /> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Mark H. Wood</name> - <email>mwoodiupui at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - <developer> - <name>Scott Yeadon</name> - <email>syeadon at users.sourceforge.net</email> - <roles> - <role>commiter</role> - </roles> - </developer> - </developers> - - <contributors> - <contributor> - <name>Add Your Name Here and submit a patch!</name> - <email>contributor at myu.edu</email> - <url>http://www.myu.edu/me</url> - <organization>My University</organization> - <organizationUrl>http://www.myu.edu</organizationUrl> - <roles> - <role>developer</role> - </roles> - <timezone>0</timezone> - </contributor> - <contributor> - <name>Pere Villega</name> - <email>pere.villega@gmail.com</email> - <url>http://www.perevillega.com</url> - <organization /> - <organizationUrl /> - <roles> - <role>developer</role> - </roles> - <timezone>0</timezone> - </contributor> - <contributor> - <name>Sands Fish</name> - <email>sands at mit.edu</email> - <organization>MIT Libraries</organization> - <organizationUrl>http://libraries.mit.edu</organizationUrl> - <roles> - <role>developer</role> - </roles> - <timezone>-5</timezone> - </contributor> - <contributor> - <name>Steve Swinsburg</name> - <email>steve.swinsburg@anu.edu.au</email> - <organization>The Australian National University</organization> - <organizationUrl>http://www.anu.edu.au</organizationUrl> - <roles> - <role>developer</role> - </roles> - <timezone>+10</timezone> - </contributor> - </contributors> - - <!-- - The Subversion repository location is used by Continuum to update against - when changes have occurred. This spawns a new build cycle and releases - snapshots into the snapshot repository below. - --> - <scm> - <connection>scm:git:git@github.com:DSpace/DSpace.git</connection> - <developerConnection>scm:git:git@github.com:DSpace/DSpace.git</developerConnection> - <url>git@github.com:DSpace/DSpace.git</url> - <tag>dspace-3.2</tag> - </scm> - - <!-- - Distribution Management is currently used by the Continuum - server to update snapshots it generates. This will also be used - on release to deploy release versions to the repository by the - release manager. - --> - <distributionManagement> - <!-- further distribution management is found upstream in the sonatype parent --> - </distributionManagement> - - <repositories> - <repository> - <id>sonatype-releases</id> - <name>Sonatype Releases Repository</name> - <url>http://oss.sonatype.org/content/repositories/releases/</url> - </repository> - </repositories> - -</project> diff --git a/src/main/assembly/testEnvironment.xml b/src/main/assembly/testEnvironment.xml index 504e21161547a549083d4fdab46608e8318e3370..e1455347eebabb93f42644b7c6ab8d3557d6a3cb 100644 --- a/src/main/assembly/testEnvironment.xml +++ b/src/main/assembly/testEnvironment.xml @@ -13,7 +13,7 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd"> <!-- - Package DSpace's common testing environment (configuration, etc.) + Package DSpace's common testing environment (configuration, etc.) --> <id>testEnvironment</id> <formats> @@ -29,29 +29,31 @@ <fileSet> <!-- installable DSpace files --> <directory /> <outputDirectory /> - <excludes> - <exclude>config/dspace.cfg</exclude> - </excludes> + <!-- Copy necessary DSpace subdirectories into Test environment --> <includes> - <include>bin/**/*</include> - <include>config/**/*</include> - <include>etc/**/*</include> - <include>modules/**/*</include> - <include>solr/**/*</include> + <include>bin/**</include> + <include>config/**</include> + <include>etc/**</include> + <include>solr/**</include> </includes> + <!-- Exclude specific configs (which require filtering) --> + <excludes> + <exclude>config/dspace.cfg</exclude> + <exclude>config/log4j.properties</exclude> + <exclude>config/modules/**</exclude> + </excludes> </fileSet> - <fileSet> <!-- installable DSpace files needing filtering --> + <fileSet> <!-- Copy specific configs (filtering their content) also into Test environment --> <includes> + <include>config/modules/**</include> <include>config/dspace.cfg</include> + <include>config/log4j.properties</include> </includes> <filtered>true</filtered> </fileSet> <fileSet> <!-- test data --> <directory>src/test/data/dspaceFolder</directory> <outputDirectory /> - <includes> - <include>assetstore/**/*</include> - </includes> </fileSet> </fileSets> </sources> diff --git a/src/main/filters/testEnvironment.properties b/src/main/filters/testEnvironment.properties index 182f3f645374f544fd4152c6af1e63e6b8cd40e9..5cacf0eb0dc5957b4a04c145d420a4de817ff868 100644 --- a/src/main/filters/testEnvironment.properties +++ b/src/main/filters/testEnvironment.properties @@ -32,7 +32,8 @@ default.language = en_US # Database name ("oracle", or "postgres") db.name = oracle -db.url = jdbc:h2:mem:test;MODE=Oracle +# MVCC=true tells H2 to use multi-version concurrency to avoid "timeout trying to lock" errors (http://www.h2database.com/html/advanced.html#mvcc) +db.url = jdbc:h2:mem:test;MODE=Oracle;MVCC=true db.driver = org.h2.Driver db.username = sa db.password = sa